From 32ff12e4dc360df395d093d8b72dda150d64bc34 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Mon, 5 Feb 2024 11:41:39 -0800 Subject: [PATCH] Update Paper Also included is a fix to Connection#handleDisconnection using the wrong login state for removing pending login --- gradle.properties | 2 +- ...king-ownership-of-region-by-position.patch | 2 +- patches/server/0001-Build-changes.patch | 10 +- patches/server/0003-Threaded-Regions.patch | 1291 ++++++++--------- patches/server/0004-Max-pending-logins.patch | 8 +- ...-getHandle-and-overrides-perform-thr.patch | 32 +- ...0007-Disable-mid-tick-task-execution.patch | 4 +- ...edOperationException-for-broken-APIs.patch | 4 +- ...to-be-explicitly-marked-as-Folia-sup.patch | 8 +- ...dates-in-non-loaded-or-non-owned-chu.patch | 20 +- ...access-when-waking-players-up-during.patch | 4 +- ...ition-to-player-position-on-player-d.patch | 4 +- patches/server/0018-Region-profiler.patch | 98 +- 13 files changed, 733 insertions(+), 754 deletions(-) diff --git a/gradle.properties b/gradle.properties index 2b307b8..195e60b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ group=dev.folia version=1.20.4-R0.1-SNAPSHOT mcVersion=1.20.4 -paperRef=4a98986e2881439fc018d847df2808e2f17f3a7d +paperRef=9e171ef8ff0a0ec57ebc75772fc9de578c987059 org.gradle.caching=true org.gradle.parallel=true diff --git a/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch b/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch index 3d9e255..3251639 100644 --- a/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch +++ b/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch @@ -11,7 +11,7 @@ the schedulers depending on the result of the ownership check. diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 48fab492609e0bae459d20cc2eae78b87e37ab75..00ed780f190fa1bf3c33fc093a46b4e914131e5f 100644 +index 2d53675907f411046978b0a234c0b6f33c909973..15252f744d60408a816dba1c0ca0c7104236ae6f 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -2837,6 +2837,14 @@ public final class Bukkit { diff --git a/patches/server/0001-Build-changes.patch b/patches/server/0001-Build-changes.patch index 31bc62c..b047cd0 100644 --- a/patches/server/0001-Build-changes.patch +++ b/patches/server/0001-Build-changes.patch @@ -93,20 +93,20 @@ index 9d687da5bdf398bb3f6c84cdf1249a7213d09f2e..e2f704c115fd6e00960bb56bb0779f11 ).openBufferedStream()) { JsonObject json = new Gson().fromJson(reader, JsonObject.class); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 24430f9bf1b641a84e79b4b9b2e0ac5d16681ada..c7498b4ec41f0ae56530b948bd04c892a0f6d4a7 100644 +index d06185566b447c432d4dc2e3ba04d121bcdbc71b..680919045310be7e50e2d503a23d265f2e9b2bc6 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1852,7 +1852,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // Spigot - Spigot > // CraftBukkit - cb > vanilla! -+ return "Folia"; // Folia - Folia > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! +- return "Paper"; // Paper ++ return "Folia"; // Paper // Folia - Folia } 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 eb617d659c701e512aac8a1ff822c147b69d3a3b..3b133cd19c0cceeb78f58d36de817b699cc59884 100644 +index 4df3b94c8126f00188f5e125757411a0359728fa..825e7abebd6eb898198106ca6e783ec462e64173 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 diff --git a/patches/server/0003-Threaded-Regions.patch b/patches/server/0003-Threaded-Regions.patch index 472d7d5..4e53bfe 100644 --- a/patches/server/0003-Threaded-Regions.patch +++ b/patches/server/0003-Threaded-Regions.patch @@ -677,7 +677,7 @@ index 0000000000000000000000000000000000000000..7869cc177c95e26dd9e1d3db5b50e996 + +} diff --git a/src/main/java/ca/spottedleaf/concurrentutil/map/SWMRLong2ObjectHashTable.java b/src/main/java/ca/spottedleaf/concurrentutil/map/SWMRLong2ObjectHashTable.java -index 1e98f778ffa0a7bb00ebccaaa8bde075183e41f0..aebe82cbe8bc20e5f4260a871d7b620e5092b2c9 100644 +index 94fca3c9b31ca4e40688209e419e93320b0f7c34..fea1244ee156e0f562f295f31e3da288774d2f5c 100644 --- a/src/main/java/ca/spottedleaf/concurrentutil/map/SWMRLong2ObjectHashTable.java +++ b/src/main/java/ca/spottedleaf/concurrentutil/map/SWMRLong2ObjectHashTable.java @@ -534,6 +534,44 @@ public class SWMRLong2ObjectHashTable { @@ -1352,10 +1352,10 @@ index 0000000000000000000000000000000000000000..63688716244066581d5b505703576e33 + private TimeUtil() {} +} diff --git a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -index 22a2547810d0c029f29685faddf7ac21cde2df0b..e36b4053eb2676e934b8c9c401bf58cfa7dd969c 100644 +index fa062e6543e8a0377e3d4715996955dba005ee80..6284262d8cc2a07ad43eb46c888ca647613c926a 100644 --- a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java +++ b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -@@ -832,14 +832,14 @@ public class RedstoneWireTurbo { +@@ -833,14 +833,14 @@ public class RedstoneWireTurbo { j = getMaxCurrentStrength(upd, j); int l = 0; @@ -1454,10 +1454,10 @@ index 23432eea862c6df716d7726a32da3a0612a3fb77..f59e8bb72c5233f26a8a0d506ac64bb3 } } diff --git a/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java b/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java -index 95e5073a68e4dd38b70e8268daf2160922c3a12f..19349637e4a38e697debe6d18ab8b759ede0359e 100644 +index cbeaadaecf816070b3a37938c8e683180939afc4..f1991bbce762df848726d2f0b6f1d01765be9ba5 100644 --- a/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java +++ b/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java -@@ -92,6 +92,9 @@ public final class ChunkSystem { +@@ -82,6 +82,9 @@ public final class ChunkSystem { for (int index = 0, len = chunkMap.regionManagers.size(); index < len; ++index) { chunkMap.regionManagers.get(index).addChunk(holder.getPos().x, holder.getPos().z); } @@ -1467,7 +1467,7 @@ index 95e5073a68e4dd38b70e8268daf2160922c3a12f..19349637e4a38e697debe6d18ab8b759 } public static void onChunkHolderDelete(final ServerLevel level, final ChunkHolder holder) { -@@ -99,34 +102,39 @@ public final class ChunkSystem { +@@ -89,34 +92,39 @@ public final class ChunkSystem { for (int index = 0, len = chunkMap.regionManagers.size(); index < len; ++index) { chunkMap.regionManagers.get(index).removeChunk(holder.getPos().x, holder.getPos().z); } @@ -2421,10 +2421,10 @@ index 385ca2c1022e0985550a5cc2bbff953f1aa33f5c..f7a66f54a450f1a46e9d0a138544e974 public int maxAutoSaveChunksPerTick = 24; public int fixedChunkInhabitedTime = -1; diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java -index 04efba1517e2bde8ecced31ab2eb669b2e84a28c..13769aec38766665787eb60e4d5bca8345b3c4ee 100644 +index eeea1e6f7b1ed64567a3f90d8eb2e2cfd53e5912..ae9892b7d5233e32a9d81fdd3978b608bb55ea14 100644 --- a/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java +++ b/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java -@@ -244,12 +244,7 @@ class PaperPluginInstanceManager { +@@ -242,12 +242,7 @@ class PaperPluginInstanceManager { + pluginName + " (Is it up to date?)", ex, plugin); // Paper } @@ -2440,7 +2440,7 @@ index 04efba1517e2bde8ecced31ab2eb669b2e84a28c..13769aec38766665787eb60e4d5bca83 try { diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java b/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java new file mode 100644 -index 0000000000000000000000000000000000000000..2b48833023771fa965f131890ade98e9da3f5976 +index 0000000000000000000000000000000000000000..3f3fd8b1881106f893ffb677272e50d77cbb6626 --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java @@ -0,0 +1,175 @@ @@ -2497,7 +2497,7 @@ index 0000000000000000000000000000000000000000..2b48833023771fa965f131890ade98e9 + + private void saveLevelData(final ServerLevel world) { + try { -+ world.saveLevelData(); ++ world.saveLevelData(false); + } catch (final Throwable thr) { + LOGGER.error("Failed to save level data for " + world.getWorld().getName(), thr); + } @@ -8855,10 +8855,10 @@ index 413e4b6da027876dbbe8eb78f2568a440f431547..3a7dbcb9964723b8ed5e6b0a1ee42679 throw new RuntimeException(); } diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java -index 200ed770b57e1a9240abf0473968d4b85cbefe3c..1f0ec6add54b7503415d5f4141fe2b6046f1ec69 100644 +index 850f75172e9efa72cabb8e5bd124b96a0b1a945f..878306271d4af280c7a086d1839c446a01da1ad6 100644 --- a/src/main/java/io/papermc/paper/util/MCUtil.java +++ b/src/main/java/io/papermc/paper/util/MCUtil.java -@@ -335,6 +335,7 @@ public final class MCUtil { +@@ -334,6 +334,7 @@ public final class MCUtil { */ public static void ensureMain(String reason, Runnable run) { if (!isMainThread()) { @@ -8866,7 +8866,7 @@ index 200ed770b57e1a9240abf0473968d4b85cbefe3c..1f0ec6add54b7503415d5f4141fe2b60 if (reason != null) { MinecraftServer.LOGGER.warn("Asynchronous " + reason + "!", new IllegalStateException()); } -@@ -475,6 +476,30 @@ public final class MCUtil { +@@ -474,6 +475,30 @@ public final class MCUtil { return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()); } @@ -8898,7 +8898,7 @@ index 200ed770b57e1a9240abf0473968d4b85cbefe3c..1f0ec6add54b7503415d5f4141fe2b60 * Converts an NMS entity's current location to a Bukkit Location * @param entity diff --git a/src/main/java/io/papermc/paper/util/TickThread.java b/src/main/java/io/papermc/paper/util/TickThread.java -index f9063e2282f89e97a378f06822cde0a64ab03f9a..c6b3c747d4c9792c3b690af4d45b13d2b05039ee 100644 +index bdaf062f9b66ceab303a0807eca301342886a8ea..61fc8d4a52d6fb29b09eefd7b0fa880c0cf97849 100644 --- a/src/main/java/io/papermc/paper/util/TickThread.java +++ b/src/main/java/io/papermc/paper/util/TickThread.java @@ -1,5 +1,11 @@ @@ -9342,7 +9342,7 @@ index 0000000000000000000000000000000000000000..cf9b66afc1762dbe2c625f09f9e804ca + } +} diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java -index 6978d0a9abc9cc5870ac5ee6308f2e9949b42fde..a5b9cc88a80b4b920788bd7faf5a300286c86ab4 100644 +index f341813e9713e39bfe142ca34b751de3d8efd25b..7793797dfae906e5181dff517a7d04c95e869a37 100644 --- a/src/main/java/net/minecraft/commands/CommandSourceStack.java +++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java @@ -68,7 +68,7 @@ public class CommandSourceStack implements ExecutionCommandSource(player.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper + // Paper start - Perf: Async command map building + new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(player.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper - Brigadier API - net.minecraft.server.MinecraftServer.getServer().execute(() -> { - runSync(player, bukkit, rootcommandnode); - }); + // Folia start - region threading + // ignore if retired + player.getBukkitEntity().taskScheduler.schedule((updatedPlayer) -> { -+ runSync((ServerPlayer)updatedPlayer, bukkit, rootcommandnode); ++ runSync((ServerPlayer)updatedPlayer, bukkit, rootcommandnode); + }, null, 1L); + // Folia end - region threading } @@ -9493,7 +9493,7 @@ index 6df0db8b4cdab23494ea34236949ece4989110a3..2fd670d941bd575f99def28732ffee29 } diff --git a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -index 6c78d90e73b47b62c4052727730850d4b67a9cd2..22bd34cf8994082e1b33d58f21ae86219d642b33 100644 +index f28705547a62da790f5df071400986aacba39367..4bbed8e057a32ce22d768392cebc27110cf4338b 100644 --- a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java @@ -85,7 +85,7 @@ public class DefaultDispenseItemBehavior implements DispenseItemBehavior { @@ -9701,7 +9701,7 @@ index 6f2adf2334e35e8a617a4ced0c1af2abf32bbd8d..de323c881b6d54061f7fef2b56658beb } diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 4fe69c47eefbdf01b555e1471c8db3e7be17d306..43f7097599dc82cd8e9fedebe4ae2e83be068c5c 100644 +index 4716f8bd8a64d4f20f0d5957c1e7fabf63020f43..14c82f0903d08e289cec49d095af986b83b500aa 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java @@ -84,7 +84,7 @@ public class Connection extends SimpleChannelInboundHandler> { @@ -9817,8 +9817,8 @@ index 4fe69c47eefbdf01b555e1471c8db3e7be17d306..43f7097599dc82cd8e9fedebe4ae2e83 - } - return false; + return this.processQueue(); // Folia - region threading - connection fixes - } - ++ } ++ + // Folia start - region threading - connection fixes + // allow only one thread to be flushing the queue at once to ensure packets are written in the order they are sent + // into the queue @@ -9826,8 +9826,8 @@ index 4fe69c47eefbdf01b555e1471c8db3e7be17d306..43f7097599dc82cd8e9fedebe4ae2e83 + + private static boolean canWrite(WrappedConsumer queued) { + return queued != null && (!(queued instanceof PacketSendAction packet) || packet.packet.isReady()); -+ } -+ + } + + private boolean canWritePackets() { + return canWrite(this.pendingActions.peek()); + } @@ -9897,13 +9897,14 @@ index 4fe69c47eefbdf01b555e1471c8db3e7be17d306..43f7097599dc82cd8e9fedebe4ae2e83 // Paper end - Optimize network @@ -571,21 +607,41 @@ public class Connection extends SimpleChannelInboundHandler> { - private static int currTick; // Paper + private static int currTick; // Paper - Buffer joins to world public void tick() { this.flushQueue(); -- // Paper start +- // Paper start - Buffer joins to world - if (Connection.currTick != net.minecraft.server.MinecraftServer.currentTick) { - Connection.currTick = net.minecraft.server.MinecraftServer.currentTick; - Connection.joinAttemptsThisTick = 0; ++ // Folia - this is broken + // Folia start - region threading + // handle disconnect requests, but only after flushQueue() + DisconnectReq disconnectReq; @@ -9925,20 +9926,19 @@ index 4fe69c47eefbdf01b555e1471c8db3e7be17d306..43f7097599dc82cd8e9fedebe4ae2e83 + return; + } } -- // Paper end +- // Paper end - Buffer joins to world + if (!this.isConnected()) { + // disconnected from above + this.handleDisconnection(); + return; + } + // Folia end - region threading -+ // Folia - this is broken PacketListener packetlistener = this.packetListener; if (packetlistener instanceof TickablePacketListener) { TickablePacketListener tickablepacketlistener = (TickablePacketListener) packetlistener; - // Paper start - limit the number of joins which can be processed each tick + // Paper start - Buffer joins to world - if (!(this.packetListener instanceof net.minecraft.server.network.ServerLoginPacketListenerImpl loginPacketListener) - || loginPacketListener.state != net.minecraft.server.network.ServerLoginPacketListenerImpl.State.VERIFYING - || Connection.joinAttemptsThisTick++ < MAX_PER_TICK) { @@ -9947,7 +9947,7 @@ index 4fe69c47eefbdf01b555e1471c8db3e7be17d306..43f7097599dc82cd8e9fedebe4ae2e83 net.minecraft.network.protocol.PacketUtils.packetProcessing.push(this.packetListener); try { // Paper end - detailed watchdog information @@ -597,7 +653,7 @@ public class Connection extends SimpleChannelInboundHandler> { - // Paper end + // Paper end - Buffer joins to world } - if (!this.isConnected() && !this.disconnectionHandled) { @@ -9976,10 +9976,10 @@ index 4fe69c47eefbdf01b555e1471c8db3e7be17d306..43f7097599dc82cd8e9fedebe4ae2e83 PacketListener packetlistener = this.getPacketListener(); PacketListener packetlistener1 = packetlistener != null ? packetlistener : this.disconnectListener; -@@ -856,6 +913,21 @@ public class Connection extends SimpleChannelInboundHandler> { - ((java.net.InetSocketAddress)address).getAddress(), false).callEvent(); +@@ -857,6 +914,22 @@ public class Connection extends SimpleChannelInboundHandler> { } } + // Paper end - Add PlayerConnectionCloseEvent + // Folia start - region threading + if (packetlistener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl commonPacketListener) { + net.minecraft.server.MinecraftServer.getServer().getPlayerList().removeConnection( @@ -9987,7 +9987,7 @@ index 4fe69c47eefbdf01b555e1471c8db3e7be17d306..43f7097599dc82cd8e9fedebe4ae2e83 + commonPacketListener.getOwner().getId(), this + ); + } else if (packetlistener instanceof net.minecraft.server.network.ServerLoginPacketListenerImpl loginPacketListener) { -+ if (loginPacketListener.state.ordinal() >= net.minecraft.server.network.ServerLoginPacketListenerImpl.State.VERIFYING.ordinal()) { ++ if (loginPacketListener.state.ordinal() >= net.minecraft.server.network.ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING.ordinal()) { + net.minecraft.server.MinecraftServer.getServer().getPlayerList().removeConnection( + loginPacketListener.authenticatedProfile.getName(), + loginPacketListener.authenticatedProfile.getId(), this @@ -9995,10 +9995,11 @@ index 4fe69c47eefbdf01b555e1471c8db3e7be17d306..43f7097599dc82cd8e9fedebe4ae2e83 + } + } + // Folia end - region threading - // Paper end ++ // Paper end } -@@ -877,15 +949,25 @@ public class Connection extends SimpleChannelInboundHandler> { + } +@@ -877,15 +950,25 @@ public class Connection extends SimpleChannelInboundHandler> { // Paper start - Optimize network public void clearPacketQueue() { final net.minecraft.server.level.ServerPlayer player = getPlayer(); @@ -10067,7 +10068,7 @@ index 3e2d5dcd62775b6ed7c0ce0ba51a71b635b1d644..98fb69a9adeb6eaab199aec127692acb // CraftBukkit start - SPIGOT-5477, MC-142590 } else if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) listener).processedDisconnect)) { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index c7498b4ec41f0ae56530b948bd04c892a0f6d4a7..301ff715b89abbebda83af1e15f8d5d15097002f 100644 +index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d742a4dc0ac 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -203,7 +203,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; public Commands vanillaCommandDispatcher; -@@ -306,7 +305,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); Thread thread = new io.papermc.paper.util.TickThread(() -> { // Paper - rewrite chunk system -@@ -350,7 +377,7 @@ 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()) { - continue; - } @@ -10690,7 +10692,7 @@ index c7498b4ec41f0ae56530b948bd04c892a0f6d4a7..301ff715b89abbebda83af1e15f8d5d1 MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot // Paper this.profiler.popPush("levels"); //Iterator iterator = this.getAllLevels().iterator(); // Paper - Throw exception on world create while being ticked; moved down -@@ -1657,7 +1741,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper -- 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.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 + // Folia - region threading this.profiler.push(() -> { return worldserver + " " + worldserver.dimension().location(); -@@ -1708,7 +1789,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop this.level.spigotConfig.viewDistance) ? (byte) this.level.spigotConfig.viewDistance : chunkRange; chunkRange = (chunkRange > 8) ? 8 : chunkRange; -@@ -938,7 +901,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -924,7 +887,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (!this.distanceManager.hasPlayersNearby(chunkcoordintpair.toLong())) { return false; } else { @@ -12453,7 +12458,7 @@ index 673f0d1ee4e4228a52c07fc1b570822257e59300..bc1c0ce0a29654172afdfc30baee1902 ServerPlayer entityplayer; -@@ -970,7 +933,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -956,7 +919,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return List.of(); } else { Builder builder = ImmutableList.builder(); @@ -12462,7 +12467,7 @@ index 673f0d1ee4e4228a52c07fc1b570822257e59300..bc1c0ce0a29654172afdfc30baee1902 while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); -@@ -999,25 +962,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -985,25 +948,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } void updatePlayerStatus(ServerPlayer player, boolean added) { @@ -12492,7 +12497,7 @@ index 673f0d1ee4e4228a52c07fc1b570822257e59300..bc1c0ce0a29654172afdfc30baee1902 this.removePlayerFromDistanceMaps(player); // Paper - distance maps // Paper - handled by player chunk loader -@@ -1032,31 +989,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1018,31 +975,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } public void move(ServerPlayer player) { @@ -12528,7 +12533,7 @@ index 673f0d1ee4e4228a52c07fc1b570822257e59300..bc1c0ce0a29654172afdfc30baee1902 // Paper - replaced by PlayerChunkLoader } -@@ -1087,9 +1026,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1073,9 +1012,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public void addEntity(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot // Paper start - ignore and warn about illegal addEntity calls instead of crashing server @@ -12539,8 +12544,8 @@ index 673f0d1ee4e4228a52c07fc1b570822257e59300..bc1c0ce0a29654172afdfc30baee1902 + + ": " + entity + (entity.tracker != null ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable()); return; } - if (entity instanceof ServerPlayer && ((ServerPlayer) entity).supressTrackerForLogin) return; // Delay adding to tracker until after list packets -@@ -1102,27 +1041,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end - ignore and warn about illegal addEntity calls instead of crashing server +@@ -1088,27 +1027,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (i != 0) { int j = entitytypes.updateInterval(); @@ -12576,7 +12581,7 @@ index 673f0d1ee4e4228a52c07fc1b570822257e59300..bc1c0ce0a29654172afdfc30baee1902 } } -@@ -1136,16 +1073,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1122,16 +1059,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider ServerPlayer entityplayer = (ServerPlayer) entity; this.updatePlayerStatus(entityplayer, false); @@ -12600,7 +12605,7 @@ index 673f0d1ee4e4228a52c07fc1b570822257e59300..bc1c0ce0a29654172afdfc30baee1902 if (playerchunkmap_entitytracker1 != null) { playerchunkmap_entitytracker1.broadcastRemoved(); -@@ -1153,82 +1090,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1139,82 +1076,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider entity.tracker = null; // Paper - We're no longer tracked } @@ -12705,7 +12710,7 @@ index 673f0d1ee4e4228a52c07fc1b570822257e59300..bc1c0ce0a29654172afdfc30baee1902 if (playerchunkmap_entitytracker != null) { playerchunkmap_entitytracker.broadcast(packet); -@@ -1237,7 +1129,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1223,7 +1115,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } protected void broadcastAndSend(Entity entity, Packet packet) { @@ -12714,7 +12719,7 @@ index 673f0d1ee4e4228a52c07fc1b570822257e59300..bc1c0ce0a29654172afdfc30baee1902 if (playerchunkmap_entitytracker != null) { playerchunkmap_entitytracker.broadcastAndSend(packet); -@@ -1414,6 +1306,78 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1400,6 +1292,78 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } } @@ -12793,7 +12798,7 @@ index 673f0d1ee4e4228a52c07fc1b570822257e59300..bc1c0ce0a29654172afdfc30baee1902 public void updatePlayer(ServerPlayer player) { org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot -@@ -1437,9 +1401,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1423,9 +1387,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } } // Paper end - Configurable entity tracking range by Y @@ -12810,7 +12815,7 @@ index 673f0d1ee4e4228a52c07fc1b570822257e59300..bc1c0ce0a29654172afdfc30baee1902 } // CraftBukkit end diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index 328aba4a638f6147eb0c521cc464163ad7bd5840..27f0306a47397b07c44d1d46dd70e00e84611841 100644 +index 7c425ac50c83757b66a2178bc19d4c920b82f12f..584ee79355f1825b42bc98e508a3678b22886831 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java +++ b/src/main/java/net/minecraft/server/level/DistanceManager.java @@ -191,11 +191,11 @@ public abstract class DistanceManager { @@ -12828,10 +12833,10 @@ index 328aba4a638f6147eb0c521cc464163ad7bd5840..27f0306a47397b07c44d1d46dd70e00e public String getDebugStatus() { diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4dcb0fa1e1 100644 +index 366c0c9b45a819f7f94ebe3e49b8ab7f9edf9ce7..d532043f33825ce2971d9e53f290cdead22d6916 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -58,73 +58,42 @@ public class ServerChunkCache extends ChunkSource { +@@ -58,23 +58,20 @@ public class ServerChunkCache extends ChunkSource { public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; public final ChunkMap chunkMap; private final DimensionDataStorage dataStorage; @@ -12848,16 +12853,19 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d - private NaturalSpawner.SpawnState lastSpawnState; + // Folia - moved to regionised world data // Paper start -- final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); +- public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet tickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true); +- public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet entityTickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true); ++ // Folia - region threading - move to regionised world data + final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); - final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap loadedChunkMap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(8192, 0.5f); -+ // Folia - region threading + final ca.spottedleaf.concurrentutil.map.SWMRLong2ObjectHashTable loadedChunkMap = new ca.spottedleaf.concurrentutil.map.SWMRLong2ObjectHashTable<>(8192, 0.5f); // Folia - region threading - + final java.util.concurrent.atomic.AtomicLong chunkFutureAwaitCounter = new java.util.concurrent.atomic.AtomicLong(); // Paper - chunk system rewrite - private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4]; + // Folia - region threading + // Paper end - private static int getChunkCacheKey(int x, int z) { - return x & 3 | ((z & 3) << 2); + public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory) { +@@ -107,52 +104,23 @@ public class ServerChunkCache extends ChunkSource { } public void addLoadedChunk(LevelChunk chunk) { @@ -12868,12 +12876,12 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d - } finally { - this.loadedChunkMapSeqLock.releaseWrite(); - } -+ } // Folia - region threading - +- - // rewrite cache if we have to - // we do this since we also cache null chunks - int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -- ++ } // Folia - region threading + - this.lastLoadedChunks[cacheKey] = chunk; + // Folia - region threading } @@ -12886,12 +12894,12 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d - } finally { - this.loadedChunkMapSeqLock.releaseWrite(); - } -+ } // Folia - region threading - +- - // rewrite cache if we have to - // we do this since we also cache null chunks - int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -- ++ } // Folia - region threading + - LevelChunk cachedChunk = this.lastLoadedChunks[cacheKey]; - if (cachedChunk != null && cachedChunk.coordinateKey == chunk.coordinateKey) { - this.lastLoadedChunks[cacheKey] = null; @@ -12917,17 +12925,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d } public final LevelChunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { -@@ -161,8 +130,7 @@ public class ServerChunkCache extends ChunkSource { - this.distanceManager.removeTicket(ticketType, chunkPos, ticketLevel, identifier); - } - -- public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet tickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true); -- public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet entityTickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true); -+ // Folia - region threading - // Paper end - - public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory) { -@@ -236,26 +204,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -197,26 +165,7 @@ public class ServerChunkCache extends ChunkSource { public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) { long k = ChunkPos.asLong(x, z); @@ -12955,7 +12953,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d } // Paper end -@@ -329,6 +278,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -314,6 +263,7 @@ public class ServerChunkCache extends ChunkSource { } public CompletableFuture> getChunkFuture(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { @@ -12963,7 +12961,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d boolean flag1 = io.papermc.paper.util.TickThread.isTickThread(); // Paper - rewrite chunk system CompletableFuture completablefuture; -@@ -507,10 +457,11 @@ public class ServerChunkCache extends ChunkSource { +@@ -499,10 +449,11 @@ public class ServerChunkCache extends ChunkSource { } private void tickChunks() { @@ -12978,7 +12976,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d if (!this.level.isDebug()) { ProfilerFiller gameprofilerfiller = this.level.getProfiler(); -@@ -530,7 +481,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -522,7 +473,7 @@ public class ServerChunkCache extends ChunkSource { NaturalSpawner.SpawnState spawnercreature_d; // moved down if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled // re-set mob counts @@ -12987,7 +12985,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d // Paper start - per player mob spawning backoff for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) { player.mobCounts[ii] = 0; -@@ -543,22 +494,22 @@ public class ServerChunkCache extends ChunkSource { +@@ -535,22 +486,22 @@ public class ServerChunkCache extends ChunkSource { } // Paper end - per player mob spawning backoff } @@ -12997,7 +12995,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d - spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); + spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); // Folia - region threading - note: function only cares about loaded entities, doesn't need all } - // Paper end + // Paper end - Optional per player mob spawns this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings - this.lastSpawnState = spawnercreature_d; @@ -13016,7 +13014,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d player.playerNaturallySpawnedEvent = null; player.lastEntitySpawnRadiusSquared = -1.0; continue; -@@ -574,7 +525,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -566,7 +517,7 @@ public class ServerChunkCache extends ChunkSource { com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange); event.callEvent(); if (event.isCancelled() || event.getSpawnRadius() < 0) { @@ -13025,7 +13023,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d player.playerNaturallySpawnedEvent = null; player.lastEntitySpawnRadiusSquared = -1.0; continue; -@@ -584,13 +535,13 @@ public class ServerChunkCache extends ChunkSource { +@@ -576,13 +527,13 @@ public class ServerChunkCache extends ChunkSource { int chunkX = io.papermc.paper.util.CoordinateUtils.getChunkCoordinate(player.getX()); int chunkZ = io.papermc.paper.util.CoordinateUtils.getChunkCoordinate(player.getZ()); @@ -13041,7 +13039,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d // Paper - optimise chunk tick iteration int chunksTicked = 0; // Paper -@@ -598,10 +549,10 @@ public class ServerChunkCache extends ChunkSource { +@@ -590,10 +541,10 @@ public class ServerChunkCache extends ChunkSource { io.papermc.paper.util.player.NearbyPlayers nearbyPlayers = this.chunkMap.getNearbyPlayers(); // Paper - optimise chunk tick iteration Iterator chunkIterator; if (this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { @@ -13055,7 +13053,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d while (chunkIterator.hasNext()) { shuffled.add(chunkIterator.next()); } -@@ -671,17 +622,21 @@ public class ServerChunkCache extends ChunkSource { +@@ -663,17 +614,21 @@ public class ServerChunkCache extends ChunkSource { // Paper - optimise chunk tick iteration this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing // Paper start - optimise chunk tick iteration @@ -13085,7 +13083,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d // Paper end - optimise chunk tick iteration this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing // Paper - optimise chunk tick iteration -@@ -744,14 +699,19 @@ public class ServerChunkCache extends ChunkSource { +@@ -736,14 +691,19 @@ public class ServerChunkCache extends ChunkSource { @Override public void onLightUpdate(LightLayer type, SectionPos pos) { @@ -13107,7 +13105,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d } public void addRegionTicket(TicketType ticketType, ChunkPos pos, int radius, T argument) { -@@ -823,7 +783,8 @@ public class ServerChunkCache extends ChunkSource { +@@ -815,7 +775,8 @@ public class ServerChunkCache extends ChunkSource { @Nullable @VisibleForDebug public NaturalSpawner.SpawnState getLastSpawnState() { @@ -13117,7 +13115,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d } public void removeTicketsOnClosing() { -@@ -856,8 +817,43 @@ public class ServerChunkCache extends ChunkSource { +@@ -848,8 +809,43 @@ public class ServerChunkCache extends ChunkSource { return ServerChunkCache.this.mainThread; } @@ -13161,7 +13159,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d ServerChunkCache.this.level.getProfiler().incrementCounter("runTask"); super.doRunTask(task); } -@@ -865,10 +861,15 @@ public class ServerChunkCache extends ChunkSource { +@@ -857,10 +853,15 @@ public class ServerChunkCache extends ChunkSource { @Override // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task public boolean pollTask() { @@ -13179,7 +13177,7 @@ index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..a21cc9c7d5981c742f379affe9c1ef4d } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69b1593795 100644 +index 6934e9dac0d69c043b73b7c46d59f2d39b37c67f..172f8e1abb036669b787fde570da8d326d2ab262 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -193,36 +193,35 @@ public class ServerLevel extends Level implements WorldGenLevel { @@ -13222,13 +13220,13 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 // CraftBukkit start public final LevelStorageSource.LevelStorageAccess convertable; public final UUID uuid; -- public boolean hasPhysicsEvent = true; // Paper -- public boolean hasEntityMoveEvent = false; // Paper - Add EntityMoveEvent -+ // Folia - region threading +- public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent +- public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent ++ // Folia - region threading - move to regionised world data private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current) - public static Throwable getAddToWorldStackTrace(Entity entity) { - final Throwable thr = new Throwable(entity + " Added to world at " + new java.util.Date()); -@@ -258,6 +257,36 @@ public class ServerLevel extends Level implements WorldGenLevel { + + public LevelChunk getChunkIfLoaded(int x, int z) { +@@ -253,6 +252,36 @@ public class ServerLevel extends Level implements WorldGenLevel { ServerChunkCache chunkProvider = this.getChunkSource(); @@ -13265,7 +13263,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 for (int cx = minChunkX; cx <= maxChunkX; ++cx) { for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) { if (chunkProvider.getChunkAtIfLoadedImmediately(cx, cz) == null) { -@@ -516,7 +545,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -511,7 +540,7 @@ public class ServerLevel extends Level implements WorldGenLevel { public final int getRegionChunkShift() { // placeholder for folia @@ -13274,9 +13272,9 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } // Paper end - rewrite chunk system -@@ -571,14 +600,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -566,14 +595,14 @@ public class ServerLevel extends Level implements WorldGenLevel { } - // Paper end + // Paper end - optimise getPlayerByUUID // Paper start - lag compensation - private long lagCompensationTick = net.minecraft.server.MinecraftServer.SERVER_INIT; + // Folia - region threading @@ -13292,7 +13290,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } // Paper end - lag compensation // Paper start - optimise nearby player retrieval -@@ -625,7 +654,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -620,7 +649,7 @@ public class ServerLevel extends Level implements WorldGenLevel { ServerPlayer nearest = null; double nearestDist = Double.MAX_VALUE; @@ -13301,7 +13299,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 double dist = player.distanceToSqr(x, y, z); if (dist >= nearestDist) { continue; -@@ -681,7 +710,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -676,7 +705,7 @@ public class ServerLevel extends Level implements WorldGenLevel { return nearest; } else { @@ -13310,7 +13308,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } } -@@ -690,6 +719,58 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -685,6 +714,58 @@ public class ServerLevel extends Level implements WorldGenLevel { return this.getNearestPlayer(targetPredicate, null, x, y, z); } // Paper end - optimise nearby player retrieval @@ -13369,7 +13367,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 // Add env and gen to constructor, IWorldDataServer -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { -@@ -702,13 +783,13 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -697,13 +778,13 @@ public class ServerLevel extends Level implements WorldGenLevel { this.convertable = convertable_conversionsession; this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); // CraftBukkit end @@ -13389,7 +13387,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 this.dragonParts = new Int2ObjectOpenHashMap(); this.tickTime = flag1; this.server = minecraftserver; -@@ -747,7 +828,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -742,7 +823,7 @@ public class ServerLevel extends Level implements WorldGenLevel { }); this.chunkSource.getGeneratorState().ensureStructuresGenerated(); this.portalForcer = new PortalForcer(this); @@ -13398,7 +13396,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 this.prepareWeather(); this.getWorldBorder().setAbsoluteMaxSize(minecraftserver.getAbsoluteMaxWorldSize()); this.raids = (Raids) this.getDataStorage().computeIfAbsent(Raids.factory(this), Raids.getFileId(this.dimensionTypeRegistration())); -@@ -774,7 +855,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -769,7 +850,14 @@ 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 @@ -13413,7 +13411,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 // Paper start @Override -@@ -807,44 +895,27 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -802,44 +890,27 @@ public class ServerLevel extends Level implements WorldGenLevel { return this.structureManager; } @@ -13450,7 +13448,8 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 - this.setDayTime(this.getDayTime() + event.getSkipAmount()); - } - } -- ++ if (region == null) this.tickSleep(); // Folia - region threading + - if (!event.isCancelled()) { - this.wakeUpAllPlayers(); - } @@ -13459,14 +13458,13 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 - this.resetWeatherCycle(); - } - } -+ if (region == null) this.tickSleep(); // Folia - region threading - +- - this.updateSkyBrightness(); + if (region == null) this.updateSkyBrightness(); // Folia - region threading if (flag) { this.tickTime(); } -@@ -852,11 +923,11 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -847,11 +918,11 @@ public class ServerLevel extends Level implements WorldGenLevel { gameprofilerfiller.popPush("tickPending"); this.timings.scheduledBlocks.startTiming(); // Paper if (!this.isDebug() && flag) { @@ -13481,7 +13479,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 gameprofilerfiller.pop(); } this.timings.scheduledBlocks.stopTiming(); // Paper -@@ -879,7 +950,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -874,7 +945,7 @@ public class ServerLevel extends Level implements WorldGenLevel { this.timings.doSounds.stopTiming(); // Spigot } @@ -13490,7 +13488,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 gameprofilerfiller.pop(); boolean flag1 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players -@@ -891,20 +962,30 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -886,20 +957,30 @@ public class ServerLevel extends Level implements WorldGenLevel { gameprofilerfiller.push("entities"); this.timings.tickEntities.startTiming(); // Spigot if (this.dragonFight != null && flag) { @@ -13522,7 +13520,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 gameprofilerfiller.pop(); if (true || this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { // Paper - now always true if in the ticking list Entity entity1 = entity.getVehicle(); -@@ -935,6 +1016,31 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -930,6 +1011,31 @@ public class ServerLevel extends Level implements WorldGenLevel { gameprofilerfiller.pop(); } @@ -13554,7 +13552,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 @Override public boolean shouldTickBlocksAt(long chunkPos) { // Paper start - replace player chunk loader system -@@ -945,11 +1051,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -940,11 +1046,12 @@ public class ServerLevel extends Level implements WorldGenLevel { protected void tickTime() { if (this.tickTime) { @@ -13571,7 +13569,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 this.setDayTime(this.levelData.getDayTime() + 1L); } -@@ -978,15 +1085,23 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -973,15 +1080,23 @@ public class ServerLevel extends Level implements WorldGenLevel { private void wakeUpAllPlayers() { this.sleepStatus.removeAllSleepers(); (this.players.stream().filter(LivingEntity::isSleeping).collect(Collectors.toList())).forEach((entityplayer) -> { // CraftBukkit - decompile error @@ -13598,16 +13596,16 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 ChunkPos chunkcoordintpair = chunk.getPos(); boolean flag = this.isRaining(); int j = chunkcoordintpair.getMinBlockX(); -@@ -994,7 +1109,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -989,7 +1104,7 @@ public class ServerLevel extends Level implements WorldGenLevel { ProfilerFiller gameprofilerfiller = this.getProfiler(); gameprofilerfiller.push("thunder"); - final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change + final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition.get(); // Paper - use mutable to reduce allocation rate, final to force compile fail on change // Folia - region threading - if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - disable thunder + if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - Option to disable thunder blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper -@@ -1050,7 +1165,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1045,7 +1160,7 @@ public class ServerLevel extends Level implements WorldGenLevel { int yPos = (sectionIndex + minSection) << 4; for (int a = 0; a < randomTickSpeed; ++a) { int tickingBlocks = section.tickingList.size(); @@ -13616,7 +13614,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 if (index >= tickingBlocks) { continue; } -@@ -1064,7 +1179,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1059,7 +1174,7 @@ public class ServerLevel extends Level implements WorldGenLevel { BlockPos blockposition2 = blockposition.set(j + randomX, randomY, k + randomZ); BlockState iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); @@ -13625,7 +13623,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } // We drop the fluid tick since LAVA is ALREADY TICKED by the above method (See LiquidBlock). // TODO CHECK ON UPDATE (ping the Canadian) -@@ -1169,7 +1284,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1164,7 +1279,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } public boolean isHandlingTick() { @@ -13634,7 +13632,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } public boolean canSleepThroughNights() { -@@ -1201,6 +1316,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1196,6 +1311,14 @@ public class ServerLevel extends Level implements WorldGenLevel { } public void updateSleepingPlayerList() { @@ -13649,7 +13647,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 if (!this.players.isEmpty() && this.sleepStatus.update(this.players)) { this.announceSleepStatus(); } -@@ -1212,7 +1335,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1207,7 +1330,7 @@ public class ServerLevel extends Level implements WorldGenLevel { return this.server.getScoreboard(); } @@ -13658,7 +13656,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 boolean flag = this.isRaining(); if (this.dimensionType().hasSkyLight()) { -@@ -1298,23 +1421,24 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1293,23 +1416,24 @@ public class ServerLevel extends Level implements WorldGenLevel { this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel)); } // */ @@ -13692,7 +13690,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } } // CraftBukkit end -@@ -1379,7 +1503,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1374,7 +1498,7 @@ public class ServerLevel extends Level implements WorldGenLevel { public void tickNonPassenger(Entity entity) { // Paper start - log detailed entity tick information @@ -13701,7 +13699,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 try { if (currentlyTickingEntity.get() == null) { currentlyTickingEntity.lazySet(entity); -@@ -1412,7 +1536,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1407,7 +1531,16 @@ public class ServerLevel extends Level implements WorldGenLevel { if (isActive) { // Paper - EAR 2 TimingHistory.activatedEntityTicks++; entity.tick(); @@ -13719,7 +13717,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } else { entity.inactiveTick(); } // Paper - EAR 2 this.getProfiler().pop(); } finally { timer.stopTiming(); } // Paper - timings -@@ -1435,7 +1568,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1430,7 +1563,7 @@ public class ServerLevel extends Level implements WorldGenLevel { private void tickPassenger(Entity vehicle, Entity passenger) { if (!passenger.isRemoved() && passenger.getVehicle() == vehicle) { @@ -13728,7 +13726,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 // Paper - EAR 2 final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper -@@ -1452,7 +1585,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1447,7 +1580,16 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper start - EAR 2 if (isActive) { passenger.rideTick(); @@ -13746,37 +13744,38 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } else { passenger.setDeltaMovement(Vec3.ZERO); passenger.inactiveTick(); -@@ -1540,7 +1682,15 @@ public class ServerLevel extends Level implements WorldGenLevel { - // Paper - rewrite chunk system - entity saving moved into ChunkHolder +@@ -1536,20 +1678,22 @@ public class ServerLevel extends Level implements WorldGenLevel { } else if (close) { chunkproviderserver.close(false); } // Paper - rewrite chunk system -+ // Folia - move into saveLevelData() -+ } -+ public void saveLevelData() { // Folia - region threading -+ if (this.dragonFight != null) { -+ this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit -+ } -+ // Folia start - region threading -+ // moved from save - // CraftBukkit start - moved from MinecraftServer.saveChunks - ServerLevel worldserver1 = this; - -@@ -1548,12 +1698,7 @@ public class ServerLevel extends Level implements WorldGenLevel { - this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save()); - this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); - // CraftBukkit end -- } +- // CraftBukkit start - moved from MinecraftServer.saveChunks +- ServerLevel worldserver1 = this; - -- private void saveLevelData() { -- if (this.dragonFight != null) { -- this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit -- } -+ // Folia end - region threading - - this.getChunkSource().getDataStorage().save(); +- this.serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); +- this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save()); +- this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); +- // CraftBukkit end ++ // Folia - move into saveLevelData } -@@ -1608,6 +1753,19 @@ public class ServerLevel extends Level implements WorldGenLevel { + +- private void saveLevelData(boolean async) { // Paper - Write SavedData IO async ++ public void saveLevelData(boolean async) { // Paper - Write SavedData IO async // Folia - public + if (this.dragonFight != null) { + this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit + } + ++ // Folia start - moved into saveLevelData ++ ServerLevel worldserver1 = this; ++ ++ this.serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save()); ++ this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); ++ // Folia end - moved into saveLevelData ++ + this.getChunkSource().getDataStorage().save(async); // Paper - Write SavedData IO async + } + +@@ -1603,6 +1747,19 @@ public class ServerLevel extends Level implements WorldGenLevel { return list; } @@ -13796,7 +13795,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 @Nullable public ServerPlayer getRandomPlayer() { List list = this.getPlayers(LivingEntity::isAlive); -@@ -1710,8 +1868,8 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1690,8 +1847,8 @@ public class ServerLevel extends Level implements WorldGenLevel { } else { if (entity instanceof net.minecraft.world.entity.item.ItemEntity itemEntity && itemEntity.getItem().isEmpty()) return false; // Paper - Prevent empty items from being added // Paper start - capture all item additions to the world @@ -13807,7 +13806,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 return true; } // Paper end - capture all item additions to the world -@@ -1855,7 +2013,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1835,7 +1992,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @Override public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { @@ -13816,7 +13815,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 String s = "recursive call to sendBlockUpdated"; Util.logAndPauseIfInIde("recursive call to sendBlockUpdated", new IllegalStateException("recursive call to sendBlockUpdated")); -@@ -1868,7 +2026,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1848,7 +2005,7 @@ public class ServerLevel extends Level implements WorldGenLevel { if (Shapes.joinIsNotEmpty(voxelshape, voxelshape1, BooleanOp.NOT_SAME)) { List list = new ObjectArrayList(); @@ -13825,7 +13824,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 while (iterator.hasNext()) { // CraftBukkit start - fix SPIGOT-6362 -@@ -1891,7 +2049,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1871,7 +2028,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } try { @@ -13834,7 +13833,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 iterator = list.iterator(); while (iterator.hasNext()) { -@@ -1900,7 +2058,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1880,7 +2037,7 @@ public class ServerLevel extends Level implements WorldGenLevel { navigationabstract1.recomputePath(); } } finally { @@ -13843,7 +13842,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } } -@@ -1909,23 +2067,23 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1889,23 +2046,23 @@ public class ServerLevel extends Level implements WorldGenLevel { @Override public void updateNeighborsAt(BlockPos pos, Block sourceBlock) { @@ -13872,7 +13871,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } @Override -@@ -1956,7 +2114,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1936,7 +2093,7 @@ public class ServerLevel extends Level implements WorldGenLevel { explosion.clearToBlow(); } @@ -13881,7 +13880,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); -@@ -1971,25 +2129,28 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1951,25 +2108,28 @@ public class ServerLevel extends Level implements WorldGenLevel { @Override public void blockEvent(BlockPos pos, Block block, int type, int data) { @@ -13916,7 +13915,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } private boolean doBlockEvent(BlockEventData event) { -@@ -2000,12 +2161,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1980,12 +2140,12 @@ public class ServerLevel extends Level implements WorldGenLevel { @Override public LevelTicks getBlockTicks() { @@ -13931,16 +13930,16 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } @Nonnull -@@ -2029,7 +2190,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2009,7 +2169,7 @@ public class ServerLevel extends Level implements WorldGenLevel { public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { - // Paper start - Particle API Expansion + // Paper start - Particle API - return sendParticles(players, sender, t0, d0, d1, d2, i, d3, d4, d5, d6, force); + return sendParticles(this.getLocalPlayers(), sender, t0, d0, d1, d2, i, d3, d4, d5, d6, force); // Folia - region threading } public int sendParticles(List receivers, @Nullable ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { - // Paper end -@@ -2082,7 +2243,14 @@ public class ServerLevel extends Level implements WorldGenLevel { + // Paper end - Particle API +@@ -2062,7 +2222,14 @@ public class ServerLevel extends Level implements WorldGenLevel { public Entity getEntityOrPart(int id) { Entity entity = (Entity) this.getEntities().get(id); @@ -13956,7 +13955,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } @Nullable -@@ -2260,6 +2428,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2240,6 +2407,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } public boolean setChunkForced(int x, int z, boolean forced) { @@ -13964,7 +13963,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) this.getDataStorage().computeIfAbsent(ForcedChunksSavedData.factory(), "chunks"); ChunkPos chunkcoordintpair = new ChunkPos(x, z); long k = chunkcoordintpair.toLong(); -@@ -2268,7 +2437,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2248,7 +2416,7 @@ public class ServerLevel extends Level implements WorldGenLevel { if (forced) { flag1 = forcedchunk.getChunks().add(k); if (flag1) { @@ -13973,7 +13972,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } } else { flag1 = forcedchunk.getChunks().remove(k); -@@ -2296,13 +2465,18 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2276,13 +2444,18 @@ public class ServerLevel extends Level implements WorldGenLevel { BlockPos blockposition1 = pos.immutable(); optional.ifPresent((holder) -> { @@ -13995,7 +13994,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 // Paper start - Remove stale POIs if (optional.isEmpty() && this.getPoiManager().exists(blockposition1, poiType -> true)) { this.getPoiManager().remove(blockposition1); -@@ -2310,7 +2484,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2290,7 +2463,12 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper end - Remove stale POIs this.getPoiManager().add(blockposition1, holder); DebugPackets.sendPoiAddedPacket(this, blockposition1); @@ -14009,7 +14008,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 }); } } -@@ -2357,7 +2536,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2337,7 +2515,7 @@ public class ServerLevel extends Level implements WorldGenLevel { BufferedWriter bufferedwriter = Files.newBufferedWriter(path.resolve("stats.txt")); try { @@ -14018,7 +14017,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 NaturalSpawner.SpawnState spawnercreature_d = this.getChunkSource().getLastSpawnState(); if (spawnercreature_d != null) { -@@ -2371,7 +2550,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2351,7 +2529,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } bufferedwriter.write(String.format(Locale.ROOT, "entities: %s\n", this.entityLookup.getDebugInfo())); // Paper - rewrite chunk system @@ -14027,7 +14026,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 bufferedwriter.write(String.format(Locale.ROOT, "block_ticks: %d\n", this.getBlockTicks().count())); bufferedwriter.write(String.format(Locale.ROOT, "fluid_ticks: %d\n", this.getFluidTicks().count())); bufferedwriter.write("distance_manager: " + playerchunkmap.getDistanceManager().getDebugStatus() + "\n"); -@@ -2517,7 +2696,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2497,7 +2675,7 @@ public class ServerLevel extends Level implements WorldGenLevel { private void dumpBlockEntityTickers(Writer writer) throws IOException { CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(writer); @@ -14036,7 +14035,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 while (iterator.hasNext()) { TickingBlockEntity tickingblockentity = (TickingBlockEntity) iterator.next(); -@@ -2530,7 +2709,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2510,7 +2688,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @VisibleForTesting public void clearBlockEvents(BoundingBox box) { @@ -14045,7 +14044,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 return box.isInside(blockactiondata.pos()); }); } -@@ -2539,7 +2718,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2519,7 +2697,7 @@ public class ServerLevel extends Level implements WorldGenLevel { public void blockUpdated(BlockPos pos, Block block) { if (!this.isDebug()) { // CraftBukkit start @@ -14054,7 +14053,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 return; } // CraftBukkit end -@@ -2582,9 +2761,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2562,9 +2740,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @VisibleForTesting public String getWatchdogStats() { @@ -14065,7 +14064,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } private static String getTypeCount(Iterable items, Function classifier) { -@@ -2617,6 +2794,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2597,6 +2773,12 @@ public class ServerLevel extends Level implements WorldGenLevel { public static void makeObsidianPlatform(ServerLevel worldserver, Entity entity) { // CraftBukkit end BlockPos blockposition = ServerLevel.END_SPAWN_POINT; @@ -14078,7 +14077,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 int i = blockposition.getX(); int j = blockposition.getY() - 2; int k = blockposition.getZ(); -@@ -2629,11 +2812,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2609,11 +2791,7 @@ public class ServerLevel extends Level implements WorldGenLevel { BlockPos.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockposition1) -> { blockList.setBlock(blockposition1, Blocks.OBSIDIAN.defaultBlockState(), 3); }); @@ -14091,7 +14090,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 blockList.updateList(); } // CraftBukkit end -@@ -2654,13 +2833,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2634,13 +2812,14 @@ public class ServerLevel extends Level implements WorldGenLevel { } public void startTickingChunk(LevelChunk chunk) { @@ -14110,7 +14109,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } @Override -@@ -2682,7 +2862,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2662,7 +2841,7 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper end - rewrite chunk system } @@ -14119,7 +14118,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 // Paper start - optimize is ticking ready type functions io.papermc.paper.chunk.system.scheduling.NewChunkHolder chunkHolder = this.chunkTaskScheduler.chunkHolderManager.getChunkHolder(chunkPos); // isTicking implies the chunk is loaded, and the chunk is loaded now implies the entities are loaded -@@ -2748,16 +2928,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2728,16 +2907,16 @@ public class ServerLevel extends Level implements WorldGenLevel { public void onCreated(Entity entity) {} public void onDestroyed(Entity entity) { @@ -14139,15 +14138,15 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 // Paper start - Reset pearls when they stop being ticked if (paperConfig().fixes.disableUnloadedChunkEnderpearlExploit && entity instanceof net.minecraft.world.entity.projectile.ThrownEnderpearl pearl) { pearl.cachedOwner = null; -@@ -2768,6 +2948,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2748,6 +2927,7 @@ public class ServerLevel extends Level implements WorldGenLevel { public void onTrackingStart(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot + ServerLevel.this.getCurrentWorldData().addLoadedEntity(entity); // Folia - region threading - // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - moved down below valid=true + // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true if (entity instanceof ServerPlayer) { ServerPlayer entityplayer = (ServerPlayer) entity; -@@ -2785,7 +2966,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2765,7 +2945,7 @@ public class ServerLevel extends Level implements WorldGenLevel { Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); } @@ -14156,7 +14155,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } if (entity instanceof EnderDragon) { -@@ -2796,7 +2977,9 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2776,7 +2956,9 @@ public class ServerLevel extends Level implements WorldGenLevel { for (int j = 0; j < i; ++j) { EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; @@ -14166,7 +14165,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } } -@@ -2818,16 +3001,24 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2798,16 +2980,24 @@ public class ServerLevel extends Level implements WorldGenLevel { public void onTrackingEnd(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot @@ -14192,7 +14191,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 map.carriedByPlayers.remove( (Player) entity ); for ( Iterator iter = (Iterator) map.carriedBy.iterator(); iter.hasNext(); ) { -@@ -2837,6 +3028,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2817,6 +3007,7 @@ public class ServerLevel extends Level implements WorldGenLevel { iter.remove(); } } @@ -14200,7 +14199,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } } } ); -@@ -2871,7 +3063,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2851,7 +3042,7 @@ public class ServerLevel extends Level implements WorldGenLevel { Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); } @@ -14209,7 +14208,7 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 } if (entity instanceof EnderDragon) { -@@ -2882,13 +3074,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2862,13 +3053,16 @@ public class ServerLevel extends Level implements WorldGenLevel { for (int j = 0; j < i; ++j) { EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; @@ -14227,14 +14226,14 @@ index 320f95af742ce2ae8cc4a8d9e727a4a573ed3214..a04ae14681880897132bd410680d8f69 for (ServerPlayer player : ServerLevel.this.players) { player.getBukkitEntity().onEntityRemove(entity); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 63aa403e032686905b4388024939cd8379c09f70..9a4481da26820f967d38ff582c256361936f957b 100644 +index 0dba30c41affafe7b1d585b515925043b37712fa..b9e7c8776b5b4086fb2455035857947f9a4b3dba 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -191,7 +191,7 @@ import org.bukkit.inventory.MainHand; public class ServerPlayer extends Player { private static final Logger LOGGER = LogUtils.getLogger(); -- public long lastSave = MinecraftServer.currentTick; // Paper +- public long lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving + public long lastSave = Long.MIN_VALUE; // Paper // Folia - threaded regions - changed to nanoTime private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; @@ -14783,7 +14782,7 @@ index 63aa403e032686905b4388024939cd8379c09f70..9a4481da26820f967d38ff582c256361 + this.camera = (Entity) (entity == null ? this : entity); if (entity1 != this.camera) { - // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event + // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity @@ -2733,7 +3175,7 @@ public class ServerPlayer extends Player { this.experienceLevel = this.newLevel; this.totalExperience = this.newTotalExp; @@ -14794,24 +14793,24 @@ index 63aa403e032686905b4388024939cd8379c09f70..9a4481da26820f967d38ff582c256361 this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.DEATH); this.effectsDirty = true; diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index 1f122067f5863c386bc1e50769d33eda422defcc..760c5754030d01c2c01ca90df48276f9f43b9683 100644 +index a7b217ddbcbf92513bd38101fdfca2075505e267..8d2d0852ca5d137a74ba7be9a58e45c6bb832552 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java @@ -128,7 +128,7 @@ public class ServerPlayerGameMode { BlockState iblockdata; if (this.hasDelayedDestroy) { -- iblockdata = this.level.getBlockStateIfLoaded(this.delayedDestroyPos); // Paper -+ iblockdata = !io.papermc.paper.util.TickThread.isTickThreadFor(this.level, this.delayedDestroyPos) ? null : this.level.getBlockStateIfLoaded(this.delayedDestroyPos); // Paper // Folia - region threading - don't destroy blocks not owned - if (iblockdata == null || iblockdata.isAir()) { // Paper +- iblockdata = this.level.getBlockStateIfLoaded(this.delayedDestroyPos); // Paper - Don't allow digging into unloaded chunks ++ iblockdata = !io.papermc.paper.util.TickThread.isTickThreadFor(this.level, this.delayedDestroyPos) ? null : this.level.getBlockStateIfLoaded(this.delayedDestroyPos); // Paper - Don't allow digging into unloaded chunks // Folia - region threading - don't destroy blocks not owned + if (iblockdata == null || iblockdata.isAir()) { // Paper - Don't allow digging into unloaded chunks this.hasDelayedDestroy = false; } else { @@ -141,7 +141,7 @@ public class ServerPlayerGameMode { } } else if (this.isDestroyingBlock) { - // Paper start - don't want to do same logic as above, return instead + // Paper start - Don't allow digging into unloaded chunks; don't want to do same logic as above, return instead - iblockdata = this.level.getBlockStateIfLoaded(this.destroyPos); -+ iblockdata = !io.papermc.paper.util.TickThread.isTickThreadFor(this.level, this.destroyPos) ? null : this.level.getBlockStateIfLoaded(this.destroyPos); // Folia - region threading - don't destroy blocks not owned ++ iblockdata = !io.papermc.paper.util.TickThread.isTickThreadFor(this.level, this.destroyPos) ? null : this.level.getBlockStateIfLoaded(this.destroyPos); if (iblockdata == null) { this.isDestroyingBlock = false; return; @@ -14964,7 +14963,7 @@ index 5ece375eaf6bcc61864997a389bb5e24625e4505..33c1ef45ed620f8424c2c83dd30b6748 this.generatingStatus = status; this.writeRadiusCutoff = placementRadius; diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -index 5d0500ee2740977c6b6eb89ed51e29b5a2e66760..bdeb70fdcd2985c9ffd7cfb77f75d1bd1eb49a02 100644 +index 0306771b8f90dcdd77f151c19c6c2d75c41f8feb..22f0d91df0a81040d72c499fbff32b3a9d41598f 100644 --- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java @@ -75,6 +75,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack @@ -15006,7 +15005,7 @@ index 5d0500ee2740977c6b6eb89ed51e29b5a2e66760..bdeb70fdcd2985c9ffd7cfb77f75d1bd this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause - }); + // Folia - region threading - do not schedule to main anymore, there is no main - // Paper endg + // Paper end - This needs to be handled on the main thread for plugins } @@ -292,24 +304,8 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack @@ -15046,7 +15045,7 @@ index 5d0500ee2740977c6b6eb89ed51e29b5a2e66760..bdeb70fdcd2985c9ffd7cfb77f75d1bd protected boolean isSingleplayerOwner() { diff --git a/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java -index cae10b963d153fb1777b18054796a45b2809342b..080a25714937e8413c4e9d15eb257f726a03ea7f 100644 +index 76f31845fe50200d09e5ab6a6c08da00444414ad..58ec60ad6e597f2f3e6cbbe8a4e5bc696e709d1d 100644 --- a/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java @@ -43,6 +43,7 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis @@ -15117,14 +15116,14 @@ index cae10b963d153fb1777b18054796a45b2809342b..080a25714937e8413c4e9d15eb257f72 } catch (Exception exception) { ServerConfigurationPacketListenerImpl.LOGGER.error("Couldn't place player in world", exception); diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -index 1e33cabcdf2c6c4894024bdcc1a479b2d120f944..35bf160d10b56fb84d4cb845b61c1d61337e48ca 100644 +index 586521a2cbb1d4dcfb912029f65e4363ec7674a7..6e95017f4c36208abdf344e3b7d55efe2d5b4e10 100644 --- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -@@ -158,10 +158,13 @@ public class ServerConnectionListener { +@@ -152,10 +152,13 @@ public class ServerConnectionListener { }); } // Paper end - Add support for proxy protocol -- pending.add(object); // Paper +- pending.add(object); // Paper - prevent blocking on adding a new connection while the server is ticking + // Folia - connection fixes - move down ((Connection) object).configurePacketHandler(channelpipeline); ((Connection) object).setListenerForServerboundHandshake(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); @@ -15135,9 +15134,9 @@ index 1e33cabcdf2c6c4894024bdcc1a479b2d120f944..35bf160d10b56fb84d4cb845b61c1d61 } }).group(eventloopgroup).localAddress(address)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit // Paper - Unix domain socket support } -@@ -224,7 +227,7 @@ public class ServerConnectionListener { +@@ -218,7 +221,7 @@ public class ServerConnectionListener { // Spigot Start - this.addPending(); // Paper + this.addPending(); // Paper - prevent blocking on adding a new connection while the server is ticking // This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order - if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && MinecraftServer.currentTick % org.spigotmc.SpigotConfig.playerShuffle == 0 ) + if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && 0 % org.spigotmc.SpigotConfig.playerShuffle == 0 ) // Folia - region threading @@ -15145,19 +15144,19 @@ index 1e33cabcdf2c6c4894024bdcc1a479b2d120f944..35bf160d10b56fb84d4cb845b61c1d61 Collections.shuffle( this.connections ); } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263bc83758ea 100644 +index a7e40f72a3b56916620a7f089410ec3a6db0cffc..095134bb3c07ad8daeaf4b28076d60b96b481458 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -292,7 +292,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -291,7 +291,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl private final LastSeenMessagesValidator lastSeenMessages = new LastSeenMessagesValidator(20); private final MessageSignatureCache messageSignatureCache = MessageSignatureCache.createDefault(); private final FutureChain chatMessageChain; - private boolean waitingForSwitchToConfig; + public volatile boolean waitingForSwitchToConfig; // Folia - rewrite login process - fix bad ordering of this field write + public - private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); // Paper + private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); // Paper - Limit client sign length public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player, CommonListenerCookie clientData) { -@@ -310,10 +310,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -309,10 +309,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } // CraftBukkit start - add fields @@ -15171,7 +15170,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b private int dropCount = 0; private boolean hasMoved = false; -@@ -325,8 +325,21 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -324,8 +324,21 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl private boolean justTeleported = false; // CraftBukkit end @@ -15193,7 +15192,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b if (this.ackBlockChangesUpTo > -1) { this.send(new ClientboundBlockChangedAckPacket(this.ackBlockChangesUpTo)); this.ackBlockChangesUpTo = -1; -@@ -375,7 +388,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -374,7 +387,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.aboveGroundVehicleTickCount = 0; } @@ -15201,8 +15200,8 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b + // Folia - region threading - moved to beginning of method // CraftBukkit start for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !this.chatSpamTickCount.compareAndSet(spam, spam - 1); ) ; - if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable -@@ -412,6 +425,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - configurable tab spam limits +@@ -411,6 +424,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.lastGoodX = this.player.getX(); this.lastGoodY = this.player.getY(); this.lastGoodZ = this.player.getZ(); @@ -15222,7 +15221,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b } @Override -@@ -512,9 +538,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -511,9 +537,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // Paper end - fix large move vectors killing the server // CraftBukkit start - handle custom speeds and skipped ticks @@ -15235,7 +15234,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b ++this.receivedMovePacketCount; int i = this.receivedMovePacketCount - this.knownMovePacketCount; -@@ -588,7 +615,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -587,7 +614,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } entity.absMoveTo(d3, d4, d5, f, f1); @@ -15244,7 +15243,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b // Paper start - optimise out extra getCubes boolean teleportBack = flag2; // violating this is always a fail -@@ -601,11 +628,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -600,11 +627,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } if (teleportBack) { // Paper end - optimise out extra getCubes entity.absMoveTo(d0, d1, d2, f, f1); @@ -15265,7 +15264,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b // CraftBukkit start - fire PlayerMoveEvent Player player = this.getCraftPlayer(); if (!this.hasMoved) { -@@ -645,7 +680,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -644,7 +679,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // If the event is cancelled we move the player back to their old location. if (event.isCancelled()) { @@ -15274,7 +15273,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b return; } -@@ -653,7 +688,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -652,7 +687,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. // We only do this if the Event was not cancelled. if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { @@ -15283,41 +15282,34 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b return; } -@@ -769,13 +804,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - run this async +@@ -768,7 +803,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - AsyncTabCompleteEvent; run this async // CraftBukkit start - if (this.chatSpamTickCount.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable -- server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause -+ this.disconnect(Component.translatable("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause // Folia - region threading + if (this.chatSpamTickCount.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper - configurable tab spam limits +- this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - Kick event cause ++ this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - Kick event cause // Folia - region threading return; } + // CraftBukkit end +@@ -780,7 +815,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // Paper start - String str = packet.getCommand(); int index = -1; - if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { -- server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]))); // Paper -+ this.disconnect(Component.translatable("disconnect.spam", new Object[0])); // Paper // Folia - region threading + final int index; + if (packet.getCommand().length() > 64 && ((index = packet.getCommand().indexOf(' ')) == -1 || index >= 64)) { +- this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); ++ this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Folia - region threading return; } // Paper end -@@ -800,7 +835,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - if (!event.isHandled()) { - if (!event.isCancelled()) { +@@ -805,7 +840,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + } -- this.server.scheduleOnMain(() -> { // This needs to be on main -+ this.player.getBukkitEntity().taskScheduler.schedule((ServerPlayer player) -> { // Folia - region threading - ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); - - this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -@@ -816,7 +851,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestEvent.getSuggestions())); - // Paper end - Brigadier API - }); -- }); -+ }, null, 1L); // Folia - region threading - } - } else if (!completions.isEmpty()) { - final com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(command, stringreader.getTotalLength()); -@@ -1132,7 +1167,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + // This needs to be on main +- this.server.scheduleOnMain(() -> this.sendServerSuggestions(packet, stringreader)); ++ this.player.getBukkitEntity().taskScheduler.schedule((ServerPlayer player) -> this.sendServerSuggestions(packet, stringreader), null, 1L); // Folia - region threading + } else if (!completions.isEmpty()) { + final com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); + final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1); +@@ -1150,7 +1185,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; if (byteLength > 256 * 4) { ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!"); @@ -15326,7 +15318,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b return; } byteTotal += byteLength; -@@ -1155,17 +1190,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1173,17 +1208,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl if (byteTotal > byteAllowed) { ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); @@ -15335,7 +15327,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b return; } } - // Paper end + // Paper end - Book size limits // CraftBukkit start - if (this.lastBookTick + 20 > MinecraftServer.currentTick) { - server.scheduleOnMain(() -> this.disconnect("Book edited too quickly!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause // Paper - Also ensure this is called on main @@ -15348,7 +15340,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b // CraftBukkit end int i = packet.getSlot(); -@@ -1185,7 +1220,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1203,7 +1238,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.updateBookContents(list1, i); }; @@ -15369,7 +15361,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b } } -@@ -1371,9 +1418,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1389,9 +1436,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl int i = this.receivedMovePacketCount - this.knownMovePacketCount; // CraftBukkit start - handle custom speeds and skipped ticks @@ -15382,7 +15374,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b if (i > Math.max(this.allowedPlayerTicks, 5)) { ServerGamePacketListenerImpl.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName().getString(), i); -@@ -1566,7 +1614,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1581,7 +1629,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // If the event is cancelled we move the player back to their old location. if (event.isCancelled()) { @@ -15391,7 +15383,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b return; } -@@ -1574,7 +1622,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1589,7 +1637,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. // We only do this if the Event was not cancelled. if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { @@ -15400,7 +15392,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b return; } -@@ -1806,9 +1854,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1809,9 +1857,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl if (!this.player.isSpectator()) { // limit how quickly items can be dropped // If the ticks aren't the same then the count starts from 0 and we update the lastDropTick. @@ -15412,16 +15404,16 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b } else { // Else we increment the drop count and check the amount. this.dropCount++; -@@ -1836,7 +1884,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1839,7 +1887,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl case ABORT_DESTROY_BLOCK: case STOP_DESTROY_BLOCK: - // Paper start - Don't allow digging in unloaded chunks + // Paper start - Don't allow digging into unloaded chunks - if (this.player.level().getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(this.player.serverLevel(), blockposition.getX() >> 4, blockposition.getZ() >> 4, 8) || this.player.level().getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { // Folia - region threading - don't destroy blocks not owned ++ if (!io.papermc.paper.util.TickThread.isTickThreadFor(this.player.serverLevel(), blockposition.getX() >> 4, blockposition.getZ() >> 4, 8) || this.player.level().getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { // Folia - region threading - don't destroy blocks not owned this.player.connection.ackBlockChangesUpTo(packet.getSequence()); return; } -@@ -1920,7 +1968,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1923,7 +1971,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl BlockPos blockposition = movingobjectpositionblock.getBlockPos(); Vec3 vec3d1 = Vec3.atCenterOf(blockposition); @@ -15430,7 +15422,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b Vec3 vec3d2 = vec3d.subtract(vec3d1); double d0 = 1.0000001D; -@@ -2034,7 +2082,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2037,7 +2085,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl Entity entity = packet.getEntity(worldserver); if (entity != null) { @@ -15439,7 +15431,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b return; } } -@@ -2071,7 +2119,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2074,7 +2122,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } // CraftBukkit end ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), reason.getString()); @@ -15448,7 +15440,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b super.onDisconnect(reason, quitMessage); // Paper - Fix kick event leave message not being sent } -@@ -2080,6 +2128,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2083,6 +2131,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.removePlayerFromWorld(null); } @@ -15457,7 +15449,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b private void removePlayerFromWorld(@Nullable net.kyori.adventure.text.Component quitMessage) { // Paper end - Fix kick event leave message not being sent this.chatMessageChain.close(); -@@ -2092,6 +2142,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2095,6 +2145,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.player.disconnect(); // Paper start - Adventure quitMessage = quitMessage == null ? this.server.getPlayerList().remove(this.player) : this.server.getPlayerList().remove(this.player, quitMessage); // Paper - pass in quitMessage to fix kick message not being used @@ -15466,7 +15458,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { this.server.getPlayerList().broadcastSystemMessage(PaperAdventure.asVanilla(quitMessage), false); // Paper end -@@ -2144,7 +2196,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2147,7 +2199,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } // CraftBukkit end if (ServerGamePacketListenerImpl.isChatMessageIllegal(packet.message())) { @@ -15476,7 +15468,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b } else { Optional optional = this.tryHandleChat(packet.lastSeenMessages()); -@@ -2176,21 +2230,22 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2179,21 +2233,22 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl @Override public void handleChatCommand(ServerboundChatCommandPacket packet) { if (ServerGamePacketListenerImpl.isChatMessageIllegal(packet.command())) { @@ -15502,7 +15494,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b } } -@@ -2324,7 +2379,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2327,7 +2382,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl String originalFormat = event.getFormat(), originalMessage = event.getMessage(); this.cserver.getPluginManager().callEvent(event); @@ -15511,7 +15503,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b // Evil plugins still listening to deprecated event final PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients()); queueEvent.setCancelled(event.isCancelled()); -@@ -2435,6 +2490,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2438,6 +2493,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl if (s.isEmpty()) { ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send an empty message"); } else if (this.getCraftPlayer().isConversing()) { @@ -15519,7 +15511,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b final String conversationInput = s; this.server.processQueue.add(new Runnable() { @Override -@@ -2671,8 +2727,25 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2674,8 +2730,25 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // Spigot End public void switchToConfig() { @@ -15546,7 +15538,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b this.send(new ClientboundStartConfigurationPacket()); } -@@ -2697,7 +2770,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2700,7 +2773,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.player.resetLastActionTime(); this.player.setShiftKeyDown(packet.isUsingSecondaryAction()); @@ -15555,7 +15547,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b if (!worldserver.getWorldBorder().isWithinBounds(entity.blockPosition())) { return; } -@@ -2838,6 +2911,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2830,6 +2903,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl switch (packetplayinclientcommand_enumclientcommand) { case PERFORM_RESPAWN: if (this.player.wonGame) { @@ -15568,7 +15560,7 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b this.player.wonGame = false; this.player = this.server.getPlayerList().respawn(this.player, this.server.getLevel(this.player.getRespawnDimension()), true, null, true, RespawnReason.END_PORTAL, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); // Paper - Expand PlayerRespawnEvent CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD); -@@ -2846,6 +2925,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2838,6 +2917,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl return; } @@ -15587,16 +15579,16 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b this.player = this.server.getPlayerList().respawn(this.player, false, RespawnReason.DEATH); if (this.server.isHardcore()) { this.player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper - Expand PlayerGameModeChangeEvent -@@ -3204,7 +3295,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -3196,7 +3287,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // Paper start - auto recipe limit if (!org.bukkit.Bukkit.isPrimaryThread()) { if (this.recipeSpamPackets.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamLimit) { -- this.server.scheduleOnMain(() -> this.disconnect(net.minecraft.network.chat.Component.translatable("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause -+ this.disconnect(net.minecraft.network.chat.Component.translatable("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause // Folia - region threading +- this.server.scheduleOnMain(() -> this.disconnect(net.minecraft.network.chat.Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause ++ this.disconnect(net.minecraft.network.chat.Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause // Folia - region threading return; } } -@@ -3373,7 +3464,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -3365,7 +3456,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.filterTextPacket(list).thenAcceptAsync((list1) -> { this.updateSignText(packet, list1); @@ -15617,12 +15609,12 @@ index ba6d22426398546b70760c2205ce625cead11803..f6e4d034379d40b39c2ed3de13fa263b private void updateSignText(ServerboundSignUpdatePacket packet, List signText) { diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 399786839bb9dbf96d2ecd654f999cb944cf2822..586027a4c97a3c1be42f1c8d5a248e2672bb6489 100644 +index c5fa9f4d28f9a7f64a50a902ee5e631bfc00119c..58cdb65083134680230d7070f9f6209f2d32873b 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -83,9 +83,13 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, +@@ -83,7 +83,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, } - // Paper end + // Paper end - Do not allow logins while the server is shutting down if (this.state == ServerLoginPacketListenerImpl.State.VERIFYING) { - if (this.connection.isConnected()) { // Paper - prevent logins to be processed even though disconnect was called + // Folia start - region threading - rewrite login process @@ -15631,11 +15623,8 @@ index 399786839bb9dbf96d2ecd654f999cb944cf2822..586027a4c97a3c1be42f1c8d5a248e26 + if (this.server.getPlayerList().pushPendingJoin(name, uniqueId, this.connection)) { + // Folia end - region threading - rewrite login process this.verifyLoginAndFinishConnectionSetup((GameProfile) Objects.requireNonNull(this.authenticatedProfile)); -- } // Paper -+ } // Folia - region threading - rewrite login process + } // Paper - prevent logins to be processed even though disconnect was called } - - if (this.state == ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT && !this.isPlayerAlreadyInWorld((GameProfile) Objects.requireNonNull(this.authenticatedProfile))) { @@ -205,7 +209,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, })); } @@ -15707,10 +15696,10 @@ index 8b1da1fb5ca27432a39aff6dbc452b793268dab5..e83f3676d5a194fa8d3d1567edcb4b6f // Guess we don't have a date } diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java -index 59eb65e207ff0206b0dfad6f2dcffe785f61f8ff..d568f54a14a1321a0478c220e72dba797b88523e 100644 +index 45d4638d568ea2aee805aa1b0542533019e5870d..599feff33b43623d7c6bd22158afa730efd5370d 100644 --- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java +++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java -@@ -511,7 +511,7 @@ public class OldUsersConverter { +@@ -510,7 +510,7 @@ public class OldUsersConverter { Date date1; try { @@ -15720,7 +15709,7 @@ index 59eb65e207ff0206b0dfad6f2dcffe785f61f8ff..d568f54a14a1321a0478c220e72dba79 date1 = fallback; } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541e7a015ca 100644 +index 91feb12732564c90656da487664dbc12e55397fc..fa36e892b019877a770a618fe8d4cda118fe137d 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -131,10 +131,10 @@ public abstract class PlayerList { @@ -15742,17 +15731,17 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 private CraftServer cserver; - private final Map playersByName = new java.util.HashMap<>(); + private final Map playersByName = new java.util.concurrent.ConcurrentHashMap<>(); // Folia - region threading - change to CHM - Note: we do NOT expect concurrency PER KEY! - public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule + public @Nullable String collideRuleTeamName; // Paper - Configurable player collision + // Folia start - region threading -+ private final Object stateLock = new Object(); ++ private final Object connectionsStateLock = new Object(); + private final Map connectionByName = new java.util.HashMap<>(); + private final Map connectionById = new java.util.HashMap<>(); + + public boolean pushPendingJoin(String userName, UUID byId, Connection conn) { + userName = userName.toLowerCase(java.util.Locale.ROOT); + Connection conflictingName, conflictingId; -+ synchronized (this.stateLock) { ++ synchronized (this.connectionsStateLock) { + conflictingName = this.connectionByName.get(userName); + conflictingId = this.connectionById.get(byId); + @@ -15778,14 +15767,14 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 + + public void removeConnection(String userName, UUID byId, Connection conn) { + userName = userName.toLowerCase(java.util.Locale.ROOT); -+ synchronized (this.stateLock) { ++ synchronized (this.connectionsStateLock) { + this.connectionByName.remove(userName, conn); + this.connectionById.remove(byId, conn); + } + } + + private int getTotalConnections() { -+ synchronized (this.stateLock) { ++ synchronized (this.connectionsStateLock) { + return this.connectionById.size(); + } + } @@ -15801,11 +15790,11 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 - public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie clientData) { + public void loadSpawnForNewPlayer(final Connection connection, final ServerPlayer player, final CommonListenerCookie clientData, org.apache.commons.lang3.mutable.MutableObject data, org.apache.commons.lang3.mutable.MutableObject lastKnownName, ca.spottedleaf.concurrentutil.completable.Completable toComplete) { // Folia - region threading - rewrite login process player.isRealPlayer = true; // Paper - player.loginTime = System.currentTimeMillis(); // Paper + player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed GameProfile gameprofile = player.getGameProfile(); @@ -257,18 +304,42 @@ public abstract class PlayerList { player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login - // Paper start - reset to main world spawn if first spawn or invalid world + // Paper start - reset to main world spawn if first spawn or invalid world } + // Folia start - region threading - rewrite login process + // must write to these before toComplete is invoked @@ -15813,9 +15802,9 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 + lastKnownName.setValue(s); + // Folia end - region threading - rewrite login process if (nbttagcompound == null || invalidPlayerWorld) { - // Paper end -- player.fudgeSpawnLocation(worldserver1); // only move to spawn on first login, otherwise, stay where you are.... -+ ServerPlayer.fudgeSpawnLocation(worldserver1, player, toComplete); // only move to spawn on first login, otherwise, stay where you are.... // Folia - region threading + // Paper end - reset to main world spawn if first spawn or invalid world +- player.fudgeSpawnLocation(worldserver1); // Paper - Don't move existing players to world spawn ++ ServerPlayer.fudgeSpawnLocation(worldserver1, player, toComplete); // Paper - Don't move existing players to world spawn // Folia - region threading + } else { // Folia start - region threading - rewrite login process + worldserver1.loadChunksForMoveAsync( + player.getBoundingBox(), @@ -15826,7 +15815,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 + ); } + // Folia end - region threading - rewrite login process - // Paper end + // Paper end - Entity#getEntitySpawnReason + // Folia start - region threading - rewrite login process + return; + } @@ -15888,33 +15877,33 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) { // Paper start - Add Listing API for Player @@ -482,7 +556,7 @@ public abstract class PlayerList { - // Paper start - Add to collideRule team if needed + // Paper start - Configurable player collision; Add to collideRule team if needed final net.minecraft.world.scores.Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); final PlayerTeam collideRuleTeam = scoreboard.getPlayerTeam(this.collideRuleTeamName); - if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) { + if (false && this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) { // Folia - region threading scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); } - // Paper end -@@ -577,7 +651,7 @@ public abstract class PlayerList { + // Paper end - Configurable player collision +@@ -576,7 +650,7 @@ public abstract class PlayerList { protected void save(ServerPlayer player) { if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit -- player.lastSave = MinecraftServer.currentTick; // Paper +- player.lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving + player.lastSave = System.nanoTime(); // Folia - region threading - changed to nanoTime tracking this.playerIo.save(player); ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit -@@ -617,7 +691,7 @@ public abstract class PlayerList { +@@ -616,7 +690,7 @@ public abstract class PlayerList { // CraftBukkit end - // Paper start - Remove from collideRule team if needed + // Paper start - Configurable player collision; Remove from collideRule team if needed - if (this.collideRuleTeamName != null) { + if (false && this.collideRuleTeamName != null) { // Folia - region threading final net.minecraft.world.scores.Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard(); final PlayerTeam team = scoreBoard.getPlayersTeam(this.collideRuleTeamName); if (entityplayer.getTeam() == team && team != null) { -@@ -657,7 +731,7 @@ public abstract class PlayerList { +@@ -656,7 +730,7 @@ public abstract class PlayerList { entityplayer.unRide(); worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER); @@ -15923,7 +15912,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 entityplayer.getAdvancements().stopListening(); this.players.remove(entityplayer); this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -676,8 +750,7 @@ public abstract class PlayerList { +@@ -675,8 +749,7 @@ public abstract class PlayerList { // CraftBukkit start // this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID()))); ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID())); @@ -15933,7 +15922,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 if (entityplayer2.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { entityplayer2.connection.send(packet); -@@ -702,19 +775,13 @@ public abstract class PlayerList { +@@ -701,19 +774,12 @@ public abstract class PlayerList { ServerPlayer entityplayer; @@ -15948,14 +15937,14 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 Iterator iterator = list.iterator(); while (iterator.hasNext()) { - entityplayer = (ServerPlayer) iterator.next(); +- entityplayer = (ServerPlayer) iterator.next(); - this.save(entityplayer); // CraftBukkit - Force the player's inventory to be saved -- entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause +- entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login"), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause + // Folia - moved to pushPendingJoin } // Instead of kicking then returning, we need to store the kick reason -@@ -733,7 +800,7 @@ public abstract class PlayerList { +@@ -732,7 +798,7 @@ public abstract class PlayerList { ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason()); if (gameprofilebanentry.getExpires() != null) { @@ -15964,7 +15953,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 } // return chatmessage; -@@ -746,14 +813,14 @@ public abstract class PlayerList { +@@ -745,14 +811,14 @@ public abstract class PlayerList { ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipbanentry.getReason()); if (ipbanentry.getExpires() != null) { @@ -15981,7 +15970,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 event.disallow(PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure } } -@@ -819,6 +886,11 @@ public abstract class PlayerList { +@@ -818,6 +884,11 @@ 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) { // Paper end - Expand PlayerRespawnEvent @@ -15993,7 +15982,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 entityplayer.stopRiding(); // CraftBukkit this.players.remove(entityplayer); this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -1018,10 +1090,10 @@ public abstract class PlayerList { +@@ -1017,10 +1088,10 @@ public abstract class PlayerList { public void tick() { if (++this.sendAllPlayerInfoIn > 600) { // CraftBukkit start @@ -16007,7 +15996,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 @Override public boolean test(ServerPlayer input) { return target.getBukkitEntity().canSee(input.getBukkitEntity()); -@@ -1047,18 +1119,17 @@ public abstract class PlayerList { +@@ -1046,18 +1117,17 @@ public abstract class PlayerList { // CraftBukkit start - add a world/entity limited version public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) { @@ -16030,7 +16019,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 } } -@@ -1102,8 +1173,7 @@ public abstract class PlayerList { +@@ -1101,8 +1171,7 @@ public abstract class PlayerList { if (scoreboardteam == null) { this.broadcastSystemMessage(message, false); } else { @@ -16040,7 +16029,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 if (entityplayer.getTeam() != scoreboardteam) { entityplayer.sendSystemMessage(message); -@@ -1114,10 +1184,12 @@ public abstract class PlayerList { +@@ -1113,10 +1182,12 @@ public abstract class PlayerList { } public String[] getPlayerNamesArray() { @@ -16056,7 +16045,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 } return astring; -@@ -1136,7 +1208,9 @@ public abstract class PlayerList { +@@ -1135,7 +1206,9 @@ public abstract class PlayerList { ServerPlayer entityplayer = this.getPlayer(profile.getId()); if (entityplayer != null) { @@ -16066,7 +16055,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 } } -@@ -1146,7 +1220,10 @@ public abstract class PlayerList { +@@ -1145,7 +1218,10 @@ public abstract class PlayerList { ServerPlayer entityplayer = this.getPlayer(profile.getId()); if (entityplayer != null) { @@ -16077,7 +16066,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 } } -@@ -1207,8 +1284,7 @@ public abstract class PlayerList { +@@ -1206,8 +1282,7 @@ public abstract class PlayerList { } public void broadcast(@Nullable net.minecraft.world.entity.player.Player player, double x, double y, double z, double distance, ResourceKey worldKey, Packet packet) { @@ -16087,7 +16076,7 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 // CraftBukkit start - Test if player receiving packet can see the source of the packet if (player != null && !entityplayer.getBukkitEntity().canSee(player.getBukkitEntity())) { -@@ -1238,12 +1314,21 @@ public abstract class PlayerList { +@@ -1237,12 +1312,21 @@ public abstract class PlayerList { io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main MinecraftTimings.savePlayers.startTiming(); // Paper int numSaved = 0; @@ -16112,9 +16101,9 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 + } + // Folia end - region threading } - // Paper end + // Paper end - Incremental chunk and player saving } -@@ -1362,6 +1447,20 @@ public abstract class PlayerList { +@@ -1361,6 +1445,20 @@ public abstract class PlayerList { } public void removeAll(boolean isRestarting) { @@ -16135,20 +16124,20 @@ index fef047544dbbd24ef30b673ebb92c1a047575d09..8284cde1984408a97a933f4299ad8541 // Paper end // CraftBukkit start - disconnect safely for (ServerPlayer player : this.players) { -@@ -1371,7 +1470,7 @@ public abstract class PlayerList { +@@ -1370,7 +1468,7 @@ public abstract class PlayerList { // CraftBukkit end - // Paper start - Remove collideRule team if it exists + // Paper start - Configurable player collision; Remove collideRule team if it exists - if (this.collideRuleTeamName != null) { + if (false && this.collideRuleTeamName != null) { // Folia - region threading final net.minecraft.world.scores.Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); final PlayerTeam team = scoreboard.getPlayersTeam(this.collideRuleTeamName); if (team != null) scoreboard.removePlayerTeam(team); diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java -index 665120a62525f56912263a3e1b6f12f6c3e15dec..d37315eba7c1db671136e913d6c1d73a6995fc8e 100644 +index 35f973cc2c0989256fa21abaf0327c2f36dbe4c9..3208b37cd74462e4efdc4985109a443a7e38883a 100644 --- a/src/main/java/net/minecraft/server/players/StoredUserList.java +++ b/src/main/java/net/minecraft/server/players/StoredUserList.java -@@ -126,6 +126,7 @@ public abstract class StoredUserList> { +@@ -103,6 +103,7 @@ public abstract class StoredUserList> { } public void save() throws IOException { @@ -16156,7 +16145,7 @@ index 665120a62525f56912263a3e1b6f12f6c3e15dec..d37315eba7c1db671136e913d6c1d73a this.removeExpired(); // Paper - remove expired values before saving JsonArray jsonarray = new JsonArray(); Stream stream = this.map.values().stream().map((jsonlistentry) -> { // CraftBukkit - decompile error -@@ -156,10 +157,12 @@ public abstract class StoredUserList> { +@@ -133,10 +134,12 @@ public abstract class StoredUserList> { if (bufferedwriter != null) { bufferedwriter.close(); } @@ -16169,7 +16158,7 @@ index 665120a62525f56912263a3e1b6f12f6c3e15dec..d37315eba7c1db671136e913d6c1d73a if (this.file.exists()) { BufferedReader bufferedreader = Files.newReader(this.file, StandardCharsets.UTF_8); -@@ -216,5 +219,6 @@ public abstract class StoredUserList> { +@@ -193,5 +196,6 @@ public abstract class StoredUserList> { } } @@ -16231,10 +16220,10 @@ index a6ac76707da39cf86113003b1f326433fdc86c86..531ccc48154b25378e9039478ce7f89b @Override public boolean remove(Object object) { diff --git a/src/main/java/net/minecraft/util/SpawnUtil.java b/src/main/java/net/minecraft/util/SpawnUtil.java -index 028d69907a988e191213a17e072ef22710b5bc83..ffa081156313247882747ea6da182ee54a1cf8a0 100644 +index 1954fdc7b72700d5948e93ebcb0e6a26fe244a1b..0167951b4dfbe07866bbf12f7ee81732788206f4 100644 --- a/src/main/java/net/minecraft/util/SpawnUtil.java +++ b/src/main/java/net/minecraft/util/SpawnUtil.java -@@ -63,7 +63,7 @@ public class SpawnUtil { +@@ -59,7 +59,7 @@ public class SpawnUtil { return Optional.of(t0); } @@ -16384,12 +16373,12 @@ index ea27b46eec01bda427653335f922ccd068cffcb5..e551d3b875eab6851b75041f418c9a08 return blockToFallLocation(blockState); } else { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94cda717fe 100644 +index 9ee1e3da1cb16291ff3e37829e25227a6b97a177..b736cb55542ea7bc35d1a02e7fe5913de024ca60 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -169,7 +169,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S - // Paper start + // Paper start - Share random for entities to make them more random public static RandomSource SHARED_RANDOM = new RandomRandomSource(); - private static final class RandomRandomSource extends java.util.Random implements net.minecraft.world.level.levelgen.BitRandomSource { + public static final class RandomRandomSource extends java.util.Random implements net.minecraft.world.level.levelgen.BitRandomSource { // Folia - region threading @@ -16404,34 +16393,8 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 + private volatile CraftEntity bukkitEntity; // Folia - region threading public @org.jetbrains.annotations.Nullable net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper - public @Nullable Throwable addedToWorldStack; // Paper - entity debug -@@ -537,6 +537,25 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S - this.teleportTo(worldserver, null); - } - // Paper end - make end portalling safe -+ // Folia start -+ private static final java.util.concurrent.ConcurrentHashMap, Integer> CLASS_ID_MAP = new java.util.concurrent.ConcurrentHashMap<>(); -+ private static final AtomicInteger CLASS_ID_GENERATOR = new AtomicInteger(); -+ public final int classId = CLASS_ID_MAP.computeIfAbsent(this.getClass(), (Class c) -> { -+ return CLASS_ID_GENERATOR.getAndIncrement(); -+ }); -+ private static final java.util.concurrent.atomic.AtomicLong REFERENCE_ID_GENERATOR = new java.util.concurrent.atomic.AtomicLong(); -+ public final long referenceId = REFERENCE_ID_GENERATOR.getAndIncrement(); -+ // Folia end -+ // Folia start - region ticking -+ public void updateTicks(long fromTickOffset, long fromRedstoneTimeOffset) { -+ if (this.activatedTick != Integer.MIN_VALUE) { -+ this.activatedTick += fromTickOffset; -+ } -+ if (this.activatedImmunityTick != Integer.MIN_VALUE) { -+ this.activatedImmunityTick += fromTickOffset; -+ } -+ } -+ // Folia end - region ticking - - public boolean isLegacyTrackingEntity = false; - -@@ -544,28 +563,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S + public CraftEntity getBukkitEntity() { +@@ -478,28 +478,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S this.isLegacyTrackingEntity = isLegacyTrackingEntity; } @@ -16459,9 +16422,26 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 - } + // Folia - region ticking // Paper end - optimise entity tracking + public float getBukkitYaw() { + return this.yRot; +@@ -566,6 +545,16 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S + + public boolean updatingSectionStatus = false; + // Paper end ++ // Folia start - region ticking ++ public void updateTicks(long fromTickOffset, long fromRedstoneTimeOffset) { ++ if (this.activatedTick != Integer.MIN_VALUE) { ++ this.activatedTick += fromTickOffset; ++ } ++ if (this.activatedImmunityTick != Integer.MIN_VALUE) { ++ this.activatedImmunityTick += fromTickOffset; ++ } ++ } ++ // Folia end - region ticking public Entity(EntityType type, Level world) { -@@ -813,6 +811,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S + this.id = Entity.ENTITY_COUNTER.incrementAndGet(); +@@ -812,6 +801,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S // CraftBukkit start public void postTick() { @@ -16474,7 +16454,7 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 // 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 if (!(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities this.handleNetherPortal(); -@@ -835,7 +839,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -834,7 +829,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S this.walkDistO = this.walkDist; this.xRotO = this.getXRot(); this.yRotO = this.getYRot(); @@ -16483,7 +16463,7 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 if (this.canSpawnSprintParticle()) { this.spawnSprintParticle(); } -@@ -944,11 +948,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -943,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); } @@ -16497,7 +16477,7 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 // CraftBukkit end - we also don't throw an event unless the object in lava is living, to save on some event calls } -@@ -1093,8 +1097,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -1093,8 +1088,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S } else { this.wasOnFire = this.isOnFire(); if (movementType == MoverType.PISTON) { @@ -16508,7 +16488,7 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 movement = this.limitPistonMovement(movement); if (movement.equals(Vec3.ZERO)) { return; -@@ -3001,7 +3005,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -2998,7 +2993,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S this.passengers = ImmutableList.copyOf(list); } @@ -16517,7 +16497,7 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 } } -@@ -3049,7 +3053,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -3046,7 +3041,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S } entity.boardingCooldown = 60; @@ -16526,7 +16506,7 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 } return true; // CraftBukkit } -@@ -3329,6 +3333,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -3326,6 +3321,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S @Nullable public PlayerTeam getTeam() { @@ -16535,10 +16515,10 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 + return null; + } + // Folia end - region threading - if (!this.level().paperConfig().scoreboards.allowNonPlayerEntitiesOnScoreboards && !(this instanceof Player)) { return null; } // Paper + if (!this.level().paperConfig().scoreboards.allowNonPlayerEntitiesOnScoreboards && !(this instanceof Player)) { return null; } // Paper - Perf: Disable Scoreboards for non players by default return this.level().getScoreboard().getPlayersTeam(this.getScoreboardName()); } -@@ -3444,9 +3453,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -3441,9 +3441,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S if (this.fireImmune()) { return; } @@ -16550,7 +16530,7 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 return; } // CraftBukkit end -@@ -3619,6 +3628,775 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -3616,6 +3616,775 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S this.portalEntrancePos = original.portalEntrancePos; } @@ -17326,7 +17306,7 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 @Nullable public Entity changeDimension(ServerLevel destination) { // CraftBukkit start -@@ -3627,6 +4405,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -3624,6 +4393,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S @Nullable public Entity teleportTo(ServerLevel worldserver, Vec3 location) { @@ -17336,9 +17316,9 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 + } + // Folia end - region threading // CraftBukkit end - // Paper start - fix bad state entities causing dupes + // Paper start - Fix item duplication and teleport issues if (!this.isAlive() || !this.valid) { -@@ -3719,6 +4502,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -3716,6 +4490,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S } } @@ -17351,7 +17331,7 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 protected void removeAfterChangingDimensions() { this.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); } -@@ -4658,7 +5447,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -4650,7 +5430,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S } } // Paper end - Fix MC-4 @@ -17361,7 +17341,7 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 synchronized (this.posLock) { // Paper this.position = new Vec3(x, y, z); } // Paper -@@ -4679,7 +5469,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -4671,7 +5452,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S // Paper start - Block invalid positions and bounding box; don't allow desync of pos and AABB // hanging has its own special logic @@ -17370,7 +17350,7 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 this.setBoundingBox(this.makeBoundingBox()); } // Paper end - Block invalid positions and bounding box -@@ -4766,6 +5556,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -4758,6 +5539,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S return this.removalReason != null; } @@ -17383,17 +17363,17 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 @Nullable public Entity.RemovalReason getRemovalReason() { return this.removalReason; -@@ -4781,6 +5577,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -4773,6 +5560,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S } // Paper end - rewrite chunk system - final boolean alreadyRemoved = this.removalReason != null; + final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers + // Folia start - region threading + this.preRemove(reason); + // Folia end - region threading if (this.removalReason == null) { this.removalReason = reason; } -@@ -4803,6 +5602,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -4795,6 +5585,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S this.removalReason = null; } @@ -17405,10 +17385,10 @@ index d0bbf39caddb801e670fe8618e723724b030190d..1ee49570e9c3250d1d3ce0420a0a0c94 /** * Invoked only when the entity is truly removed from the server, never to be added to any world. diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index f0d565ac0b3c8d3c3a200348a16e7db21ff3920a..36ec42505505af86b1a63bd8cfea5a88f4569c74 100644 +index 6523795e715e5d472739e9bc6433143115c3de8f..03e96af48a1d54d19383a3f0b270248f673ad0aa 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -275,6 +275,13 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -274,6 +274,13 @@ public abstract class LivingEntity extends Entity implements Attackable { ++this.noActionTime; // Above all the floats } // Spigot end @@ -17422,7 +17402,7 @@ index f0d565ac0b3c8d3c3a200348a16e7db21ff3920a..36ec42505505af86b1a63bd8cfea5a88 protected LivingEntity(EntityType type, Level world) { super(type, world); -@@ -480,7 +487,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -479,7 +486,7 @@ public abstract class LivingEntity extends Entity implements Attackable { if (this.isDeadOrDying() && this.level().shouldTickDeath(this)) { this.tickDeath(); @@ -17431,7 +17411,7 @@ index f0d565ac0b3c8d3c3a200348a16e7db21ff3920a..36ec42505505af86b1a63bd8cfea5a88 if (this.lastHurtByPlayerTime > 0) { --this.lastHurtByPlayerTime; -@@ -626,11 +633,14 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -625,11 +632,14 @@ public abstract class LivingEntity extends Entity implements Attackable { return true; } @@ -17448,7 +17428,7 @@ index f0d565ac0b3c8d3c3a200348a16e7db21ff3920a..36ec42505505af86b1a63bd8cfea5a88 } } -@@ -852,9 +862,9 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -851,9 +861,9 @@ public abstract class LivingEntity extends Entity implements Attackable { } this.hurtTime = nbt.getShort("HurtTime"); @@ -17459,7 +17439,7 @@ index f0d565ac0b3c8d3c3a200348a16e7db21ff3920a..36ec42505505af86b1a63bd8cfea5a88 + if (false && nbt.contains("Team", 8)) { // Folia start - region threading String s = nbt.getString("Team"); PlayerTeam scoreboardteam = this.level().getScoreboard().getPlayerTeam(s); - if (!this.level().paperConfig().scoreboards.allowNonPlayerEntitiesOnScoreboards && !(this instanceof net.minecraft.world.entity.player.Player)) { scoreboardteam = null; } // Paper + if (!this.level().paperConfig().scoreboards.allowNonPlayerEntitiesOnScoreboards && !(this instanceof net.minecraft.world.entity.player.Player)) { scoreboardteam = null; } // Paper - Perf: Disable Scoreboards for non players by default @@ -1140,6 +1150,7 @@ public abstract class LivingEntity extends Entity implements Attackable { public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) { // Paper end - Don't fire sync event during generation @@ -17468,7 +17448,7 @@ index f0d565ac0b3c8d3c3a200348a16e7db21ff3920a..36ec42505505af86b1a63bd8cfea5a88 if (this.isTickingEffects) { this.effectsToProcess.add(new ProcessableEffect(mobeffect, cause)); return true; -@@ -2337,7 +2348,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2338,7 +2349,7 @@ public abstract class LivingEntity extends Entity implements Attackable { @Nullable public LivingEntity getKillCredit() { @@ -17477,7 +17457,7 @@ index f0d565ac0b3c8d3c3a200348a16e7db21ff3920a..36ec42505505af86b1a63bd8cfea5a88 } public final float getMaxHealth() { -@@ -3480,7 +3491,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3481,7 +3492,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.pushEntities(); this.level().getProfiler().pop(); // Paper start - Add EntityMoveEvent @@ -17485,7 +17465,7 @@ index f0d565ac0b3c8d3c3a200348a16e7db21ff3920a..36ec42505505af86b1a63bd8cfea5a88 + if (((ServerLevel) this.level()).getCurrentWorldData().hasEntityMoveEvent && !(this instanceof net.minecraft.world.entity.player.Player)) { // Folia - region threading if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) { Location from = new Location(this.level().getWorld(), this.xo, this.yo, this.zo, this.yRotO, this.xRotO); - Location to = new Location (this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + Location to = new Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); @@ -4174,7 +4185,7 @@ public abstract class LivingEntity extends Entity implements Attackable { BlockPos blockposition = BlockPos.containing(d0, d1, d2); Level world = this.level(); @@ -17496,7 +17476,7 @@ index f0d565ac0b3c8d3c3a200348a16e7db21ff3920a..36ec42505505af86b1a63bd8cfea5a88 while (!flag2 && blockposition.getY() > world.getMinBuildHeight()) { diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 5e51fd71bb6bc679ea6df3f021b46aa555be3cf2..4e770f3b781be4c282d1e81c327fb2fb06b5af1f 100644 +index 24629412d2b4acaa81788ce70412b03387cc777c..a1a0ac986e2052d3669428a29987630bc226d80f 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java @@ -137,6 +137,14 @@ public abstract class Mob extends LivingEntity implements Targeting { @@ -17683,13 +17663,13 @@ index c0da573e3818a1dd2c1ef5a61c7cb34934b0a252..d34a3018264ec196ef57151af3c1d584 this.navigation.stop(); return true; diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -index ac996b066415e461af1fcb71b19807401179c7f8..c065d372ac5f1663db3c521e996ee03669d0bc31 100644 +index 47de460ff5435ea6712c800c77093126908d0fce..b31ba4e2286eaee5028cb4dc236829d1a302a25a 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java @@ -42,6 +42,11 @@ public class GroundPathNavigation extends PathNavigation { @Override - public Path createPath(BlockPos target, @javax.annotation.Nullable Entity entity, int distance) { // Paper + public Path createPath(BlockPos target, @javax.annotation.Nullable Entity entity, int distance) { // Paper - EntityPathfindEvent + // Folia start - region threading + if (!io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level, target)) { + return null; @@ -17699,7 +17679,7 @@ index ac996b066415e461af1fcb71b19807401179c7f8..c065d372ac5f1663db3c521e996ee036 if (levelChunk == null) { return null; diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index b37415d45dda8e658c8995a4519e552dc378bb41..147057bfd67d56857b5d3ab1ebd0f0a0c1793a9c 100644 +index a04fb58c29b462e20ed0b702cef478e3985b7cd2..089baec30e0c16149b147a501d68958663519b96 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java @@ -80,11 +80,11 @@ public abstract class PathNavigation { @@ -17716,16 +17696,16 @@ index b37415d45dda8e658c8995a4519e552dc378bb41..147057bfd67d56857b5d3ab1ebd0f0a0 this.hasDelayedRecomputation = false; } } else { -@@ -199,7 +199,7 @@ public abstract class PathNavigation { +@@ -200,7 +200,7 @@ public abstract class PathNavigation { public boolean moveTo(Entity entity, double speed) { - // Paper start - Pathfinding optimizations + // Paper start - Perf: Optimise pathfinding - if (this.pathfindFailures > 10 && this.path == null && net.minecraft.server.MinecraftServer.currentTick < this.lastFailure + 40) { + if (this.pathfindFailures > 10 && this.path == null && this.tick < this.lastFailure + 40) { // Folia - region threading return false; } - // Paper end -@@ -211,7 +211,7 @@ public abstract class PathNavigation { + // Paper end - Perf: Optimise pathfinding +@@ -212,7 +212,7 @@ public abstract class PathNavigation { return true; } else { this.pathfindFailures++; @@ -17733,7 +17713,7 @@ index b37415d45dda8e658c8995a4519e552dc378bb41..147057bfd67d56857b5d3ab1ebd0f0a0 + this.lastFailure = this.tick; // Folia - region threading return false; } - // Paper end + // Paper end - Perf: Optimise pathfinding diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/TemptingSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/TemptingSensor.java index e3242cf9a6ad51a23c5781142198dec30c8f376d..f32f5982ceb368b240062b9b8ac0141be59e2f1e 100644 --- a/src/main/java/net/minecraft/world/entity/ai/sensing/TemptingSensor.java @@ -17748,7 +17728,7 @@ index e3242cf9a6ad51a23c5781142198dec30c8f376d..f32f5982ceb368b240062b9b8ac0141b }).filter((entityplayer) -> { return entity.closerThan(entityplayer, 10.0D); diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -index fed09b886f4fa0006d160e5f2abb00dfee45434d..37a86fe9585ebf004876a48808e19eb272e2372d 100644 +index 2b5b2869589991be37a4f128faabbff50e661470..c8d4878a0574a603bbb4bce45d1fb4d84b7ac6ce 100644 --- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java @@ -22,62 +22,66 @@ import org.slf4j.Logger; @@ -17933,7 +17913,7 @@ index 12a7aaeaa8b4b788b620b1985591c3b93253ccd5..5150d447c9dc2f539446749c8bee1020 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index a87a34b0c4c8e5d0cf079025c230b1434c919b54..cbb0ebf003f5d832be1937aa886802df3f06b12a 100644 +index f9521a6e115f0c975a7885b024c99eae300b63bf..9f1791e60061934fc89a13258f3fab9f67f3a45c 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java @@ -1043,6 +1043,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @@ -17974,7 +17954,7 @@ index f760ce7d9df79ef58f8963de3e901cba3e12fcaa..03bd7038bda7bd3bf592eab39ec6d985 this.setPersistenceRequired(); } 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..68e8e82f4c3406b1ed5c079e68806f893e5f3e5e 100644 +index d595f1590619b24d460fc2c10a5412844f62cba0..520f9da801d2d0420feb2af5ab63bf234a72b705 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 { @@ -18005,10 +17985,10 @@ index 80303f9466b8c7097151be313afc9a383693d18a..d53905cafc7bf257907e6c9b9ea2ba97 }); 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 21a4669b01e9c57100224e20500bc23f8e101434..9e35c0c493962b70607649af08d800b4ca29b188 100644 +index 9daf8aa557d9f4fdbcc138a47892ea5a061dd877..25b7b85cbd1130c5320e55b3c6b6f81ec228da81 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 { +@@ -293,9 +293,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) -> { @@ -18021,7 +18001,7 @@ index 21a4669b01e9c57100224e20500bc23f8e101434..9e35c0c493962b70607649af08d800b4 boolean flag = this.blockState.is(BlockTags.ANVIL); diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java -index 292c343683de4701418d2a9e14158e49f595c1f2..ba130ad4936d8e8bed8d028492dc0c6dbd51d496 100644 +index eb0d6238588efa35fa868f26290547574a08eca2..7c416a0e4734e6987279cfbb34103a0bf00ed087 100644 --- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java @@ -54,7 +54,7 @@ public class ItemEntity extends Entity implements TraceableEntity { @@ -18030,8 +18010,8 @@ index 292c343683de4701418d2a9e14158e49f595c1f2..ba130ad4936d8e8bed8d028492dc0c6d public final float bobOffs; - private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit + //private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit // Folia - region threading - public boolean canMobPickup = true; // Paper - private int despawnRate = -1; // Paper + public boolean canMobPickup = true; // Paper - Item#canEntityPickup + private int despawnRate = -1; // Paper - Alternative item-despawn-rate public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API @@ -144,13 +144,11 @@ public class ItemEntity extends Entity implements TraceableEntity { this.discard(); @@ -18086,7 +18066,7 @@ index 292c343683de4701418d2a9e14158e49f595c1f2..ba130ad4936d8e8bed8d028492dc0c6d + } + // Folia end - region threading - restore original timers - if (!this.level().isClientSide && this.age >= this.despawnRate) { // Spigot // Paper + if (!this.level().isClientSide && this.age >= this.despawnRate) { // Spigot // Paper - Alternative item-despawn-rate // CraftBukkit start - fire ItemDespawnEvent @@ -548,14 +547,20 @@ public class ItemEntity extends Entity implements TraceableEntity { return false; @@ -18113,7 +18093,7 @@ index 292c343683de4701418d2a9e14158e49f595c1f2..ba130ad4936d8e8bed8d028492dc0c6d return entity; } diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -index 2274541c9386e4f1bbae489a1f123d502ccbf9cc..b0b50f1398d0b5dbc8b482aa94c8b5d7296891e4 100644 +index cd7b955754b809826048b80723e2e9055b373a4a..9a48c2d943241a6d53daecf7e8125b7aeca77b38 100644 --- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java @@ -71,7 +71,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { @@ -18148,7 +18128,7 @@ index 30ea3f64234fd1fda8dada3c7fb12be0730322a8..395c7763db5f748911639336e3274d4c } 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 142650302dbab411e37bc1957825e3db0c50deac..f2fdc5607b3292c585aab151f6ff8d6fcba83cd3 100644 +index 5c40e994007dbf46ebc12c1e6a6ca90379471b74..723ef6e7a3618c30087ce2ac50811dbe638881ec 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java @@ -95,7 +95,7 @@ public class Zombie extends Monster { @@ -18156,8 +18136,8 @@ index 142650302dbab411e37bc1957825e3db0c50deac..f2fdc5607b3292c585aab151f6ff8d6f private int inWaterTime; public int conversionTime; - private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field -+ // private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field // Folia - region threading - restore original timers - private boolean shouldBurnInDay = true; // Paper ++ //private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field // Folia - region threading - restore original timers + private boolean shouldBurnInDay = true; // Paper - Add more Zombie API public Zombie(EntityType type, Level world) { @@ -218,10 +218,7 @@ public class Zombie extends Monster { @@ -18183,7 +18163,7 @@ index 142650302dbab411e37bc1957825e3db0c50deac..f2fdc5607b3292c585aab151f6ff8d6f @Override @@ -277,7 +274,7 @@ public class Zombie extends Monster { } - // Paper end + // Paper end - Add more Zombie API public void startUnderWaterConversion(int ticksUntilWaterConversion) { - this.lastTick = MinecraftServer.currentTick; // CraftBukkit + // Folia - region threading - restore original timers @@ -18277,7 +18257,7 @@ index 5f407535298a31a34cfe114dd863fd6a9b977707..cb0f75fb32836efa50f0a86dfae7907b return 0; } else { diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 5c2010fb247462433bed6ae58d88a72c4e137ede..a7857a7d141a552f800d7becd130e0cf1660e886 100644 +index 1aae466e3e334d7f4bbb3ea9365a255afcc3dd3a..853c777bad19656cd48e9de9015c12e2c078d940 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -203,7 +203,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @@ -18400,7 +18380,7 @@ index d7bddedb19c10f62fd1f7d3128453ad706ed16be..948749a0a3ef9d06f0482bc5331a5283 entityvillagertrader.setWanderTarget(blockposition1); entityvillagertrader.restrictTo(blockposition1, 16); diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 9044458491fc9a33923852e324a15ac59d6660b2..542bc7657f21d0a987a865e495360eeffe0d934a 100644 +index df8d6f3eb675354ce0d180fc56886ce12788d6ae..07855c28a032c5d3d1e2056d817d788cd86442d9 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java @@ -1519,6 +1519,14 @@ public abstract class Player extends LivingEntity { @@ -18419,7 +18399,7 @@ index 9044458491fc9a33923852e324a15ac59d6660b2..542bc7657f21d0a987a865e495360eef return false; } diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -index 5a2144417783f859729fc93281edd9d577c59ca2..6264a02c0bef70618787dce262d80681231f32f4 100644 +index d14eab0d83d629a4522bf3f7d789d2853eb84f06..32ac9ffb1655e370255f2f3fe62b756217988196 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java @@ -156,6 +156,11 @@ public abstract class AbstractArrow extends Projectile { @@ -18507,7 +18487,7 @@ index b2f08889139dc447f7071f1c81456035bf8de31e..619bedc55d61f83dbc5adcf76a739cf9 } } diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index 5706c9b744b660d6f7639b8152dce82799c4b466..67e4a0eea8312cf6389a374c12e5fd054ec6284b 100644 +index 90a5f6bd729148f2adc745273536e48d704fcd1e..702949d3d4c46222d2ef8227a559acd54d399bc0 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java @@ -104,7 +104,7 @@ public class FishingHook extends Projectile { @@ -18576,7 +18556,7 @@ index 0bbe853f7df93f9dcd2b21d762939f8b6be069aa..4f4d6dedb99feac995e9b5bdf1d5c9f1 HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index 5b6d5c799cc8e601a01b6967917e15ba1e2db721..8bd77418e7303443640bfa9ac0e3c6ce1f808b8c 100644 +index 156809090f1f83ad68e7e2477a3cfddac5757a8e..10d7c64fb3a9bafdcdae99f8dc87017722341337 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java @@ -70,9 +70,20 @@ public abstract class Projectile extends Entity implements TraceableEntity { @@ -18967,7 +18947,7 @@ index 42d87800a328f71c5127ce5599ca4c71cc9bb1cd..4b08175b71e7f92e9bb578f9f6c2c0ef } diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 46c7c36a07169915f7409f1146e5066e8ac65c21..a7ebeaf507c131897f3c75084112180c856b065c 100644 +index ed27a963223bfe18310ad5adabf461b5e307ef9c..c9a40483db8750db8dc0fa7ffc80b97786486ff6 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java @@ -378,31 +378,32 @@ public final class ItemStack { @@ -19033,8 +19013,8 @@ index 46c7c36a07169915f7409f1146e5066e8ac65c21..a7ebeaf507c131897f3c75084112180c enuminteractionresult = InteractionResult.FAIL; // cancel placement // PAIL: Remove this when MC-99075 fixed placeEvent.getPlayer().updateInventory(); -- world.capturedTileEntities.clear(); // Paper - clear out tile entities as chests and such will pop loot -+ worldData.capturedTileEntities.clear(); // Paper - clear out tile entities as chests and such will pop loot // Folia - region threading +- world.capturedTileEntities.clear(); // Paper - Allow chests to be placed with NBT data; clear out block entities as chests and such will pop loot ++ worldData.capturedTileEntities.clear(); // Paper - Allow chests to be placed with NBT data; clear out block entities as chests and such will pop loot // Folia - region threading // revert back all captured blocks - world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710 + worldData.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710 // Folia - region threading @@ -19067,7 +19047,7 @@ index 46c7c36a07169915f7409f1146e5066e8ac65c21..a7ebeaf507c131897f3c75084112180c return enuminteractionresult; diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java -index 797415866a7f182d804f6b8e57ceb07a6ac2a20a..a6269b362964857ad3f97e6e6c2f7574d92d67e3 100644 +index d8dd99ec8bf7444c5a3c426db3a9c13e334dc0ff..5204449e94eeadb9b0485a0b4ff876196f40051c 100644 --- a/src/main/java/net/minecraft/world/item/MapItem.java +++ b/src/main/java/net/minecraft/world/item/MapItem.java @@ -95,6 +95,7 @@ public class MapItem extends ComplexItem { @@ -19181,7 +19161,7 @@ index 524b0f1086c01888fe0b76e180c40915d16a1eb9..50b3025189938374886c7e2725dd3e4d this.lastOutput = Component.literal("[" + simpledateformat.format(date) + "] ").append(message); diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index ff0b7b9e4ae3aa0c170d05bc51fd7ff26e7531ee..b37d36e5ecac85a383216e5c85bebb99e3367251 100644 +index ed84c87a3f76bc0254c1abb189e6b8b808823465..894a25e9dfd61b8409f2883fc0af7c799cf5aabe 100644 --- a/src/main/java/net/minecraft/world/level/EntityGetter.java +++ b/src/main/java/net/minecraft/world/level/EntityGetter.java @@ -38,6 +38,12 @@ public interface EntityGetter { @@ -19217,7 +19197,7 @@ index ff0b7b9e4ae3aa0c170d05bc51fd7ff26e7531ee..b37d36e5ecac85a383216e5c85bebb99 @@ -177,7 +183,7 @@ public interface EntityGetter { - // Paper start + // Paper start - Affects Spawning API default boolean hasNearbyAlivePlayerThatAffectsSpawning(double x, double y, double z, double range) { - for (Player player : this.players()) { + for (Player player : this.getLocalPlayers()) { // Folia - region threading @@ -19225,7 +19205,7 @@ index ff0b7b9e4ae3aa0c170d05bc51fd7ff26e7531ee..b37d36e5ecac85a383216e5c85bebb99 double distanceSqr = player.distanceToSqr(x, y, z); if (range < 0.0D || distanceSqr < range * range) { @@ -190,7 +196,7 @@ public interface EntityGetter { - // Paper end + // Paper end - Affects Spawning API default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) { - for(Player player : this.players()) { @@ -19274,7 +19254,7 @@ index ff0b7b9e4ae3aa0c170d05bc51fd7ff26e7531ee..b37d36e5ecac85a383216e5c85bebb99 return player; } diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 210b6d71207b99e66ba014b176b2c1445053b1d1..53dc4270590ea41c068e35004dab27e1e053abcb 100644 +index 28ef910885dbd48965fba6f08cec412697b1b7f0..d38d88062bac04c8c03f4e43d55fe8ee7deaaabc 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 { @@ -19318,25 +19298,25 @@ index 210b6d71207b99e66ba014b176b2c1445053b1d1..53dc4270590ea41c068e35004dab27e1 private final double posX, posY, posZ; private final double minX, minY, minZ; diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c2f500b5d 100644 +index 19f23a6c8fb5c02843c27fb8a242ec9d0d1b538b..2b8674034979e3f8d45362f7cbae3c1b453834ee 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -120,10 +120,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -115,10 +115,10 @@ 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 +- public final List blockEntityTickers = Lists.newArrayList(); // Paper - public - protected final NeighborUpdater neighborUpdater; - private final List pendingBlockEntityTickers = Lists.newArrayList(); - private boolean tickingBlockEntities; -+ //protected final List blockEntityTickers = Lists.newArrayList(); public final int getTotalTileEntityTickers() { return this.blockEntityTickers.size(); } // Paper // Folia - region threading -+ public final int neighbourUpdateMax; //protected final NeighborUpdater neighborUpdater; ++ //public final List blockEntityTickers = Lists.newArrayList(); // Paper - public // Folia - region threading ++ public final int neighbourUpdateMax; //protected final NeighborUpdater neighborUpdater; // Folia - region threading + //private final List pendingBlockEntityTickers = Lists.newArrayList(); // Folia - region threading + //private boolean tickingBlockEntities; // Folia - region threading public final Thread thread; private final boolean isDebug; private int skyDarken; -@@ -133,7 +133,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -128,7 +128,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public float rainLevel; protected float oThunderLevel; public float thunderLevel; @@ -19345,7 +19325,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c /** @deprecated */ @Deprecated private final RandomSource threadSafeRandom = RandomSource.createThreadSafe(); -@@ -147,7 +147,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -142,7 +142,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { private final ResourceKey dimension; private final RegistryAccess registryAccess; private final DamageSources damageSources; @@ -19354,9 +19334,9 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c // CraftBukkit start Added the following private final CraftWorld world; -@@ -156,20 +156,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -150,20 +150,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean keepSpawnInMemory = true; public org.bukkit.generator.ChunkGenerator generator; - public static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper - public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710 - public boolean captureBlockStates = false; @@ -19378,20 +19358,20 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot // Paper start - add paper world config private final io.papermc.paper.configuration.WorldConfiguration paperConfig; -@@ -183,9 +173,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -177,9 +167,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; private org.spigotmc.TickLimiter tileLimiter; - private int tileTickPosition; - public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions -- public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here +- public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Faster redstone torch rapid clock removal; Move from Map in BlockRedstoneTorch to here + //private int tileTickPosition; // Folia - region threading + //public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions // Folia - region threading -+ //public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here // Folia - region threading ++ //public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Faster redstone torch rapid clock removal; Move from Map in BlockRedstoneTorch to here // Folia - region threading // Paper start - fix and optimise world upgrading // copied from below -@@ -213,6 +203,33 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -207,6 +197,33 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public abstract ResourceKey getTypeKey(); @@ -19425,7 +19405,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c 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 - create paper world config -@@ -256,7 +273,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -250,7 +267,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { this.thread = Thread.currentThread(); this.biomeManager = new BiomeManager(this, i); this.isDebug = flag1; @@ -19434,7 +19414,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c this.registryAccess = iregistrycustom; this.damageSources = new DamageSources(iregistrycustom); // CraftBukkit start -@@ -849,8 +866,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -839,8 +856,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Nullable public final BlockState getBlockStateIfLoaded(BlockPos pos) { // CraftBukkit start - tree generation @@ -19445,7 +19425,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c if (previous != null) { return previous.getHandle(); } -@@ -912,16 +929,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -902,16 +919,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Override public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { @@ -19454,10 +19434,10 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { + if (worldData.captureTreeGeneration) { // Folia - region threading - // Paper start + // Paper start - Protect Bedrock and End Portal/Frames from being destroyed BlockState type = getBlockState(pos); if (!type.isDestroyable()) return false; - // Paper end + // Paper end - Protect Bedrock and End Portal/Frames from being destroyed - CraftBlockState blockstate = this.capturedBlockStates.get(pos); + CraftBlockState blockstate = worldData.capturedBlockStates.get(pos); // Folia - region threading if (blockstate == null) { @@ -19467,7 +19447,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c } blockstate.setFlag(flags); // Paper - update the flag also blockstate.setData(state); -@@ -938,10 +957,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -928,10 +947,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { // CraftBukkit start - capture blockstates boolean captured = false; @@ -19480,7 +19460,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c captured = true; } // CraftBukkit end -@@ -951,8 +970,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -941,8 +960,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { if (iblockdata1 == null) { // CraftBukkit start - remove blockstate if failed (or the same) @@ -19491,7 +19471,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c } // CraftBukkit end return false; -@@ -989,7 +1008,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -979,7 +998,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { */ // CraftBukkit start @@ -19500,16 +19480,16 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c // Modularize client and physic updates // Spigot start try { -@@ -1039,7 +1058,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1029,7 +1048,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam CraftWorld world = ((ServerLevel) this).getWorld(); boolean cancelledUpdates = false; // Paper - Fix block place logic -- if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper -+ if (world != null && ((ServerLevel)this).getCurrentWorldData().hasPhysicsEvent) { // Paper // Folia - region threading +- if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent ++ if (world != null && ((ServerLevel)this).getCurrentWorldData().hasPhysicsEvent) { // Paper - BlockPhysicsEvent // Folia - region threading BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); this.getCraftServer().getPluginManager().callEvent(event); -@@ -1053,7 +1072,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1043,7 +1062,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } // CraftBukkit start - SPIGOT-5710 @@ -19518,7 +19498,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); } // CraftBukkit end -@@ -1137,7 +1156,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1127,7 +1146,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Override public void neighborShapeChanged(Direction direction, BlockState neighborState, BlockPos pos, BlockPos neighborPos, int flags, int maxUpdateDepth) { @@ -19527,7 +19507,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c } @Override -@@ -1162,11 +1181,34 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1152,11 +1171,34 @@ public abstract class Level implements LevelAccessor, AutoCloseable { return this.getChunkSource().getLightEngine(); } @@ -19564,7 +19544,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c if (previous != null) { return previous.getHandle(); } -@@ -1263,7 +1305,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1253,7 +1295,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } public void addBlockEntityTicker(TickingBlockEntity ticker) { @@ -19573,7 +19553,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c } protected void tickBlockEntities() { -@@ -1271,11 +1313,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1261,11 +1303,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { gameprofilerfiller.push("blockEntities"); this.timings.tileEntityPending.startTiming(); // Spigot @@ -19589,10 +19569,10 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c this.timings.tileEntityPending.stopTiming(); // Spigot this.timings.tileEntityTick.startTiming(); // Spigot -@@ -1286,9 +1327,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1276,9 +1317,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { 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); @@ -19601,7 +19581,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c // Spigot end if (tickingblockentity.isRemoved()) { -@@ -1299,19 +1339,19 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1289,19 +1329,19 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) { tickingblockentity.tick(); // Paper start - execute chunk tasks during tick @@ -19612,8 +19592,8 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c // Paper end - execute chunk tasks during tick } } -- this.blockEntityTickers.removeAll(toRemove); -+ blockEntityTickers.removeAll(toRemove); // Folia - regionised ticking +- this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 ++ blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 // Folia - regionised ticking this.timings.tileEntityTick.stopTiming(); // Spigot - this.tickingBlockEntities = false; @@ -19626,17 +19606,17 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c } public void guardEntityTick(Consumer tickConsumer, T entity) { -@@ -1324,7 +1364,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1314,7 +1354,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ()); MinecraftServer.LOGGER.error(msg, throwable); - getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); + getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable))); // Paper - ServerExceptionEvent - entity.discard(); + if (!(entity instanceof net.minecraft.server.level.ServerPlayer)) entity.discard(); // Folia - properly disconnect players + if (entity instanceof net.minecraft.server.level.ServerPlayer player) player.connection.disconnect(net.minecraft.network.chat.Component.translatable("multiplayer.disconnect.generic"), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); // Folia - properly disconnect players - // Paper end + // Paper end - Prevent block entity and entity crashes } } -@@ -1424,9 +1465,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1414,9 +1455,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Nullable public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) { @@ -19645,14 +19625,14 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c + return null; + } + // Folia end - region threading - // 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) { + if (!this.getCurrentWorldData().capturedTileEntities.isEmpty() && (blockEntity = this.getCurrentWorldData().capturedTileEntities.get(blockposition)) != null) { // Folia - region threading return blockEntity; } - // Paper end -@@ -1439,8 +1485,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Paper end - Perf: Optimize capturedTileEntities lookup +@@ -1429,8 +1475,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { if (!this.isOutsideBuildHeight(blockposition)) { // CraftBukkit start @@ -19663,7 +19643,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c return; } // CraftBukkit end -@@ -1520,6 +1566,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1510,6 +1556,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Override public List getEntities(@Nullable Entity except, AABB box, Predicate predicate) { @@ -19671,7 +19651,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c this.getProfiler().incrementCounter("getEntities"); List list = Lists.newArrayList(); ((ServerLevel)this).getEntityLookup().getEntities(except, box, list, predicate); // Paper - optimise this call -@@ -1539,6 +1586,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1529,6 +1576,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } public void getEntities(EntityTypeTest filter, AABB box, Predicate predicate, List result, int limit) { @@ -19679,7 +19659,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c this.getProfiler().incrementCounter("getEntities"); // Paper start - optimise this call //TODO use limit -@@ -1576,13 +1624,30 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1566,13 +1614,30 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public void disconnect() {} @@ -19712,7 +19692,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c public boolean mayInteract(Player player, BlockPos pos) { return true; -@@ -1786,8 +1851,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1776,8 +1841,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 @@ -19722,7 +19702,7 @@ index 0c1d7265dee638642f7c868e2f988af7b59e6d7e..7334a522956649fdf606b560d52e127c out.set(x + (i1 & 15), y + (i1 >> 16 & l), z + (i1 >> 8 & 15)); // Paper - change to setValues call return out; // Paper -@@ -1818,7 +1882,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1808,7 +1872,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Override public long nextSubTickCount() { @@ -19791,7 +19771,7 @@ index 12eaafdbd324fa36b3f46c3b644bc8117a4123ad..c8c358a2ce567567159039ed6a1ba804 @Deprecated default boolean hasChunksAt(int minX, int minZ, int maxX, int maxZ) { diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 46d743db099e69e10f5534aafdd7aa5eda67dec9..1d082e977442790504e3ca70a90dabd69b522622 100644 +index da7489986848316fed029b71d1bc4e1248c9c9a8..9c1263fdc3731e04ac28c6d0ed904ecdc3ea3038 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java @@ -146,7 +146,7 @@ public final class NaturalSpawner { @@ -19871,7 +19851,7 @@ index b59581b92aed0bc1b09008c695b0b112c3e65743..e91f36528862c0ee4c5b5d765113fdaf } diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java -index 8677dc684bd2e0bb3cf5f77b659ce02b79627e76..da7d65595efee6731b1d87810b4220182bfcccb5 100644 +index 38fcde81d797dc46409f5a9ed426fe296d79bdfa..11ba667fd0fe79513d505b34eb0cf1ec66fc2842 100644 --- a/src/main/java/net/minecraft/world/level/block/BedBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java @@ -367,7 +367,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock @@ -19884,10 +19864,10 @@ index 8677dc684bd2e0bb3cf5f77b659ce02b79627e76..da7d65595efee6731b1d87810b422018 } // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 73d6f881a7d4d8ff96040d34ac502e5b0937d577..326f5931f35e7528a8b801be6d92d62cebf83823 100644 +index 22036ed3ea0629bc12981a8d91a03e55cc2117d6..6df3913145aaf37f9a1b7dc77fed12f6952d77e6 100644 --- a/src/main/java/net/minecraft/world/level/block/Block.java +++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -397,8 +397,8 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -398,8 +398,8 @@ public class Block extends BlockBehaviour implements ItemLike { entityitem.setDefaultPickUpDelay(); // CraftBukkit start @@ -19912,7 +19892,7 @@ index bed3d9c781c7d3ca260027b4737970889a54689c..46c81d73813c6607d95062358e6e3cd0 } } 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 88ca50038b483fe5c207ef5c2bf3ea87540e147e..db07c9233a4e92dc5f505af6141c0c0ccf7ae5d3 100644 +index 232a3a0332d8d2c1ec625f3f2155316c69d95153..75d03ee9bdd3ad4f43d52b29f6c90642e36b5fc9 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 { @@ -19957,7 +19937,7 @@ index de6f00d03223939386aa2ccfdec1e696a68313d7..eb7c2c5b762dbadbe9ccbddc37757bdf } 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 1ee863ec252872deb15a6b96f1d937c672ce5898..33820e1325d6296bd4b36871088fe52fa265eba3 100644 +index 644e64850479cea20a98b8a65503ccf3a34fd32a..321779653c5b1f528673b7aad01f544cc200be58 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,7 @@ public class DispenserBlock extends BaseEntityBlock { @@ -19972,7 +19952,7 @@ index 1ee863ec252872deb15a6b96f1d937c672ce5898..33820e1325d6296bd4b36871088fe52f @@ -105,7 +105,7 @@ public class DispenserBlock extends BaseEntityBlock { if (idispensebehavior != DispenseItemBehavior.NOOP) { - if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(world, pos, itemstack, i)) return; // Paper - Add BlockPreDispenseEvent + 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 // Folia - region threading tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); @@ -19992,17 +19972,17 @@ index 03b5ab8251497c0c94467f90e6663a0dc766babb..4fb595a8300ce2b163540603c7a2b002 } // CraftBukkit end 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 47eb8bf604a63259c0200cada1403dc005a6cbac..e78c5364e086d29c88dac8a1e993b1d6c1bc6d96 100644 +index 6e4c852c93f2418ea69e485ed3a10cbe3a6e3bd2..ab2b9b85b844cf3e6ef5a0379fa3279b85a7328c 100644 --- a/src/main/java/net/minecraft/world/level/block/FarmBlock.java +++ b/src/main/java/net/minecraft/world/level/block/FarmBlock.java @@ -92,8 +92,8 @@ public class FarmBlock extends Block { @Override public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { int i = (Integer) state.getValue(FarmBlock.MOISTURE); -- 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 || (world.getRedstoneGameTime() + pos.hashCode()) % world.paperConfig().tickRates.wetFarmland != 0)) { return; } // Paper // Folia - region threading -+ if (i == 0 && world.paperConfig().tickRates.dryFarmland != 1 && (world.paperConfig().tickRates.dryFarmland < 1 || (world.getRedstoneGameTime() + pos.hashCode()) % world.paperConfig().tickRates.dryFarmland != 0)) { return; } // Paper // Folia - region threading +- 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 ++ if (i > 0 && world.paperConfig().tickRates.wetFarmland != 1 && (world.paperConfig().tickRates.wetFarmland < 1 || (world.getRedstoneGameTime() + pos.hashCode()) % world.paperConfig().tickRates.wetFarmland != 0)) { return; } // Paper - Configurable random tick rates for blocks // Folia - region threading ++ if (i == 0 && world.paperConfig().tickRates.dryFarmland != 1 && (world.paperConfig().tickRates.dryFarmland < 1 || (world.getRedstoneGameTime() + pos.hashCode()) % world.paperConfig().tickRates.dryFarmland != 0)) { return; } // Paper - Configurable random tick rates for blocks // Folia - region threading if (!FarmBlock.isNearWater(world, pos) && !world.isRainingAt(pos.above())) { if (i > 0) { @@ -20094,7 +20074,7 @@ index e310abaca79615caaa75d92183a57242734266a3..ea78392580e2cc71fd95a682ec69774f super.fallOn(world, state, pos, entity, fallDistance); } diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java -index 7339795addfeaedc3c8a7db03f73546fb5fba06b..875a776d5aa1399808e5d5eab1c608dd35011c85 100644 +index b5a71fd4e2f55bf036c2c697da5d50cc90fc657c..18cb719ae55b736a6dade61237a845c866fb6858 100644 --- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java @@ -69,7 +69,7 @@ public class RedStoneWireBlock extends Block { @@ -20213,13 +20193,13 @@ index 7339795addfeaedc3c8a7db03f73546fb5fba06b..875a776d5aa1399808e5d5eab1c608dd public static int getColorForPower(int powerLevel) { diff --git a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java -index 6c49962e8f9e2a5fca50b33f3e3fff76fa36f907..aebb26f379cd3bdb39432c8b70c6d382e02070c7 100644 +index 1dbfda52a4423fb031eecad24e5766f49ecf6050..332f606d9a41ab19707f2f11bd43d2880b410180 100644 --- a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java +++ b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java @@ -81,10 +81,10 @@ public class RedstoneTorchBlock extends BaseTorchBlock { public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { boolean flag = this.hasNeighborSignal(world, pos, state); - // Paper start + // Paper start - Faster redstone torch rapid clock removal - java.util.ArrayDeque redstoneUpdateInfos = world.redstoneUpdateInfos; + java.util.ArrayDeque redstoneUpdateInfos = world.getCurrentWorldData().redstoneUpdateInfos; // Folia - region threading if (redstoneUpdateInfos != null) { @@ -20232,14 +20212,14 @@ index 6c49962e8f9e2a5fca50b33f3e3fff76fa36f907..aebb26f379cd3bdb39432c8b70c6d382 @@ -165,14 +165,14 @@ public class RedstoneTorchBlock extends BaseTorchBlock { private static boolean isToggledTooFrequently(Level world, BlockPos pos, boolean addNew) { - // Paper start + // Paper start - Faster redstone torch rapid clock removal - java.util.ArrayDeque list = world.redstoneUpdateInfos; + java.util.ArrayDeque list = world.getCurrentWorldData().redstoneUpdateInfos; // Folia - region threading if (list == null) { - list = world.redstoneUpdateInfos = new java.util.ArrayDeque<>(); + list = world.getCurrentWorldData().redstoneUpdateInfos = new java.util.ArrayDeque<>(); // Folia - region threading } - + // Paper end - Faster redstone torch rapid clock removal if (addNew) { - list.add(new RedstoneTorchBlock.Toggle(pos.immutable(), world.getGameTime())); @@ -20310,15 +20290,15 @@ index 836c86104ed4f0d375330c9123af5d502efefa4d..68bd6dfb3b99b8e524f808effd129927 if (treeType != null) { event = new StructureGrowEvent(location, treeType, false, null, blocks); diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java -index 35a70bd30bc4beb06de4bb6e305ec3a787b43044..aaece21bcafc8b76c2c5e2f63458ac596a892bc1 100644 +index f3003a3832deff7724d28b4b3a091f4802a4cb29..d628cee1f72ee973bc10a49f2dd65becab85e28c 100644 --- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java @@ -55,7 +55,7 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock { @Override public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { -- if (this instanceof GrassBlock && world.paperConfig().tickRates.grassSpread != 1 && (world.paperConfig().tickRates.grassSpread < 1 || (MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper -+ if (this instanceof GrassBlock && world.paperConfig().tickRates.grassSpread != 1 && (world.paperConfig().tickRates.grassSpread < 1 || (io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() + pos.hashCode()) % world.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper // Folia - regionised ticking +- if (this instanceof GrassBlock && world.paperConfig().tickRates.grassSpread != 1 && (world.paperConfig().tickRates.grassSpread < 1 || (MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper - Configurable random tick rates for blocks ++ if (this instanceof GrassBlock && world.paperConfig().tickRates.grassSpread != 1 && (world.paperConfig().tickRates.grassSpread < 1 || (io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() + pos.hashCode()) % world.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper - Configurable random tick rates for blocks // Folia - regionised ticking // Paper start - Perf: optimize dirt and snow spreading net.minecraft.world.level.chunk.ChunkAccess cachedBlockChunk = world.getChunkIfLoaded(pos); if (cachedBlockChunk == null) { // Is this needed? @@ -20352,7 +20332,7 @@ index fb180f0bcd20e51d41cfc924029c0b23d3d26258..3db0727cd8d835e8d1b7b3fab93613d2 BlockState iblockdata = blockEntity.getBlockState(); boolean flag = iblockdata.is(Blocks.WITHER_SKELETON_SKULL) || iblockdata.is(Blocks.WITHER_SKELETON_WALL_SKULL); diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index 2250d77b0ec5ea77e3b757e03b62b26ced89a02f..4643150caa7b2bc675732e6f6b8d258c7494371b 100644 +index 4b81b0180dfc96fc6a88646838a886ca5b5d301b..d973ac7d15ee087deb6c6c55a5d10beeedcca8e0 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java @@ -211,7 +211,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name @@ -20365,7 +20345,7 @@ index 2250d77b0ec5ea77e3b757e03b62b26ced89a02f..4643150caa7b2bc675732e6f6b8d258c blockEntity.levels = BeaconBlockEntity.updateBase(world, i, j, k); } diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 4ce7a7947fa727e64556148f923508ce76c128c4..462e1952aaefea7db9f8fc37bb0ef645386094b0 100644 +index 9ea74d37cd951e0dc76d20ed8234b5871035566c..5be70de980d8b475d64dfbb029d11ba30894b880 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java @@ -26,7 +26,7 @@ import co.aikar.timings.MinecraftTimings; // Paper @@ -20614,7 +20594,7 @@ index 83481539e058e5f428d9951e409fed62ef159e5c..48260dce982181e2ee4e92614f8ed3af @Override diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -index b7a0d8ffd1823a1d1edee6baaa62c15f69e6af3d..9a655c7bed0e99bb9db818f95043cff62ad5792a 100644 +index d0e8842a2c4f7dbd0d6ac3694b2a6a5395d8a542..1a3be48e5636e80f5a5a5562e89b9f0e8070f889 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java @@ -50,9 +50,12 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { @@ -20998,7 +20978,7 @@ index 8cb822fed0cda4268f288feae1079a3dc4dc103e..3f53d51960ded5df3b8be12362110f22 // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index 1ef87580574919796dbba707f44a413ee5c5781b..a595abb43853cd4c3f5886a83527c6cbe4a3e8f7 100644 +index c71690dbc3dc52803945f1608f0ee3ba94146354..1c23597f172f46eec714b510acfedb415bb01bff 100644 --- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java @@ -144,8 +144,8 @@ public class PistonMovingBlockEntity extends BlockEntity { @@ -21013,7 +20993,7 @@ index 1ef87580574919796dbba707f44a413ee5c5781b..a595abb43853cd4c3f5886a83527c6cb break; } diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 8e441aafff788eab9e3d6d2fc7b70183d90b9ef4..4075efab9256ed19edc7a4720a728ba480e4e7ed 100644 +index 350aabd20329f429248c84d73ab8b5eb145943a7..bdb864f5e7a1bacde88be632442c9de000ce7729 100644 --- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java +++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java @@ -33,19 +33,19 @@ public class WorldBorder { @@ -21026,7 +21006,7 @@ index 8e441aafff788eab9e3d6d2fc7b70183d90b9ef4..4075efab9256ed19edc7a4720a728ba4 return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); } - // Paper start + // Paper start - Bound treasure maps to world border - private final BlockPos.MutableBlockPos mutPos = new BlockPos.MutableBlockPos(); + private static final ThreadLocal mutPos = ThreadLocal.withInitial(() -> new BlockPos.MutableBlockPos()); // Folia - region threading public boolean isBlockInBounds(int chunkX, int chunkZ) { @@ -21039,10 +21019,10 @@ index 8e441aafff788eab9e3d6d2fc7b70183d90b9ef4..4075efab9256ed19edc7a4720a728ba4 - return this.isWithinBounds(this.mutPos); + return this.isWithinBounds(mutPos.get().set(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15)); // Folia - region threading } - // Paper end + // Paper end - Bound treasure maps to world border diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -index 9cfb0283e568a7d4d554a2fed2417b375485df94..2b79f30bacc2670c4d9a92dedcc449072bbd4c6c 100644 +index b8b78494449c0cd638f9706a803dc54e184d981f..b31f1e0522ff18fa5853af6104d46f980b916285 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java @@ -320,7 +320,7 @@ public abstract class ChunkGenerator { @@ -21055,7 +21035,7 @@ index 9cfb0283e568a7d4d554a2fed2417b375485df94..2b79f30bacc2670c4d9a92dedcc44907 return true; } else { 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 27e8ee4507460b1cc72de692b41562b9f4f13929..562f42d0ccda8dadf9ddc08b1acb67c0e0c22d7e 100644 +index 6ec3fc801453fd54c25b642e6fa71c19b463311d..852fef18497435827a03e0056a09e5deb2525ed9 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -59,6 +59,13 @@ public class LevelChunk extends ChunkAccess { @@ -21152,10 +21132,10 @@ index 27e8ee4507460b1cc72de692b41562b9f4f13929..562f42d0ccda8dadf9ddc08b1acb67c0 public void tick() { if (!this.blockEntity.isRemoved() && this.blockEntity.hasLevel()) { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index c57ca085afe52af0ae9e40e241452796e246f5cc..30c1ea1b1f439b594e1c2ef7d75b0a3a2d7fbb96 100644 +index afc583d5726a572f606469bba3aaba4600827992..1e4931e0d0a585219a4905562a85c2d7321fe891 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -646,7 +646,7 @@ public class ChunkSerializer { +@@ -644,7 +644,7 @@ public class ChunkSerializer { } private static void saveTicks(ServerLevel world, CompoundTag nbt, ChunkAccess.TicksToSave tickSchedulers) { @@ -21165,7 +21145,7 @@ index c57ca085afe52af0ae9e40e241452796e246f5cc..30c1ea1b1f439b594e1c2ef7d75b0a3a nbt.put("block_ticks", tickSchedulers.blocks().save(i, (block) -> { return BuiltInRegistries.BLOCK.getKey(block).toString(); diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 111f37891f6b19ee050aafb12260a326a4e79ec0..c77cd6750deea6927327d7e1dd98f4f8b246319d 100644 +index 7e9c502a7bcda445333adc250a3106f33d38c128..2a56d59daf8c57770cbd15d3103a666ec4d5aaa0 100644 --- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java @@ -76,7 +76,7 @@ public class EndDragonFight { @@ -21233,7 +21213,7 @@ index 111f37891f6b19ee050aafb12260a326a4e79ec0..c77cd6750deea6927327d7e1dd98f4f8 if (blockposition == null) { diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java -index a908652f1ebb426d265ef614746f70cd1e538268..e615b79f68a0467aa8cfa1c61b06ae048a28ef9b 100644 +index 1c4dafdfb3898b5efe06d66792b1b0841ec5724d..8115eb2b632f6aa8d624bddc83c23e281727407f 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java @@ -19,7 +19,7 @@ import net.minecraft.world.level.block.state.BlockState; @@ -21251,7 +21231,7 @@ index a908652f1ebb426d265ef614746f70cd1e538268..e615b79f68a0467aa8cfa1c61b06ae04 RandomSource randomsource = world.random; + io.papermc.paper.threadedregions.RegionizedWorldData worldData = world.getCurrentWorldData(); // Folia - region threading - // Paper start - Patrol settings + // Paper start - Pillager patrol spawn settings and per player options // Random player selection moved up for per player spawning and configuration - int j = world.players().size(); + int j = world.getLocalPlayers().size(); // Folia - region threading @@ -21285,7 +21265,7 @@ index a908652f1ebb426d265ef614746f70cd1e538268..e615b79f68a0467aa8cfa1c61b06ae04 if (days >= world.paperConfig().entities.behavior.pillagerPatrols.start.day && world.isDay()) { diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java -index 7d7d37334321c844958ce09e77547dd61dcba6c8..bded2c58c6b44b918d89d8a18e3af632c2b9e18d 100644 +index ed80960777b18faca2d6a99783e53daf5fa19e09..b52455178290dd27478da4c062863562942ae2ba 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java @@ -22,7 +22,7 @@ import net.minecraft.world.level.material.FluidState; @@ -21389,7 +21369,7 @@ index c322827a910b6244804893784617784002758aee..22ceea2d8ff11dabd0406fb7ab50e5d0 protected int getMaxReferences() { diff --git a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java -index 42212d4533ce25d1cfcf4c58f1fc88791d546cff..fa33c8e40bad9411e1a03899d2c370806f6eba24 100644 +index 5d4c18b068f41f349bdccec14e08ca6ca7cb0c6c..4945bf03176e1842ae3e1bdd4708e39b0a3bdc07 100644 --- a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java +++ b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java @@ -89,10 +89,10 @@ public class PortalForcer { @@ -21406,7 +21386,7 @@ index 42212d4533ce25d1cfcf4c58f1fc88791d546cff..fa33c8e40bad9411e1a03899d2c37080 }); } diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java -index 395bb163fb1d62dd2e6949e1146c337c0bbc626f..a25c2983a7e0df3292f701fc46487e5e15ec7ac8 100644 +index 87db9febbbf53702be0e1e89a95db99e823713e5..de048d920452b04922871eaaafacd1abd0ee21b7 100644 --- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java +++ b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java @@ -46,6 +46,7 @@ public class CollectingNeighborUpdater implements NeighborUpdater { @@ -21418,7 +21398,7 @@ index 395bb163fb1d62dd2e6949e1146c337c0bbc626f..a25c2983a7e0df3292f701fc46487e5e boolean bl2 = this.maxChainedNeighborUpdates >= 0 && this.count >= this.maxChainedNeighborUpdates; ++this.count; diff --git a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java b/src/main/java/net/minecraft/world/level/saveddata/SavedData.java -index 697df9a9f050c0130246ce2b08a859965bddf184..6cd6e83e56cd315cf40fce23318df9e07576a8e5 100644 +index 0655a26a58b3df19d81b18abf6b8ab81fd000ef7..d222b102abdd71b9487e11b4b7637be0d129bb2b 100644 --- a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java +++ b/src/main/java/net/minecraft/world/level/saveddata/SavedData.java @@ -13,7 +13,7 @@ import org.slf4j.Logger; @@ -21430,23 +21410,23 @@ index 697df9a9f050c0130246ce2b08a859965bddf184..6cd6e83e56cd315cf40fce23318df9e0 public abstract CompoundTag save(CompoundTag nbt); -@@ -31,6 +31,7 @@ public abstract class SavedData { +@@ -36,6 +36,7 @@ public abstract class SavedData { - public void save(File file) { + public java.util.concurrent.CompletableFuture save(File file, @org.jetbrains.annotations.Nullable java.util.concurrent.ExecutorService ioExecutor) { // Paper - Write SavedData IO async if (this.isDirty()) { + this.setDirty(false); // Folia - make map data thread-safe - move before save, so that any changes after are not lost CompoundTag compoundTag = new CompoundTag(); compoundTag.put("data", this.save(new CompoundTag())); NbtUtils.addCurrentDataVersion(compoundTag); -@@ -41,7 +42,7 @@ public abstract class SavedData { - LOGGER.error("Could not save data {}", this, var4); +@@ -48,7 +49,7 @@ public abstract class SavedData { } + }; // Paper - Write SavedData IO async - this.setDirty(false); + // Folia - make map data thread-safe - move before save, so that any changes after are not lost - } - } - + // Paper start - Write SavedData IO async + if (ioExecutor == null) { + return java.util.concurrent.CompletableFuture.runAsync(writeRunnable); // No executor, just use common pool diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapIndex.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapIndex.java index 3eca0b1d1407770d3986e0f09c49bc86804b604e..d76df0d600d7f17ac01ce131b85ce9289989995a 100644 --- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapIndex.java @@ -21639,10 +21619,10 @@ index 45269115e63cfc3bd7dc740a5694e2cc7c35bcb1..df799198d4d77a1827002d6d192ebaea } } diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -index d051e8c1db6b5c42b8df0be54d9d48ba0e7b0077..c5650a1a5a728a4b632e03852f7c8262b9e5b491 100644 +index 1c16f43872d9cf9b087f247e9aaa04e7abe3d4ae..2e40f64ffe439f91de74bd7ece4d679021a9c049 100644 --- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -@@ -36,6 +36,7 @@ public class DimensionDataStorage { +@@ -39,6 +39,7 @@ public class DimensionDataStorage implements java.io.Closeable { // Paper - Writ } public T computeIfAbsent(SavedData.Factory type, String id) { @@ -21650,7 +21630,7 @@ index d051e8c1db6b5c42b8df0be54d9d48ba0e7b0077..c5650a1a5a728a4b632e03852f7c8262 T savedData = this.get(type, id); if (savedData != null) { return savedData; -@@ -44,10 +45,12 @@ public class DimensionDataStorage { +@@ -47,10 +48,12 @@ public class DimensionDataStorage implements java.io.Closeable { // Paper - Writ this.set(id, savedData2); return savedData2; } @@ -21663,7 +21643,7 @@ index d051e8c1db6b5c42b8df0be54d9d48ba0e7b0077..c5650a1a5a728a4b632e03852f7c8262 SavedData savedData = this.cache.get(id); if (savedData == null && !this.cache.containsKey(id)) { savedData = this.readSavedData(type.deserializer(), type.type(), id); -@@ -55,6 +58,7 @@ public class DimensionDataStorage { +@@ -58,6 +61,7 @@ public class DimensionDataStorage implements java.io.Closeable { // Paper - Writ } return (T)savedData; @@ -21671,7 +21651,7 @@ index d051e8c1db6b5c42b8df0be54d9d48ba0e7b0077..c5650a1a5a728a4b632e03852f7c8262 } @Nullable -@@ -73,7 +77,9 @@ public class DimensionDataStorage { +@@ -76,7 +80,9 @@ public class DimensionDataStorage implements java.io.Closeable { // Paper - Writ } public void set(String id, SavedData state) { @@ -21813,7 +21793,7 @@ index 1d7c663fa0e550bd0cfb9a4b83ccd7e2968666f0..f3df9c9b6cff85565514f990597f3fe5 LevelChunkTicks levelChunkTicks = this.allContainers.get(l); if (levelChunkTicks == null) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 3b133cd19c0cceeb78f58d36de817b699cc59884..9dfcdc92d8507dff6a77115de5122b109dce44da 100644 +index 825e7abebd6eb898198106ca6e783ec462e64173..4f9c1b04ce6e4874cfb80a91c50aceda0eff2acc 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -307,7 +307,7 @@ public final class CraftServer implements Server { @@ -21895,7 +21875,7 @@ index 3b133cd19c0cceeb78f58d36de817b699cc59884..9dfcdc92d8507dff6a77115de5122b10 if (this.commandMap.dispatch(sender, commandLine)) { return true; } -@@ -3207,7 +3250,7 @@ public final class CraftServer implements Server { +@@ -3202,7 +3245,7 @@ public final class CraftServer implements Server { @Override public int getCurrentTick() { @@ -21905,14 +21885,14 @@ index 3b133cd19c0cceeb78f58d36de817b699cc59884..9dfcdc92d8507dff6a77115de5122b10 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc1afb75b1 100644 +index a139601888b88e8580bdb9c2469386a94abae975..d3bdc355bee762b90a77528e9da96d74e6b174ae 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -186,7 +186,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getTickableTileEntityCount() { -- return world.getTotalTileEntityTickers(); +- return world.blockEntityTickers.size(); + throw new UnsupportedOperationException(); // Folia - region threading - TODO fix this? } @@ -21974,7 +21954,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc warnUnsafeChunk("regenerating a faraway chunk", x, z); // Paper // Paper start - implement regenerateChunk method final ServerLevel serverLevel = this.world; -@@ -510,6 +511,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -512,6 +513,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean refreshChunk(int x, int z) { @@ -21982,7 +21962,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); if (playerChunk == null) return false; -@@ -545,7 +547,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -547,7 +549,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean loadChunk(int x, int z, boolean generate) { @@ -21991,7 +21971,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc warnUnsafeChunk("loading a faraway chunk", x, z); // Paper // Paper start - Optimize this method ChunkPos chunkPos = new ChunkPos(x, z); -@@ -617,7 +619,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -616,7 +618,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { DistanceManager chunkDistanceManager = this.world.getChunkSource().chunkMap.distanceManager; if (chunkDistanceManager.addRegionTicketAtDistance(TicketType.PLUGIN_TICKET, new ChunkPos(x, z), 2, plugin)) { // keep in-line with force loading, add at level 31 @@ -22000,7 +21980,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc return true; } -@@ -808,13 +810,15 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -807,13 +809,15 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) { @@ -22021,7 +22001,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc BlockPos position = ((CraftBlockState) blockstate).getPosition(); net.minecraft.world.level.block.state.BlockState oldBlock = this.world.getBlockState(position); int flag = ((CraftBlockState) blockstate).getFlag(); -@@ -822,10 +826,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -821,10 +825,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { net.minecraft.world.level.block.state.BlockState newBlock = this.world.getBlockState(position); this.world.notifyAndUpdatePhysics(position, null, oldBlock, newBlock, newBlock, flag, 512); } @@ -22034,7 +22014,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc return false; } } -@@ -859,6 +863,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -858,6 +862,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setTime(long time) { @@ -22042,7 +22022,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc long margin = (time - this.getFullTime()) % 24000; if (margin < 0) margin += 24000; this.setFullTime(this.getFullTime() + margin); -@@ -871,6 +876,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -870,6 +875,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setFullTime(long time) { @@ -22050,7 +22030,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc // Notify anyone who's listening TimeSkipEvent event = new TimeSkipEvent(this, TimeSkipEvent.SkipReason.CUSTOM, time - this.world.getDayTime()); this.server.getPluginManager().callEvent(event); -@@ -898,7 +904,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -897,7 +903,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public long getGameTime() { @@ -22059,7 +22039,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc } @Override -@@ -918,11 +924,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -917,11 +923,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) { @@ -22073,7 +22053,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc 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 +1000,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -991,6 +999,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getHighestBlockYAt(int x, int z, org.bukkit.HeightMap heightMap) { @@ -22081,7 +22061,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc 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 +1031,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1021,6 +1030,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); @@ -22089,7 +22069,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc if (this.world.hasChunkAt(pos)) { net.minecraft.world.level.chunk.LevelChunk chunk = this.world.getChunkAt(pos); -@@ -1371,6 +1381,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1331,6 +1341,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setStorm(boolean hasStorm) { @@ -22097,7 +22077,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.world.serverLevelData.setRaining(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper - Add cause to Weather/ThunderChangeEvents this.setWeatherDuration(0); // Reset weather duration (legacy behaviour) this.setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) -@@ -1383,6 +1394,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1343,6 +1354,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setWeatherDuration(int duration) { @@ -22105,7 +22085,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.world.serverLevelData.setRainTime(duration); } -@@ -1393,6 +1405,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1353,6 +1365,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setThundering(boolean thundering) { @@ -22113,7 +22093,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.world.serverLevelData.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper - Add cause to Weather/ThunderChangeEvents this.setThunderDuration(0); // Reset weather duration (legacy behaviour) this.setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) -@@ -1405,6 +1418,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1365,6 +1378,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setThunderDuration(int duration) { @@ -22121,7 +22101,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.world.serverLevelData.setThunderTime(duration); } -@@ -1415,6 +1429,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1375,6 +1389,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setClearWeatherDuration(int duration) { @@ -22129,7 +22109,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.world.serverLevelData.setClearWeatherTime(duration); } -@@ -1609,6 +1624,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1569,6 +1584,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setKeepSpawnInMemory(boolean keepLoaded) { @@ -22137,7 +22117,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc // Paper start - Configurable spawn radius if (keepLoaded == this.world.keepSpawnInMemory) { // do nothing, nothing has changed -@@ -1687,6 +1703,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1647,6 +1663,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setHardcore(boolean hardcore) { @@ -22145,7 +22125,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.world.serverLevelData.settings.hardcore = hardcore; } -@@ -1699,6 +1716,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1659,6 +1676,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerAnimalSpawns(int ticksPerAnimalSpawns) { @@ -22153,7 +22133,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.setTicksPerSpawns(SpawnCategory.ANIMAL, ticksPerAnimalSpawns); } -@@ -1711,6 +1729,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1671,6 +1689,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerMonsterSpawns(int ticksPerMonsterSpawns) { @@ -22161,7 +22141,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.setTicksPerSpawns(SpawnCategory.MONSTER, ticksPerMonsterSpawns); } -@@ -1723,6 +1742,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1683,6 +1702,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerWaterSpawns(int ticksPerWaterSpawns) { @@ -22169,7 +22149,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.setTicksPerSpawns(SpawnCategory.WATER_ANIMAL, ticksPerWaterSpawns); } -@@ -1735,6 +1755,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1695,6 +1715,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerWaterAmbientSpawns(int ticksPerWaterAmbientSpawns) { @@ -22177,7 +22157,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.setTicksPerSpawns(SpawnCategory.WATER_AMBIENT, ticksPerWaterAmbientSpawns); } -@@ -1747,6 +1768,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1707,6 +1728,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerWaterUndergroundCreatureSpawns(int ticksPerWaterUndergroundCreatureSpawns) { @@ -22185,7 +22165,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.setTicksPerSpawns(SpawnCategory.WATER_UNDERGROUND_CREATURE, ticksPerWaterUndergroundCreatureSpawns); } -@@ -1759,11 +1781,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1719,11 +1741,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerAmbientSpawns(int ticksPerAmbientSpawns) { @@ -22199,7 +22179,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null"); Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory.%s are not supported", spawnCategory); -@@ -1780,21 +1804,25 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1740,21 +1764,25 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setMetadata(String metadataKey, MetadataValue newMetadataValue) { @@ -22225,7 +22205,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.server.getWorldMetadata().removeMetadata(this, metadataKey, owningPlugin); } -@@ -1807,6 +1835,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1767,6 +1795,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setMonsterSpawnLimit(int limit) { @@ -22233,7 +22213,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.setSpawnLimit(SpawnCategory.MONSTER, limit); } -@@ -1819,6 +1848,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1779,6 +1808,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setAnimalSpawnLimit(int limit) { @@ -22241,7 +22221,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.setSpawnLimit(SpawnCategory.ANIMAL, limit); } -@@ -1831,6 +1861,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1791,6 +1821,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setWaterAnimalSpawnLimit(int limit) { @@ -22249,7 +22229,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.setSpawnLimit(SpawnCategory.WATER_ANIMAL, limit); } -@@ -1843,6 +1874,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1803,6 +1834,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setWaterAmbientSpawnLimit(int limit) { @@ -22257,7 +22237,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.setSpawnLimit(SpawnCategory.WATER_AMBIENT, limit); } -@@ -1855,6 +1887,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1815,6 +1847,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setWaterUndergroundCreatureSpawnLimit(int limit) { @@ -22265,7 +22245,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.setSpawnLimit(SpawnCategory.WATER_UNDERGROUND_CREATURE, limit); } -@@ -1867,6 +1900,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1827,6 +1860,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setAmbientSpawnLimit(int limit) { @@ -22273,7 +22253,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc this.setSpawnLimit(SpawnCategory.AMBIENT, limit); } -@@ -1889,6 +1923,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1849,6 +1883,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setSpawnLimit(SpawnCategory spawnCategory, int limit) { @@ -22281,7 +22261,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null"); Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory.%s are not supported", spawnCategory); -@@ -1971,7 +2006,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1931,7 +1966,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { if (!(entity instanceof CraftEntity craftEntity) || entity.getWorld() != this || sound == null || category == null) return; ClientboundSoundEntityPacket packet = new ClientboundSoundEntityPacket(CraftSound.bukkitToMinecraftHolder(sound), net.minecraft.sounds.SoundSource.valueOf(category.name()), craftEntity.getHandle(), volume, pitch, seed); @@ -22290,7 +22270,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc if (entityTracker != null) { entityTracker.broadcastAndSend(packet); } -@@ -1983,7 +2018,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1943,7 +1978,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { if (!(entity instanceof CraftEntity craftEntity) || entity.getWorld() != this || sound == null || category == null) return; ClientboundSoundEntityPacket packet = new ClientboundSoundEntityPacket(Holder.direct(SoundEvent.createVariableRangeEvent(new ResourceLocation(sound))), net.minecraft.sounds.SoundSource.valueOf(category.name()), craftEntity.getHandle(), volume, pitch, seed); @@ -22299,7 +22279,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc if (entityTracker != null) { entityTracker.broadcastAndSend(packet); } -@@ -2072,6 +2107,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2032,6 +2067,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean setGameRuleValue(String rule, String value) { @@ -22307,7 +22287,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc // No null values allowed if (rule == null || value == null) return false; -@@ -2114,6 +2150,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2074,6 +2110,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean setGameRule(GameRule rule, T newValue) { @@ -22315,7 +22295,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc Preconditions.checkArgument(rule != null, "GameRule cannot be null"); Preconditions.checkArgument(newValue != null, "GameRule value cannot be null"); -@@ -2366,6 +2403,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2326,6 +2363,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void sendGameEvent(Entity sourceEntity, org.bukkit.GameEvent gameEvent, Vector position) { @@ -22328,7 +22308,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc 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 -@@ -2462,7 +2505,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2422,7 +2465,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 @@ -22337,7 +22317,7 @@ index 1ab5a5a554475f734ac53d39f521a43ecd042045..6bb19a9a4150f516c32bc155eafe99fc net.minecraft.world.level.chunk.LevelChunk immediate = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); if (immediate != null) { return java.util.concurrent.CompletableFuture.completedFuture(new CraftChunk(immediate)); -@@ -2479,7 +2522,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2439,7 +2482,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { java.util.concurrent.CompletableFuture ret = new java.util.concurrent.CompletableFuture<>(); io.papermc.paper.chunk.system.ChunkSystem.scheduleChunkLoad(this.getHandle(), x, z, gen, ChunkStatus.FULL, true, priority, (c) -> { @@ -22601,7 +22581,7 @@ index 3e93a6c489972ff2b4ecff3d83cc72b2d5c970f8..66dc7e20544c7000f4824b02cc3a31bc List offers = waitable.get(); if (offers == null) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index f16ac1d640fc97f348c244d4ea86e3278b30ae19..1d9e123f5c1bc94f6be08f372c94a2c595a789c6 100644 +index 8698104e3eb98e2cc5da5de87a8f538860c1d91d..ac91fe913b4f6a6148955e7181e5abda13f15820 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -233,6 +233,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -22699,10 +22679,10 @@ index f16ac1d640fc97f348c244d4ea86e3278b30ae19..1d9e123f5c1bc94f6be08f372c94a2c5 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b364a042a9b5d1b3c604f6bf6d03b6aeff03ec82..9c9b7728122aaaeb92f565f0c9322f0e3aed947b 100644 +index 39b25c2478eadd373383a3445a7f27ea30d18550..f5985bac1f72591e31a85d53a5dfde7c26966a62 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -596,7 +596,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -554,7 +554,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void kickPlayer(String message) { @@ -22711,7 +22691,7 @@ index b364a042a9b5d1b3c604f6bf6d03b6aeff03ec82..9c9b7728122aaaeb92f565f0c9322f0e if (this.getHandle().connection == null) return; this.getHandle().connection.disconnect(message == null ? "" : message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause -@@ -1319,6 +1319,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1277,6 +1277,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public boolean teleport(Location location, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) { @@ -22723,7 +22703,7 @@ index b364a042a9b5d1b3c604f6bf6d03b6aeff03ec82..9c9b7728122aaaeb92f565f0c9322f0e Set relativeArguments; Set allFlags; if (flags.length == 0) { -@@ -1950,7 +1955,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1923,7 +1928,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { private void unregisterEntity(Entity other) { // Paper end ChunkMap tracker = ((ServerLevel) this.getHandle().level()).getChunkSource().chunkMap; @@ -22732,7 +22712,7 @@ index b364a042a9b5d1b3c604f6bf6d03b6aeff03ec82..9c9b7728122aaaeb92f565f0c9322f0e if (entry != null) { entry.removePlayer(this.getHandle()); } -@@ -2047,7 +2052,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2020,7 +2025,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (original != null) otherPlayer.setUUID(original); // Paper - uuid override } @@ -22742,7 +22722,7 @@ index b364a042a9b5d1b3c604f6bf6d03b6aeff03ec82..9c9b7728122aaaeb92f565f0c9322f0e entry.updatePlayer(this.getHandle()); } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 8af725ea1378c8e5b275e5a7f690b22b7921c16b..dd876b50a6df9386aef890992b59ad29db2b3502 100644 +index 23b4b5d63d45108534bde330079c7a12b3aa4f5f..47f100ee2de9cbc5b61df2f54dad51e8f12f2ecf 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; @@ -22756,7 +22736,7 @@ index 8af725ea1378c8e5b275e5a7f690b22b7921c16b..dd876b50a6df9386aef890992b59ad29 // helper methods private static boolean canBuild(ServerLevel world, Player player, int x, int z) { -@@ -917,7 +917,7 @@ public class CraftEventFactory { +@@ -915,7 +915,7 @@ public class CraftEventFactory { return CraftEventFactory.handleBlockSpreadEvent(world, source, target, block, 2); } @@ -22765,7 +22745,7 @@ index 8af725ea1378c8e5b275e5a7f690b22b7921c16b..dd876b50a6df9386aef890992b59ad29 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 { +@@ -927,7 +927,7 @@ public class CraftEventFactory { CraftBlockState state = CraftBlockStates.getBlockState(world, target, flag); state.setData(block); @@ -22841,20 +22821,20 @@ index 8af725ea1378c8e5b275e5a7f690b22b7921c16b..dd876b50a6df9386aef890992b59ad29 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 { +@@ -2163,7 +2163,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()) { // Folia - region threading ++ if (!net.minecraft.world.level.block.DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading if (!event.callEvent()) { return itemStack; } diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 700932b65e4fda560d684b0aa079bcee3923f73e..2c3e1b420303a3c3a9315983fbc7e47423f7d9e4 100644 +index e85b9bb3f9c225d289a4959921970b9963881199..b00e3b9b628f3d2a2fdbf1d2c77904963c16d3ac 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -530,6 +530,7 @@ public class CraftScheduler implements BukkitScheduler { +@@ -532,6 +532,7 @@ public class CraftScheduler implements BukkitScheduler { } protected CraftTask handle(final CraftTask task, final long delay) { // Paper @@ -22863,7 +22843,7 @@ index 700932b65e4fda560d684b0aa079bcee3923f73e..2c3e1b420303a3c3a9315983fbc7e474 if (!this.isAsyncScheduler && !task.isSync()) { this.asyncScheduler.handle(task, delay); diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 509f8487a170f3dc84b091acf16df26e42391189..83f6756aaf32252e021059e930bd651135176af0 100644 +index ca5312febcdd467889ad725c0263367bc5fe69f6..f75010af797b26908a38f03a6c0ec3757d3770b7 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -377,6 +377,12 @@ public final class CraftMagicNumbers implements UnsafeValues { @@ -22898,7 +22878,7 @@ index 86a20c91beff6b27e6ec886e49ba902b216106f2..96007426144b78f91c12614f04350855 return this.handle; } diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index fafc8b84d6b6368c70b8eedfdb4c3a9deace9c26..5f1dee3a1d5a7b0391bad60b53eda1c5586058aa 100644 +index c39894e824334f1dc52e0466cf9d84f7e219be70..f8718d91f4c15c74d6e6dd5f60f7f05f45f63655 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java @@ -52,7 +52,7 @@ public class ActivationRange @@ -22984,7 +22964,7 @@ index fafc8b84d6b6368c70b8eedfdb4c3a9deace9c26..5f1dee3a1d5a7b0391bad60b53eda1c5 if ( world.spigotConfig.ignoreSpectatorActivation && player.isSpectator() ) { continue; -@@ -201,27 +203,34 @@ public class ActivationRange +@@ -201,26 +203,33 @@ public class ActivationRange // Paper start int worldHeight = world.getHeight(); @@ -23012,8 +22992,7 @@ index fafc8b84d6b6368c70b8eedfdb4c3a9deace9c26..5f1dee3a1d5a7b0391bad60b53eda1c5 + java.util.List entities = new java.util.ArrayList<>(); // Folia - region ticking - bypass getEntities thread check, we perform a check on the entities later + ((net.minecraft.server.level.ServerLevel)world).getEntityLookup().getEntities((Entity)null, maxBB, entities, null); // Folia - region ticking - bypass getEntities thread check, we perform a check on the entities later boolean tickMarkers = world.paperConfig().entities.markers.tick; // Paper - Configurable marker ticking - for (int i = 0; i < entities.size(); i++) { - Entity entity = entities.get(i); + for (Entity entity : entities) { // Paper start - Configurable marker ticking + // Folia start - region ticking + if (!io.papermc.paper.util.TickThread.isTickThreadFor(entity)) { @@ -23029,7 +23008,7 @@ index fafc8b84d6b6368c70b8eedfdb4c3a9deace9c26..5f1dee3a1d5a7b0391bad60b53eda1c5 } // Paper end } -@@ -233,18 +242,18 @@ public class ActivationRange +@@ -232,18 +241,18 @@ public class ActivationRange * * @param chunk */ @@ -23053,7 +23032,7 @@ index fafc8b84d6b6368c70b8eedfdb4c3a9deace9c26..5f1dee3a1d5a7b0391bad60b53eda1c5 } } } -@@ -267,10 +276,10 @@ public class ActivationRange +@@ -266,10 +275,10 @@ public class ActivationRange if (entity.getRemainingFireTicks() > 0) { return 2; } @@ -23066,7 +23045,7 @@ index fafc8b84d6b6368c70b8eedfdb4c3a9deace9c26..5f1dee3a1d5a7b0391bad60b53eda1c5 // Paper end // quick checks. if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByFluid()) ) // Paper -@@ -393,19 +402,19 @@ public class ActivationRange +@@ -392,19 +401,19 @@ public class ActivationRange } // Paper end diff --git a/patches/server/0004-Max-pending-logins.patch b/patches/server/0004-Max-pending-logins.patch index 0b58476..2aa79fe 100644 --- a/patches/server/0004-Max-pending-logins.patch +++ b/patches/server/0004-Max-pending-logins.patch @@ -6,20 +6,20 @@ Subject: [PATCH] Max pending logins Should help the floodgates on launch diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 586027a4c97a3c1be42f1c8d5a248e2672bb6489..d809dd5f6aa39fcd7583d7db822450297225eb49 100644 +index 58cdb65083134680230d7070f9f6209f2d32873b..aa4b461bbb2c8c4753f7c9057bab1740de2c0284 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -89,7 +89,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, if (this.server.getPlayerList().pushPendingJoin(name, uniqueId, this.connection)) { // Folia end - region threading - rewrite login process this.verifyLoginAndFinishConnectionSetup((GameProfile) Objects.requireNonNull(this.authenticatedProfile)); -- } // Folia - region threading - rewrite login process -+ } else { --this.tick; } // Folia - region threading - rewrite login process // Folia - max concurrent logins +- } // Paper - prevent logins to be processed even though disconnect was called ++ } else { --this.tick; } // Paper - prevent logins to be processed even though disconnect was called // Folia - max concurrent logins } if (this.state == ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT && !this.isPlayerAlreadyInWorld((GameProfile) Objects.requireNonNull(this.authenticatedProfile))) { diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8284cde1984408a97a933f4299ad8541e7a015ca..739e8966c7326edf47e85f959374cbc8970d7b2a 100644 +index fa36e892b019877a770a618fe8d4cda118fe137d..93e192ea1a0cda2d7aae983980a6fead013c8b90 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -171,6 +171,17 @@ public abstract class PlayerList { diff --git a/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch b/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch index 26b4729..e58fe73 100644 --- a/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch +++ b/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch @@ -29,10 +29,10 @@ index 41bf71d116ffc5431586ce54abba7f8def6c1dcf..519da6886613b8460e989767b1a21e31 } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 1ee49570e9c3250d1d3ce0420a0a0c94cda717fe..cc4eb106b3ff1953de11f1faa7c04f3f9982fca2 100644 +index b736cb55542ea7bc35d1a02e7fe5913de024ca60..eade31ea668c171dceafee958e265041a439c54b 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2919,6 +2919,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -2907,6 +2907,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S if (!force && (!this.canRide(entity) || !entity.canAddPassenger(this))) { return false; } else { @@ -40,7 +40,7 @@ index 1ee49570e9c3250d1d3ce0420a0a0c94cda717fe..cc4eb106b3ff1953de11f1faa7c04f3f // CraftBukkit start if (entity.getBukkitEntity() instanceof Vehicle && this.getBukkitEntity() instanceof LivingEntity) { VehicleEnterEvent event = new VehicleEnterEvent((Vehicle) entity.getBukkitEntity(), this.getBukkitEntity()); -@@ -2940,6 +2941,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -2928,6 +2929,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S return false; } // CraftBukkit end @@ -48,7 +48,7 @@ index 1ee49570e9c3250d1d3ce0420a0a0c94cda717fe..cc4eb106b3ff1953de11f1faa7c04f3f if (this.isPassenger()) { this.stopRiding(); } -@@ -3017,6 +3019,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -3005,6 +3007,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); } else { // CraftBukkit start @@ -56,7 +56,7 @@ index 1ee49570e9c3250d1d3ce0420a0a0c94cda717fe..cc4eb106b3ff1953de11f1faa7c04f3f CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle(); Entity orig = craft == null ? null : craft.getHandle(); if (this.getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { -@@ -3044,6 +3047,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -3032,6 +3035,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S return false; } // CraftBukkit end @@ -414,7 +414,7 @@ index dd91de8f24c27b9318c2a898a49991d74c100bff..d7c34f601ce66a6b090ec431a0503462 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -index 8184a2adf889e02b048ceb015edfc04d1b5c21b9..9165bb2458f2440c6a17dff8da985b60f84796db 100644 +index e33b1b6fd50a4eea57500cc00dba20d6edcab75d..f9a8e684a04c4ffdf566b29252e18dbfcf09ade9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java @@ -102,8 +102,16 @@ public class CraftBoat extends CraftVehicle implements Boat { @@ -897,7 +897,7 @@ index d657fd2c507a5b215aeab0a5f3e9c2ee892a27c8..9fc90b162aab15a9cd60b02aba563181 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 1d9e123f5c1bc94f6be08f372c94a2c595a789c6..39cb7a0a58ea24f48f7e621f696f0dbfea229ea3 100644 +index ac91fe913b4f6a6148955e7181e5abda13f15820..5adbfb278aed3c32b6d4992b8932cc3dafd8f9cc 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -490,7 +490,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -918,7 +918,7 @@ index 1d9e123f5c1bc94f6be08f372c94a2c595a789c6..39cb7a0a58ea24f48f7e621f696f0dbf } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -index b66dd5c5c5d98c9285e0d0a4ad4b99a66419f732..3d284b790c869fb30180b92b891b292006c7dad4 100644 +index 3a890cccf1766758794f3a3b5d31428f42590049..06863afd6bd855130ac0e672824aa2755e141286 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java @@ -11,8 +11,16 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { @@ -1359,7 +1359,7 @@ index 8746f80d08df5501b32958eb123aa7d814573ddf..c6c6eb55f4649e18beef9832c2ea7b9d } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 827fe201a7b74f485abb46b127a28bf0cb479c3b..bc74382c4b62ba14e655d10c261aada61191733a 100644 +index acbb64010cd59668aa1bcb52ff1220789cadb1d3..35958bb85389ca0ed02f567e0fd9f4a9dbc66ff2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -291,8 +291,16 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @@ -1827,7 +1827,7 @@ index 79b608e89d4d1f76a58868c585bb87c82e2689b1..7767a342b3d8bf9c07fbd73ad4ccacd8 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index 5f6a1fb323782816f706ccf7df922cb203238302..4cae2bb318f8f6e060314fe4bd24051e84982787 100644 +index 31f62fbb54ec7b270fbd8afba7bd7c4bfafa09e3..0c89084eae131ae91d6c6aa910b1e0d2fc47747d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java @@ -55,8 +55,16 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { @@ -1854,7 +1854,7 @@ index 5f6a1fb323782816f706ccf7df922cb203238302..4cae2bb318f8f6e060314fe4bd24051e - paperPathfinder.setHandle(getHandle()); + paperPathfinder.setHandle((net.minecraft.world.entity.Mob)entity); // Folia - region threading } - // Paper end + // Paper end - Mob Pathfinding API diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMonster.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMonster.java index 706c74c832f6893df3797023f68add31139c7d57..80a612f16669e571e336dd6369a968b4664c98e4 100644 @@ -2130,10 +2130,10 @@ index 2638c341bc02f201f7ab17fdebcdbdf3a7ec05bf..0f5c2d31a2dea13a46ba81e353393633 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 9c9b7728122aaaeb92f565f0c9322f0e3aed947b..003684843c2a9fc709619c1de8cf73dbb1b25c42 100644 +index f5985bac1f72591e31a85d53a5dfde7c26966a62..fc301fcf812b79ac7ceae710132a762f101b82b2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -616,7 +616,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -574,7 +574,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void kick(net.kyori.adventure.text.Component message, org.bukkit.event.player.PlayerKickEvent.Cause cause) { @@ -2142,7 +2142,7 @@ index 9c9b7728122aaaeb92f565f0c9322f0e3aed947b..003684843c2a9fc709619c1de8cf73db final ServerGamePacketListenerImpl connection = this.getHandle().connection; if (connection != null) { connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message, cause); -@@ -2206,9 +2206,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2179,9 +2179,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this; } @@ -2160,7 +2160,7 @@ index 9c9b7728122aaaeb92f565f0c9322f0e3aed947b..003684843c2a9fc709619c1de8cf73db } public void setHandle(final ServerPlayer entity) { -@@ -3242,7 +3249,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -3215,7 +3222,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { { if ( CraftPlayer.this.getHealth() <= 0 && CraftPlayer.this.isOnline() ) { @@ -2970,7 +2970,7 @@ index 6c15d40979fd3e3d246a447c432b321fbf29ada3..771eb799b032fcf4fc33c5e445b7fa25 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java -index fd968881eeec6dc5bdf90decc23a2bfc619c410d..96dba371b8fe88f8e15eee5fbc152a0b85bc0511 100644 +index 3aa23d9f22d5cd22231293fd7d1ca4cb79eb7cb3..f340cf90512a7097153d7fa1a2b38fe3e0f1e8d5 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java @@ -14,8 +14,16 @@ public class CraftVillagerZombie extends CraftZombie implements ZombieVillager { diff --git a/patches/server/0007-Disable-mid-tick-task-execution.patch b/patches/server/0007-Disable-mid-tick-task-execution.patch index 52218a7..9067a5f 100644 --- a/patches/server/0007-Disable-mid-tick-task-execution.patch +++ b/patches/server/0007-Disable-mid-tick-task-execution.patch @@ -10,10 +10,10 @@ the impact from scaling the region threads, but is not a fix to the underlying issue. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 301ff715b89abbebda83af1e15f8d5d15097002f..7df4935a6c1a631e07dcf9c30341f93f3fba7090 100644 +index 0330f180ef8fed3091b69758cea64d742a4dc0ac..b912a5d6737cf8bd74617225ca0837e6e97b7206 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1463,6 +1463,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop getProvidedPlugins() { return this.provides; diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginProviderFactory.java b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginProviderFactory.java -index 84305ea4bd21acf0ff2415808933552696686ac7..7858c88ffc505b7b79155f9c95316f825c5ee575 100644 +index 0a27b468560ccf4b9588cd12d50c02e442f3024f..6369b13e1fcdbdb25dd9d6e4d3bffdedbee4f739 100644 --- a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginProviderFactory.java +++ b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginProviderFactory.java @@ -24,6 +24,11 @@ class PaperPluginProviderFactory implements PluginTypeFactory 0 && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % autosavePeriod == 0; // Folia - region threading @@ -1428,15 +1428,15 @@ index 7df4935a6c1a631e07dcf9c30341f93f3fba7090..4383528df7627c5eb7cba1218f1b4e52 try { this.isSaving = true; if (playerSaveInterval > 0) { -@@ -1660,6 +1673,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Folia - region threading entityplayer.connection.suspendFlushing(); -@@ -1790,12 +1805,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop iterator = this.level.needsChangeBroadcasting.iterator(); iterator.hasNext();) { ChunkHolder holder = iterator.next(); if (!io.papermc.paper.util.TickThread.isTickThreadFor(holder.newChunkHolder.world, holder.pos)) { -@@ -635,6 +656,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -627,6 +648,7 @@ public class ServerChunkCache extends ChunkSource { iterator.remove(); } } @@ -1629,10 +1629,10 @@ index a21cc9c7d5981c742f379affe9c1ef4dcb0fa1e1..88db5ada13329a5fe0d0fb652d2c8a8d // Folia end - region threading // Paper end - optimise chunk tick iteration diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec11fdc48f7 100644 +index 172f8e1abb036669b787fde570da8d326d2ab262..a16fc5ba55dbde0cf7f968884da40d70a754a0d8 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -897,6 +897,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -892,6 +892,7 @@ public class ServerLevel extends Level implements WorldGenLevel { public void tick(BooleanSupplier shouldKeepTicking, io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - regionised ticking final io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.getCurrentWorldData(); // Folia - regionised ticking @@ -1640,7 +1640,7 @@ index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec1 ProfilerFiller gameprofilerfiller = this.getProfiler(); regionizedWorldData.setHandlingTick(true); // Folia - regionised ticking -@@ -925,9 +926,13 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -920,9 +921,13 @@ public class ServerLevel extends Level implements WorldGenLevel { if (!this.isDebug() && flag) { j = regionizedWorldData.getRedstoneGameTime(); // Folia - region threading gameprofilerfiller.push("blockTicks"); @@ -1654,7 +1654,7 @@ index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec1 gameprofilerfiller.pop(); } this.timings.scheduledBlocks.stopTiming(); // Paper -@@ -935,18 +940,24 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -930,18 +935,24 @@ public class ServerLevel extends Level implements WorldGenLevel { gameprofilerfiller.popPush("raid"); if (flag) { this.timings.raids.startTiming(); // Paper - timings @@ -1679,7 +1679,7 @@ index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec1 this.timings.doSounds.stopTiming(); // Spigot } -@@ -962,6 +973,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -957,6 +968,7 @@ public class ServerLevel extends Level implements WorldGenLevel { gameprofilerfiller.push("entities"); this.timings.tickEntities.startTiming(); // Spigot if (this.dragonFight != null && flag) { @@ -1687,7 +1687,7 @@ index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec1 if (io.papermc.paper.util.TickThread.isTickThreadFor(this, this.dragonFight.origin)) { // Folia - region threading gameprofilerfiller.push("dragonFight"); this.dragonFight.tick(); -@@ -974,10 +986,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -969,10 +981,12 @@ public class ServerLevel extends Level implements WorldGenLevel { fightCenter ); } // Folia end - region threading @@ -1700,7 +1700,7 @@ index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec1 regionizedWorldData.forEachTickingEntity((entity) -> { // Folia - regionised ticking if (!entity.isRemoved()) { if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed -@@ -1005,10 +1019,13 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1000,10 +1014,13 @@ public class ServerLevel extends Level implements WorldGenLevel { } } }); @@ -1714,7 +1714,7 @@ index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec1 } gameprofilerfiller.push("entityManagement"); -@@ -1068,12 +1085,15 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1063,12 +1080,15 @@ public class ServerLevel extends Level implements WorldGenLevel { } public void tickCustomSpawners(boolean spawnMonsters, boolean spawnAnimals) { @@ -1730,7 +1730,7 @@ index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec1 } } -@@ -1523,6 +1543,11 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1518,6 +1538,11 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper start- timings final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper @@ -1742,7 +1742,7 @@ index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec1 try { // Paper end - timings entity.setOldPosAndRot(); -@@ -1548,7 +1573,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1543,7 +1568,7 @@ public class ServerLevel extends Level implements WorldGenLevel { // Folia end - region threading } else { entity.inactiveTick(); } // Paper - EAR 2 this.getProfiler().pop(); @@ -1751,7 +1751,7 @@ index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec1 Iterator iterator = entity.getPassengers().iterator(); while (iterator.hasNext()) { -@@ -1572,6 +1597,11 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1567,6 +1592,11 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper - EAR 2 final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper @@ -1763,7 +1763,7 @@ index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec1 try { // Paper end passenger.setOldPosAndRot(); -@@ -1611,7 +1641,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1606,7 +1636,7 @@ public class ServerLevel extends Level implements WorldGenLevel { this.tickPassenger(passenger, entity2); } @@ -1773,10 +1773,10 @@ index a04ae14681880897132bd410680d8f69b1593795..653728709b275fee822e55a511e67ec1 } else { passenger.stopRiding(); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8c74ba46920c41f82df7ae066caffd17b333301c..5d4876fc53eb12ee8e4a0159177e05cee847f077 100644 +index b19f1db38e71d9185cca9fc0e44937f91443a042..d13edeff0de64cb77d7668e5b964cabcf9729388 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1329,6 +1329,7 @@ public abstract class PlayerList { +@@ -1327,6 +1327,7 @@ public abstract class PlayerList { public void saveAll(int interval) { io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main @@ -1784,7 +1784,7 @@ index 8c74ba46920c41f82df7ae066caffd17b333301c..5d4876fc53eb12ee8e4a0159177e05ce MinecraftTimings.savePlayers.startTiming(); // Paper int numSaved = 0; long now = System.nanoTime(); // Folia - region threading -@@ -1340,7 +1341,9 @@ public abstract class PlayerList { +@@ -1338,7 +1339,9 @@ public abstract class PlayerList { } // Folia end - region threading if (interval == -1 || now - entityplayer.lastSave >= timeInterval) { // Folia - region threading @@ -1795,7 +1795,7 @@ index 8c74ba46920c41f82df7ae066caffd17b333301c..5d4876fc53eb12ee8e4a0159177e05ce if (interval != -1 && max != -1 && ++numSaved >= max) { break; diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index e52f3da3b63cc3dba59d3e874a8420dd312b5e96..dc83dc377aff965222006e3eaaceb57692d2604f 100644 +index 09e8445a3f8c6b3ebc852a75a9a25b41a51ba659..f921c159c4f7556daf3c8405241de3607ba251ad 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java @@ -326,6 +326,13 @@ public class EntityType implements FeatureElement, EntityTypeT @@ -1826,10 +1826,10 @@ index e52f3da3b63cc3dba59d3e874a8420dd312b5e96..dc83dc377aff965222006e3eaaceb576 this.factory = factory; this.category = spawnGroup; diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 394ec4f018b676a441e49d7ccbef3f8c56673603..412b764a4911485487c7967ed64b74e97eb8fa8c 100644 +index de7c06785e3914fe7181bcb836b70a96a4900011..bc38893427cbe560ffea30996a391b7ba97f9d5c 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -229,6 +229,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -223,6 +223,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { return this.getCurrentWorldData().getLocalPlayers(); } // Folia end - region ticking @@ -1839,7 +1839,7 @@ index 394ec4f018b676a441e49d7ccbef3f8c56673603..412b764a4911485487c7967ed64b74e9 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 -@@ -321,6 +324,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -315,6 +318,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { this.minSection = io.papermc.paper.util.WorldUtil.getMinSection(this); this.maxSection = io.papermc.paper.util.WorldUtil.getMaxSection(this); // Paper end - optimise collisions @@ -1848,8 +1848,8 @@ index 394ec4f018b676a441e49d7ccbef3f8c56673603..412b764a4911485487c7967ed64b74e9 + // Folia end - profiler } - // Paper start -@@ -1309,17 +1315,21 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Paper start - Cancel hit for vanished players +@@ -1299,17 +1305,21 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } protected void tickBlockEntities() { @@ -1871,10 +1871,10 @@ index 394ec4f018b676a441e49d7ccbef3f8c56673603..412b764a4911485487c7967ed64b74e9 // Spigot start // Iterator iterator = this.blockEntityTickers.iterator(); boolean flag = this.tickRateManager().runsNormally(); -@@ -1346,6 +1356,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1336,6 +1346,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } } - blockEntityTickers.removeAll(toRemove); // Folia - regionised ticking + blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 // Folia - regionised ticking + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.TILE_ENTITY_TICK); } // Folia - profiler this.timings.tileEntityTick.stopTiming(); // Spigot @@ -1917,7 +1917,7 @@ index 2e110da3502a7ac5ec4cc20510a3fac933569895..5aac65f37a0190c5d6a7175073fb0cc0 } } 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 562f42d0ccda8dadf9ddc08b1acb67c0e0c22d7e..d6bc8c0dfa8f180ced0ee55d03797411164ad55a 100644 +index 852fef18497435827a03e0056a09e5deb2525ed9..4847f7caa9147a63f85a86c1c45500f45ff48fbb 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -1181,11 +1181,14 @@ public class LevelChunk extends ChunkAccess {