From da03d4a1bc5cf1bafaca65247e613964f630f981 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Mon, 28 Feb 2022 22:43:03 -0700
Subject: [PATCH] Initial 1.18 update

---
 build.gradle.kts                              |   2 +-
 gradle.properties                             |   4 +-
 patches/api/Build-system-changes.patch        |   2 +-
 patches/api/Convert-project-to-Gradle.patch   |   6 +-
 patches/api/Expand-the-Registry-API.patch     |  24 ---
 ...e-PlayerProfile-in-AsyncPreLoginEven.patch |  34 +---
 patches/server/Actually-unload-POI-data.patch |  14 +-
 .../server/Add-BellRevealRaiderEvent.patch    |   2 +-
 patches/server/Add-BlockBreakBlockEvent.patch |   2 +-
 patches/server/Add-GameEvent-tags.patch       |  35 ++--
 .../Add-PlayerItemFrameChangeEvent.patch      |   4 +-
 patches/server/Add-PlayerJumpEvent.patch      |   2 +-
 .../server/Add-PlayerKickEvent-causes.patch   |   2 +-
 patches/server/Add-StructureLocateEvent.patch |  12 +-
 .../Add-config-for-stronghold-seed.patch      |  57 -------
 ...tion-for-logging-player-ip-addresses.patch |  20 +--
 ...-configurable-height-for-slime-spawn.patch |   4 +-
 .../Add-exception-reporting-event.patch       |  14 +-
 ...event-players-from-moving-into-unloa.patch |   2 +-
 ...-address-to-AsyncPlayerPreLoginEvent.patch |  12 +-
 patches/server/Add-setMaxPlayers-API.patch    |   2 +-
 patches/server/Add-velocity-warnings.patch    |   2 +-
 .../Added-ServerResourcesReloadedEvent.patch  |  15 +-
 ...Hostname-to-AsyncPlayerPreLoginEvent.patch |  12 +-
 patches/server/Adventure.patch                |  34 ++--
 .../Allow-Saving-of-Oversized-Chunks.patch    |   4 +-
 ...riting-of-comments-to-server.propert.patch |  25 +--
 ...Item-entities-with-World.spawnEntity.patch |   4 +-
 ...-using-signs-inside-spawn-protection.patch |  12 +-
 patches/server/Anti-Xray.patch                |  53 +++---
 patches/server/AnvilDamageEvent.patch         |   2 +-
 ...difications-to-critical-entity-state.patch |   2 +-
 .../Asynchronous-chunk-IO-and-loading.patch   |  16 +-
 ...culate-regionfile-header-if-it-is-co.patch |  24 +--
 ...opper-searches-if-there-are-no-items.patch |   2 +-
 .../Bound-Treasure-Maps-to-World-Border.patch |  22 +--
 patches/server/Brand-support.patch            |  10 +-
 patches/server/Build-system-changes.patch     |   6 +-
 patches/server/Cache-block-data-strings.patch |   4 +-
 ...ServerListPingEvent-for-legacy-pings.patch |  18 +-
 .../Configurable-Grass-Spread-Tick-Rate.patch |   2 +-
 ...le-Keep-Spawn-Loaded-range-per-world.patch |   6 +-
 .../Configurable-Player-Collision.patch       |  10 +-
 .../server/Configurable-RCON-IP-address.patch |   6 +-
 .../server/Configurable-feature-seeds.patch   |   8 +-
 .../Configurable-flying-kick-messages.patch   |   2 +-
 patches/server/Custom-Potion-Mixes.patch      |   6 +-
 ...ktraces-in-log-messages-crash-report.patch |   6 +-
 ...l-more-information-in-watchdog-dumps.patch |   8 +-
 patches/server/Disable-ice-and-snow.patch     |   2 +-
 ...low-bees-to-load-chunks-for-beehives.patch |   2 +-
 ...ket-level-changes-while-unloading-pl.patch |   6 +-
 ...-profile-lookups-to-worldgen-threads.patch |   2 +-
 ...t-allow-digging-into-unloaded-chunks.patch |   6 +-
 ...ck-and-tnt-entities-at-the-specified.patch |   2 +-
 .../server/Entity-Activation-Range-2.0.patch  |   2 +-
 .../Entity-load-save-limit-per-chunk.patch    |   2 +-
 .../server/Execute-chunk-tasks-mid-tick.patch |  26 ++-
 ...PI-for-Reason-Source-Triggering-play.patch |   2 +-
 ...vanilla-BiomeProvider-from-WorldInfo.patch |   8 +-
 ...-Chunk-Post-Processing-deadlock-risk.patch |   4 +-
 ...t-isSectionEmpty-int-and-optimize-Pa.patch |  13 +-
 ...Fix-Not-a-string-Map-Conversion-spam.patch |   2 +-
 patches/server/Fix-Old-Sign-Conversion.patch  |   4 +-
 ...ld-Difficulty-Remembering-Difficulty.patch |  19 +--
 .../Fix-World-isChunkGenerated-calls.patch    |  14 +-
 ...on-leak-when-converting-pre-1.18-chu.patch |  23 ---
 ...x-and-optimise-world-force-upgrading.patch |   4 +-
 ...chunks-refusing-to-unload-at-low-TPS.patch |   2 +-
 ...y-type-tags-suggestions-in-selectors.patch | 160 ------------------
 ...r-large-move-vectors-crashing-server.patch |   4 +-
 ...ix-int-overflow-in-chunk-range-check.patch |  25 ---
 ...-event-not-being-called-in-adventure.patch |  12 +-
 ...l-LevelStem-in-StructureCheck-from-C.patch |   6 +-
 .../Fix-riding-distance-statistics.patch      |  46 -----
 patches/server/Fix-sand-duping.patch          |   2 +-
 patches/server/Fix-this-stupid-bullshit.patch |   2 +-
 .../Fix-xp-reward-for-baby-zombies.patch      |   2 +-
 .../Flat-bedrock-generator-settings.patch     |  12 +-
 patches/server/Goat-ram-API.patch             |  10 +-
 ...rializing-mismatching-chunk-coordina.patch |   2 +-
 ...n-prefixes-using-Log4J-configuration.patch |   2 +-
 ...single-and-multi-AABB-VoxelShapes-an.patch |  49 ++++--
 ...k-Priority-Urgency-System-for-Chunks.patch |  28 +--
 patches/server/Implement-Keyed-on-World.patch |   2 +-
 ...er-Thread-Pool-and-Thread-Priorities.patch |   2 +-
 patches/server/Improve-ServerGUI.patch        |  16 +-
 .../Improve-boat-collision-performance.patch  |   2 +-
 .../server/Improved-Watchdog-Support.patch    |  12 +-
 .../Lag-compensate-block-breaking.patch       |   6 +-
 patches/server/MC-Dev-fixes.patch             |  51 ++----
 patches/server/MC-Utils.patch                 |  91 +++++-----
 ...ke-legacy-ping-handler-more-reliable.patch |   2 +-
 ...more-aggressive-in-the-chunk-unload-.patch |   5 +-
 ...ter-animal-spawn-height-configurable.patch |   2 +-
 ...ove-range-check-for-block-placing-up.patch |  22 +--
 ...ckPhysicsEvent-if-a-plugin-has-a-lis.patch |  10 +-
 ...primise-map-impl-for-tracked-players.patch |   4 +-
 ...timise-BlockSoil-nearby-water-lookup.patch |   3 +-
 ...timise-IEntityAccess-getPlayerByUUID.patch |   2 +-
 .../server/Optimise-WorldServer-notify.patch  |   4 +-
 .../Optimise-chunk-tick-iteration.patch       |  22 +--
 ...on-checking-in-player-move-packet-ha.patch |  34 ++--
 .../server/Optimise-general-POI-access.patch  |   4 +-
 .../Optimise-nearby-player-lookups.patch      |  12 +-
 .../Optimise-non-flush-packet-sending.patch   |   6 +-
 .../Optimise-random-block-ticking.patch       |  88 ++++++----
 .../Optimize-Bit-Operations-by-inlining.patch |   2 +-
 ...ptimize-Collision-to-not-load-chunks.patch |   2 +-
 patches/server/Optimize-MappedRegistry.patch  |  34 ++--
 ...ze-NetworkManager-Exception-Handling.patch |  38 ++---
 ...rLevels-chunk-level-checking-methods.patch |  19 ++-
 patches/server/Optimize-Util-sequence.patch   |  44 -----
 ...erCloseEnoughForSpawning-to-use-dist.patch |   6 +-
 ...ldBounds-and-getBlockState-for-inlin.patch |   2 +-
 ...efault-CustomSpawners-in-custom-worl.patch |   6 +-
 patches/server/Paper-config-files.patch       |   2 +-
 ...layer-View-Distance-API-placeholders.patch |  14 +-
 .../server/Player.setPlayerProfile-API.patch  |  22 ++-
 ...CreateEvent-needs-to-know-its-entity.patch |   4 +-
 patches/server/PreCreatureSpawnEvent.patch    |   2 +-
 ...oftlocked-end-exit-portal-generation.patch |   3 +-
 ...nk-loads-when-villagers-try-to-find-.patch |   2 +-
 .../Remove-some-streams-from-structures.patch |  38 +++--
 .../Replace-player-chunk-loader-system.patch  |  59 ++++---
 .../Replace-ticket-level-propagator.patch     |   8 +-
 ...ite-entity-bounding-box-lookup-calls.patch |  98 ++++++-----
 patches/server/Rewrite-the-light-engine.patch |  20 +--
 patches/server/Setup-Gradle-project.patch     |  24 ++-
 ...ient-crashes-server-lists-and-Mojang.patch |   2 +-
 ...prove-performance-of-the-end-generat.patch |   8 +-
 ...awn-player-in-correct-world-on-login.patch |   2 +-
 .../Support-old-UUID-format-for-NBT.patch     |   4 +-
 ...ttedContainer-instead-of-ReentrantLo.patch |   2 +-
 patches/server/Timings-v2.patch               |  53 +++---
 patches/server/Turtle-API.patch               |   4 +-
 patches/server/Update-Log4j.patch             |   3 +-
 .../Use-ConcurrentHashMap-in-JsonList.patch   |   2 +-
 ...oleAppender-for-console-improvements.patch |  22 +--
 .../Use-a-Shared-Random-for-Entities.patch    |   2 +-
 ...lStem-registry-when-loading-default-.patch |   6 +-
 ...etChunkIfLoadedImmediately-in-places.patch |   2 +-
 ...ookup-for-Treasure-Maps-Fixes-lag-fr.patch |  17 +-
 patches/server/Validate-usernames.patch       |   1 +
 .../Vanilla-command-permission-fixes.patch    |   2 +-
 .../Vanished-players-don-t-have-rights.patch  |   4 +-
 ...-block-falling-causing-client-desync.patch |  26 +--
 ...telist-use-configurable-kick-message.patch |   2 +-
 ...ement-optional-per-player-mob-spawns.patch |   2 +-
 .../incremental-chunk-and-player-saving.patch |   8 +-
 ...-possibility-for-getServer-singleton.patch |   4 +-
 work/BuildData                                |   2 +-
 work/Bukkit                                   |   2 +-
 work/CraftBukkit                              |   2 +-
 work/Spigot                                   |   2 +-
 155 files changed, 823 insertions(+), 1298 deletions(-)
 delete mode 100644 patches/server/Add-config-for-stronghold-seed.patch
 delete mode 100644 patches/server/Fix-WorldGenRegion-leak-when-converting-pre-1.18-chu.patch
 delete mode 100644 patches/server/Fix-entity-type-tags-suggestions-in-selectors.patch
 delete mode 100644 patches/server/Fix-int-overflow-in-chunk-range-check.patch
 delete mode 100644 patches/server/Fix-riding-distance-statistics.patch
 delete mode 100644 patches/server/Optimize-Util-sequence.patch

diff --git a/build.gradle.kts b/build.gradle.kts
index 83f28bb8ac..39dae25466 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -56,7 +56,7 @@ repositories {
 }
 
 dependencies {
-    paramMappings("net.fabricmc:yarn:1.18.1+build.22:mergedv2")
+    paramMappings("net.fabricmc:yarn:1.18.2+build.1:mergedv2")
     remapper("net.fabricmc:tiny-remapper:0.8.1:fat")
     decompiler("net.minecraftforge:forgeflower:1.5.498.22")
     paperclip("io.papermc:paperclip:3.0.2")
diff --git a/gradle.properties b/gradle.properties
index a0297b8e1f..398db6bb68 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,7 +1,7 @@
 group=io.papermc.paper
-version=1.18.1-R0.1-SNAPSHOT
+version=1.18.2-R0.1-SNAPSHOT
 
-mcVersion=1.18.1
+mcVersion=1.18.2
 
 org.gradle.caching=true
 org.gradle.parallel=true
diff --git a/patches/api/Build-system-changes.patch b/patches/api/Build-system-changes.patch
index f6edbed244..6cc86039b7 100644
--- a/patches/api/Build-system-changes.patch
+++ b/patches/api/Build-system-changes.patch
@@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/build.gradle.kts
 +++ b/build.gradle.kts
 @@ -0,0 +0,0 @@ dependencies {
-     api("com.google.code.gson:gson:2.8.8")
+     api("com.google.code.gson:gson:2.8.9")
      api("net.md-5:bungeecord-chat:1.16-R0.4")
      api("org.yaml:snakeyaml:1.30")
 +    // Paper start
diff --git a/patches/api/Convert-project-to-Gradle.patch b/patches/api/Convert-project-to-Gradle.patch
index b1c26a86c5..850313dd98 100644
--- a/patches/api/Convert-project-to-Gradle.patch
+++ b/patches/api/Convert-project-to-Gradle.patch
@@ -45,7 +45,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // api dependencies are listed transitively to API consumers
 +    api("commons-lang:commons-lang:2.6")
 +    api("com.google.guava:guava:31.0.1-jre")
-+    api("com.google.code.gson:gson:2.8.8")
++    api("com.google.code.gson:gson:2.8.9")
 +    api("net.md-5:bungeecord-chat:1.16-R0.4")
 +    api("org.yaml:snakeyaml:1.30")
 +
@@ -110,7 +110,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -
 -    <groupId>org.spigotmc</groupId>
 -    <artifactId>spigot-api</artifactId>
--    <version>1.18.1-R0.1-SNAPSHOT</version>
+-    <version>1.18.2-R0.1-SNAPSHOT</version>
 -    <packaging>jar</packaging>
 -
 -    <name>Spigot-API</name>
@@ -153,7 +153,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        <dependency>
 -            <groupId>com.google.code.gson</groupId>
 -            <artifactId>gson</artifactId>
--            <version>2.8.8</version>
+-            <version>2.8.9</version>
 -            <scope>compile</scope>
 -        </dependency>
 -        <dependency>
diff --git a/patches/api/Expand-the-Registry-API.patch b/patches/api/Expand-the-Registry-API.patch
index 749ec9dc74..cf3e1d1300 100644
--- a/patches/api/Expand-the-Registry-API.patch
+++ b/patches/api/Expand-the-Registry-API.patch
@@ -34,27 +34,3 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      // Paper end
  
      /**
-diff --git a/src/main/java/org/bukkit/StructureType.java b/src/main/java/org/bukkit/StructureType.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/StructureType.java
-+++ b/src/main/java/org/bukkit/StructureType.java
-@@ -0,0 +0,0 @@ import org.jetbrains.annotations.Nullable;
-  * The registration of new {@link StructureType}s is case-sensitive.
-  */
- // Order is retrieved from WorldGenFactory
--public final class StructureType {
-+public final class StructureType implements Keyed { // Paper - implement keyed
- 
-     private static final Map<String, StructureType> structureTypeMap = new HashMap<>();
- 
-@@ -0,0 +0,0 @@ public final class StructureType {
-     public static Map<String, StructureType> getStructureTypes() {
-         return ImmutableMap.copyOf(structureTypeMap);
-     }
-+    // Paper start
-+    @Override
-+    public @NotNull NamespacedKey getKey() {
-+        return NamespacedKey.minecraft(this.name);
-+    }
-+    // Paper end
- }
diff --git a/patches/server/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/server/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch
index ec80f5732d..d67ee1a990 100644
--- a/patches/server/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch
+++ b/patches/server/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch
@@ -9,37 +9,21 @@ diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListene
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
 +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
-@@ -0,0 +0,0 @@
- package net.minecraft.server.network;
- 
-+import com.destroystokyo.paper.profile.CraftPlayerProfile;
-+import com.destroystokyo.paper.profile.PlayerProfile;
- import com.mojang.authlib.GameProfile;
- import com.mojang.authlib.exceptions.AuthenticationUnavailableException;
- import java.math.BigInteger;
-@@ -0,0 +0,0 @@ import org.apache.commons.lang3.Validate;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
- import io.papermc.paper.adventure.PaperAdventure; // Paper
-+import org.bukkit.Bukkit;
- import org.bukkit.craftbukkit.util.Waitable;
- import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
- import org.bukkit.event.player.PlayerPreLoginEvent;
 @@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
                          java.util.UUID uniqueId = ServerLoginPacketListenerImpl.this.gameProfile.getId();
                          final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server;
  
 -                        AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId);
-+                            // Paper start
-+                            PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName);
-+                            AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile);
++                        // Paper start
++                        com.destroystokyo.paper.profile.PlayerProfile profile = org.bukkit.Bukkit.createProfile(uniqueId, playerName);
++                        AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile);
                          server.getPluginManager().callEvent(asyncEvent);
-+                            profile = asyncEvent.getPlayerProfile();
-+                            profile.complete();
-+                            gameProfile = CraftPlayerProfile.asAuthlibCopy(profile);
-+                            playerName = gameProfile.getName();
-+                            uniqueId = gameProfile.getId();
-+                            // Paper end
++                        profile = asyncEvent.getPlayerProfile();
++                        profile.complete();
++                        gameProfile = com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile);
++                        playerName = gameProfile.getName();
++                        uniqueId = gameProfile.getId();
++                        // Paper end
  
                          if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) {
                              final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId);
diff --git a/patches/server/Actually-unload-POI-data.patch b/patches/server/Actually-unload-POI-data.patch
index f4b34a6fc7..f689d5e27c 100644
--- a/patches/server/Actually-unload-POI-data.patch
+++ b/patches/server/Actually-unload-POI-data.patch
@@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  this.updatingChunks.queueUpdate(pos, holder); // Paper - Don't copy
                  this.modified = true;
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
-         gameprofilerfiller.pop();
+         return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || !this.updatingChunkMap.isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.queueSorter.hasWork() || this.distanceManager.hasTickets();
      }
  
 -    private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more
@@ -39,11 +39,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                          ((LevelChunk) ichunkaccess).setLoaded(false);
                      }
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
-                     for (int index = 0, len = this.regionManagers.size(); index < len; ++index) {
-                         this.regionManagers.get(index).removeChunk(holder.pos.x, holder.pos.z);
-                     }
-+                    this.getPoiManager().queueUnload(holder.pos.longKey, MinecraftServer.currentTickLong + 1); // Paper - unload POI data
-                 } // Paper end
+                 for (int index = 0, len = this.regionManagers.size(); index < len; ++index) {
+                     this.regionManagers.get(index).removeChunk(holder.pos.x, holder.pos.z);
+                 }
++                this.getPoiManager().queueUnload(holder.pos.longKey, MinecraftServer.currentTickLong + 1); // Paper - unload POI data
+             } // Paper end
                  } finally { this.unloadingPlayerChunk = unloadingBefore; } // Paper - do not allow ticket level changes while unloading chunks
  
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -313,7 +313,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end - actually unload POI data
 +
      protected void tick(BooleanSupplier shouldKeepTicking) {
-         while(!this.dirty.isEmpty() && shouldKeepTicking.getAsBoolean()) {
+         while(this.hasWork() && shouldKeepTicking.getAsBoolean()) {
              ChunkPos chunkPos = SectionPos.of(this.dirty.firstLong()).chunk();
 @@ -0,0 +0,0 @@ public class SectionStorage<R> extends RegionFileStorage implements AutoCloseabl
                  });
diff --git a/patches/server/Add-BellRevealRaiderEvent.patch b/patches/server/Add-BellRevealRaiderEvent.patch
index 27911b4ffd..06df17f771 100644
--- a/patches/server/Add-BellRevealRaiderEvent.patch
+++ b/patches/server/Add-BellRevealRaiderEvent.patch
@@ -18,7 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      private static void showBellParticles(Level world, BlockPos pos, List<LivingEntity> hearingEntities) {
 @@ -0,0 +0,0 @@ public class BellBlockEntity extends BlockEntity {
-         return entity.isAlive() && !entity.isRemoved() && pos.closerThan(entity.position(), 48.0D) && entity.getType().is(EntityTypeTags.RAIDERS);
+         return entity.isAlive() && !entity.isRemoved() && pos.closerToCenterThan(entity.position(), 48.0D) && entity.getType().is(EntityTypeTags.RAIDERS);
      }
  
 -    private static void glow(LivingEntity entity) {
diff --git a/patches/server/Add-BlockBreakBlockEvent.patch b/patches/server/Add-BlockBreakBlockEvent.patch
index ae17f28959..34d7d82a98 100644
--- a/patches/server/Add-BlockBreakBlockEvent.patch
+++ b/patches/server/Add-BlockBreakBlockEvent.patch
@@ -43,7 +43,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -                dropResources(iblockdata1, world, blockposition3, tileentity);
 +                dropResources(iblockdata1, world, blockposition3, tileentity, pos); // Paper
                  world.setBlock(blockposition3, Blocks.AIR.defaultBlockState(), 18);
-                 if (!iblockdata1.is((Tag) BlockTags.FIRE)) {
+                 if (!iblockdata1.is(BlockTags.FIRE)) {
                      world.addDestroyBlockEffect(blockposition3, iblockdata1);
 diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
diff --git a/patches/server/Add-GameEvent-tags.patch b/patches/server/Add-GameEvent-tags.patch
index b4fb687a14..ad47f91067 100644
--- a/patches/server/Add-GameEvent-tags.patch
+++ b/patches/server/Add-GameEvent-tags.patch
@@ -13,62 +13,69 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +package io.papermc.paper;
 +
 +import net.minecraft.core.Registry;
-+import net.minecraft.resources.ResourceLocation;
-+import net.minecraft.tags.TagCollection;
++import net.minecraft.resources.ResourceKey;
++import net.minecraft.tags.TagKey;
 +import org.bukkit.GameEvent;
 +import org.bukkit.craftbukkit.tag.CraftTag;
 +import org.bukkit.craftbukkit.util.CraftNamespacedKey;
 +import org.jetbrains.annotations.NotNull;
 +
-+import java.util.Collections;
 +import java.util.Objects;
 +import java.util.Set;
 +import java.util.stream.Collectors;
 +
 +public class CraftGameEventTag extends CraftTag<net.minecraft.world.level.gameevent.GameEvent, GameEvent> {
 +
-+    public CraftGameEventTag(TagCollection<net.minecraft.world.level.gameevent.GameEvent> registry, ResourceLocation tag) {
++    public CraftGameEventTag(net.minecraft.core.Registry<net.minecraft.world.level.gameevent.GameEvent> registry, TagKey<net.minecraft.world.level.gameevent.GameEvent> tag) {
 +        super(registry, tag);
 +    }
 +
 +    @Override
 +    public boolean isTagged(@NotNull GameEvent item) {
-+        return this.getHandle().contains(Registry.GAME_EVENT.get(CraftNamespacedKey.toMinecraft(item.getKey())));
++        return registry.getHolderOrThrow(ResourceKey.create(Registry.GAME_EVENT_REGISTRY, CraftNamespacedKey.toMinecraft(item.getKey()))).is(tag);
 +    }
 +
 +    @Override
 +    public @NotNull Set<GameEvent> getValues() {
-+        return this.getHandle().getValues().stream().map(ge -> Objects.requireNonNull(GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(Registry.GAME_EVENT.getKey(ge))), ge + " is not a recognized game event")).collect(Collectors.toUnmodifiableSet());
++        return getHandle().stream().map((nms) -> Objects.requireNonNull(GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(Registry.GAME_EVENT.getKey(nms.value()))), nms + " is not a recognized game event")).collect(Collectors.toUnmodifiableSet());
 +    }
 +}
 diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
 +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+@@ -0,0 +0,0 @@ import net.minecraft.world.level.biome.BiomeSource;
+ import net.minecraft.world.level.block.Block;
+ import net.minecraft.world.level.dimension.DimensionType;
+ import net.minecraft.world.level.dimension.LevelStem;
++import net.minecraft.world.level.gameevent.GameEvent;
+ import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
+ import net.minecraft.world.level.levelgen.PatrolSpawner;
+ import net.minecraft.world.level.levelgen.PhantomSpawner;
 @@ -0,0 +0,0 @@ public final class CraftServer implements Server {
                  Preconditions.checkArgument(clazz == org.bukkit.entity.EntityType.class, "Entity type namespace must have entity type");
  
-                 return (org.bukkit.Tag<T>) new CraftEntityTag(EntityTypeTags.getAllTags(), key);
+                 return (org.bukkit.Tag<T>) new CraftEntityTag(Registry.ENTITY_TYPE, TagKey.create(Registry.ENTITY_TYPE_REGISTRY, key));
 +            // Paper start
 +            case org.bukkit.Tag.REGISTRY_GAME_EVENTS:
 +                Preconditions.checkArgument(clazz == org.bukkit.GameEvent.class, "Game Event namespace must have GameEvent type");
 +
-+                return (org.bukkit.Tag<T>) new io.papermc.paper.CraftGameEventTag(net.minecraft.tags.GameEventTags.getAllTags(), key);
++                return (org.bukkit.Tag<T>) new io.papermc.paper.CraftGameEventTag(Registry.GAME_EVENT, TagKey.create(Registry.GAME_EVENT_REGISTRY, key));
 +            // Paper end
              default:
                  throw new IllegalArgumentException();
          }
 @@ -0,0 +0,0 @@ public final class CraftServer implements Server {
  
-                 TagCollection<EntityType<?>> entityTags = EntityTypeTags.getAllTags();
-                 return entityTags.getAllTags().keySet().stream().map(key -> (org.bukkit.Tag<T>) new CraftEntityTag(entityTags, key)).collect(ImmutableList.toImmutableList());
-+                // Paper start
+                 Registry<EntityType<?>> entityTags = Registry.ENTITY_TYPE;
+                 return entityTags.getTags().map(pair -> (org.bukkit.Tag<T>) new CraftEntityTag(entityTags, pair.getFirst())).collect(ImmutableList.toImmutableList());
++            // Paper start
 +            case org.bukkit.Tag.REGISTRY_GAME_EVENTS:
 +                Preconditions.checkArgument(clazz == org.bukkit.GameEvent.class);
 +
-+                TagCollection<net.minecraft.world.level.gameevent.GameEvent> gameEvents = net.minecraft.tags.GameEventTags.getAllTags();
-+                return gameEvents.getAllTags().keySet().stream().map(key -> (org.bukkit.Tag<T>) new io.papermc.paper.CraftGameEventTag(gameEvents, key)).toList();
-+                // Paper end
++                Registry<GameEvent> gameEvents = Registry.GAME_EVENT;
++                return gameEvents.getTags().map(pair -> (org.bukkit.Tag<T>) new io.papermc.paper.CraftGameEventTag(gameEvents, pair.getFirst())).collect(ImmutableList.toImmutableList());
++            // Paper end
              default:
                  throw new IllegalArgumentException();
          }
diff --git a/patches/server/Add-PlayerItemFrameChangeEvent.patch b/patches/server/Add-PlayerItemFrameChangeEvent.patch
index 81fd611cfd..37796a50f6 100644
--- a/patches/server/Add-PlayerItemFrameChangeEvent.patch
+++ b/patches/server/Add-PlayerItemFrameChangeEvent.patch
@@ -8,9 +8,9 @@ diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
 +++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
-@@ -0,0 +0,0 @@
- package net.minecraft.world.entity.decoration;
+@@ -0,0 +0,0 @@ package net.minecraft.world.entity.decoration;
  
+ import com.mojang.logging.LogUtils;
  import javax.annotation.Nullable;
 +import io.papermc.paper.event.player.PlayerItemFrameChangeEvent; // Paper
  import net.minecraft.core.BlockPos;
diff --git a/patches/server/Add-PlayerJumpEvent.patch b/patches/server/Add-PlayerJumpEvent.patch
index e012450b01..f8041c3bcd 100644
--- a/patches/server/Add-PlayerJumpEvent.patch
+++ b/patches/server/Add-PlayerJumpEvent.patch
@@ -43,4 +43,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                                // Paper end
                              }
  
-                             this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9));
+                             boolean flag1 = this.player.verticalCollisionBelow;
diff --git a/patches/server/Add-PlayerKickEvent-causes.patch b/patches/server/Add-PlayerKickEvent-causes.patch
index 562c62a00e..f01c709287 100644
--- a/patches/server/Add-PlayerKickEvent-causes.patch
+++ b/patches/server/Add-PlayerKickEvent-causes.patch
@@ -61,7 +61,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
-         if (this.clientIsFloating && !this.player.isSleeping()) {
+         if (this.clientIsFloating && !this.player.isSleeping() && !this.player.isPassenger()) {
              if (++this.aboveGroundTickCount > 80) {
                  ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString());
 -                this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message
diff --git a/patches/server/Add-StructureLocateEvent.patch b/patches/server/Add-StructureLocateEvent.patch
index 9f34d62710..c24e18f5ee 100644
--- a/patches/server/Add-StructureLocateEvent.patch
+++ b/patches/server/Add-StructureLocateEvent.patch
@@ -11,9 +11,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
  
      @Nullable
-     public BlockPos findNearestMapFeature(ServerLevel world, StructureFeature<?> structureFeature, BlockPos center, int radius, boolean skipExistingChunks) {
+     public Pair<BlockPos, Holder<ConfiguredStructureFeature<?, ?>>> findNearestMapFeature(ServerLevel worldserver, HolderSet<ConfiguredStructureFeature<?, ?>> holderset, BlockPos center, int radius, boolean skipExistingChunks) {
 +        // Paper start
-+        org.bukkit.World world1 = world.getWorld();
++        /*org.bukkit.World world1 = worldserver.getWorld();
 +        org.bukkit.Location originLocation = new org.bukkit.Location(world1, center.getX(), center.getY(), center.getZ());
 +        io.papermc.paper.event.world.StructureLocateEvent event = new io.papermc.paper.event.world.StructureLocateEvent(world1, originLocation, org.bukkit.StructureType.getStructureTypes().get(structureFeature.getFeatureName()), radius, skipExistingChunks);
 +        if(!event.callEvent()) return null;
@@ -24,8 +24,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        // Get radius and whether to find unexplored structures (re)defined by event call.
 +        radius = event.getRadius();
 +        skipExistingChunks = event.shouldFindUnexplored();
-+        structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(event.getType().getName());
++        structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(event.getType().getName());*/
 +        // Paper end
-         if (structureFeature == StructureFeature.STRONGHOLD) {
-             this.generateStrongholds();
-             BlockPos blockposition1 = null;
+         Set<Holder<Biome>> set = (Set) holderset.stream().flatMap((holder) -> {
+             return ((ConfiguredStructureFeature) holder.value()).biomes().stream();
+         }).collect(Collectors.toSet());
diff --git a/patches/server/Add-config-for-stronghold-seed.patch b/patches/server/Add-config-for-stronghold-seed.patch
deleted file mode 100644
index e1b85bc332..0000000000
--- a/patches/server/Add-config-for-stronghold-seed.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Jake Potrebic <jake.m.potrebic@gmail.com>
-Date: Thu, 13 Jan 2022 23:05:53 -0800
-Subject: [PATCH] Add config for stronghold seed
-
-
-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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
-+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
-@@ -0,0 +0,0 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
-         skipExistingChunks = event.shouldFindUnexplored();
-         structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(event.getType().getName());
-         // Paper end
-+        this.updateStructureSettings(world, this.settings); // Spigot // Paper - move up to include strongholds
-         if (structureFeature == StructureFeature.STRONGHOLD) {
-             this.generateStrongholds();
-             BlockPos blockposition1 = null;
-@@ -0,0 +0,0 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
- 
-             return blockposition1;
-         } else {
--            this.updateStructureSettings(world, this.settings); // Spigot
-             StructureFeatureConfiguration structuresettingsfeature = this.settings.getConfig(structureFeature);
-             ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>> immutablemultimap = this.settings.structures(structureFeature);
- 
-@@ -0,0 +0,0 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
-             java.util.Map<StructureFeature<?>, StructureFeatureConfiguration> original = settings.structureConfig();
-             java.util.Map<StructureFeature<?>, StructureFeatureConfiguration> updated = new java.util.HashMap<>();
-             org.spigotmc.SpigotWorldConfig conf = world.spigotConfig;
-+            this.strongholdSeed = Objects.requireNonNullElse(conf.strongholdSeed, this.strongholdSeed); // Paper
- 
-             for (java.util.Map.Entry<StructureFeature<?>, StructureFeatureConfiguration> entry : original.entrySet()) {
-                 String name = Registry.STRUCTURE_FEATURE.getKey(entry.getKey()).getPath();
-diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
-+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java
-@@ -0,0 +0,0 @@ public class SpigotWorldConfig
-     public int mansionSeed;
-     public int fossilSeed;
-     public int portalSeed;
-+    public Long strongholdSeed; // Paper
-     private void initWorldGenSeeds()
-     {
-         this.villageSeed = this.getInt( "seed-village", 10387312 );
-@@ -0,0 +0,0 @@ public class SpigotWorldConfig
-         this.mansionSeed = this.getInt( "seed-mansion", 10387319 );
-         this.fossilSeed = this.getInt( "seed-fossil", 14357921 );
-         this.portalSeed = this.getInt( "seed-portal", 34222645 );
-+        // Paper start
-+        final String strongholdSeedString = this.getString("seed-stronghold", "default");
-+        this.strongholdSeed = org.apache.commons.lang3.math.NumberUtils.isParsable(strongholdSeedString) ? Long.parseLong(strongholdSeedString) : null;
-+        // Paper end
-         this.log( "Custom Map Seeds:  Village: " + this.villageSeed + " Desert: " + this.desertSeed + " Igloo: " + this.iglooSeed + " Jungle: " + this.jungleSeed + " Swamp: " + this.swampSeed + " Monument: " + this.monumentSeed
-                 + " Ocean: " + this.oceanSeed + " Shipwreck: " + this.shipwreckSeed + " End City: " + this.endCitySeed + " Slime: " + this.slimeSeed + " Bastion: " + this.bastionSeed + " Fortress: " + this.fortressSeed + " Mansion: " + this.mansionSeed + " Fossil: " + this.fossilSeed + " Portal: " + this.portalSeed );
-     }
diff --git a/patches/server/Add-config-option-for-logging-player-ip-addresses.patch b/patches/server/Add-config-option-for-logging-player-ip-addresses.patch
index 1474e6731f..0a6aeebe93 100644
--- a/patches/server/Add-config-option-for-logging-player-ip-addresses.patch
+++ b/patches/server/Add-config-option-for-logging-player-ip-addresses.patch
@@ -25,19 +25,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
 +++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
 @@ -0,0 +0,0 @@ public class PacketUtils {
-                     // Paper start
-                     catch (Exception e) {
-                         Connection networkmanager = listener.getConnection();
+                         packet.handle(listener);
+                     } catch (Exception exception) {
+                         net.minecraft.network.Connection networkmanager = listener.getConnection();
 +                        String playerIP = com.destroystokyo.paper.PaperConfig.logPlayerIpAddresses ? String.valueOf(networkmanager.getRemoteAddress()) : "<ip address withheld>"; // Paper
                          if (networkmanager.getPlayer() != null) {
--                            LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), networkmanager.getRemoteAddress(), e);
-+                            LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), playerIP, e); // Paper
+-                            LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), networkmanager.getRemoteAddress(), exception);
++                            LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), playerIP, exception); // Paper
                          } else {
--                            LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getRemoteAddress(), e);
-+                            LOGGER.error("Error whilst processing packet {} for connection from {}", packet, playerIP, e); // Paper
+-                            LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getRemoteAddress(), exception);
++                            LOGGER.error("Error whilst processing packet {} for connection from {}", packet, playerIP, exception); // Paper
                          }
-                         TextComponent error = new TextComponent("Packet processing error");
-                         networkmanager.send(new ClientboundDisconnectPacket(error), (future) -> {
+                         net.minecraft.network.chat.TextComponent error = new net.minecraft.network.chat.TextComponent("Packet processing error");
+                         networkmanager.send(new net.minecraft.network.protocol.game.ClientboundDisconnectPacket(error), (future) -> {
 diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
@@ -50,7 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        LOGGER.debug("Ping: (1.6) from {}", com.destroystokyo.paper.PaperConfig.logPlayerIpAddresses ? ctx.channel().remoteAddress() : "<ip address withheld>"); // Paper
  
          InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port);
-         com.destroystokyo.paper.event.server.PaperServerListPingEvent event = PaperLegacyStatusClient.processRequest(
+         com.destroystokyo.paper.event.server.PaperServerListPingEvent event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest(
 diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
diff --git a/patches/server/Add-configurable-height-for-slime-spawn.patch b/patches/server/Add-configurable-height-for-slime-spawn.patch
index 98a0ea001c..61d50af414 100644
--- a/patches/server/Add-configurable-height-for-slime-spawn.patch
+++ b/patches/server/Add-configurable-height-for-slime-spawn.patch
@@ -33,11 +33,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      public static boolean checkSlimeSpawnRules(EntityType<Slime> type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) {
          if (world.getDifficulty() != Difficulty.PEACEFUL) {
--            if (Objects.equals(world.getBiomeName(pos), Optional.of(Biomes.SWAMP)) && pos.getY() > 50 && pos.getY() < 70 && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
+-            if (world.getBiome(pos).is(Biomes.SWAMP) && pos.getY() > 50 && pos.getY() < 70 && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
 +            // Paper start - Replace rules for Height in Swamp Biome
 +            final double maxHeightSwamp = world.getMinecraftWorld().paperConfig.slimeMaxSpawnHeightInSwamp;
 +            final double minHeightSwamp = world.getMinecraftWorld().paperConfig.slimeMinSpawnHeightInSwamp;
-+            if (Objects.equals(world.getBiomeName(pos), Optional.of(Biomes.SWAMP)) && pos.getY() > minHeightSwamp && pos.getY() < maxHeightSwamp && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
++            if (world.getBiome(pos).is(Biomes.SWAMP) && pos.getY() > minHeightSwamp && pos.getY() < maxHeightSwamp && random.nextFloat() < 0.5F && random.nextFloat() < world.getMoonBrightness() && world.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) {
 +            // Paper end
                  return checkMobSpawnRules(type, world, spawnReason, pos, random);
              }
diff --git a/patches/server/Add-exception-reporting-event.patch b/patches/server/Add-exception-reporting-event.patch
index 4bf1838c1a..132385a8a1 100644
--- a/patches/server/Add-exception-reporting-event.patch
+++ b/patches/server/Add-exception-reporting-event.patch
@@ -55,7 +55,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
                  return true;
              } catch (Exception exception) {
-                 ChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception);
+                 ChunkMap.LOGGER.error("Failed to save chunk {},{}", new Object[]{chunkcoordintpair.x, chunkcoordintpair.z, exception});
 +                com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper
                  return false;
              }
@@ -91,19 +91,11 @@ diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.ja
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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
-@@ -0,0 +0,0 @@
- package net.minecraft.world.entity.ai.village;
- 
-+import com.destroystokyo.paper.exception.ServerInternalException;
-+
- import java.util.Iterator;
- import javax.annotation.Nullable;
- import net.minecraft.core.BlockPos;
 @@ -0,0 +0,0 @@ public class VillageSiege implements CustomSpawner {
                  entityzombie.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombie.blockPosition()), MobSpawnType.EVENT, (SpawnGroupData) null, (CompoundTag) null);
              } catch (Exception exception) {
                  VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception);
-+                ServerInternalException.reportInternalException(exception); // Paper
++                com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper
                  return;
              }
  
@@ -161,7 +153,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import com.destroystokyo.paper.exception.ServerInternalException;
  import com.google.common.collect.Maps;
  import com.google.common.collect.UnmodifiableIterator;
- import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+ import com.mojang.logging.LogUtils;
 @@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess {
              this.removeBlockEntity(blockEntity.getBlockPos());
              // Paper end
diff --git a/patches/server/Add-option-to-prevent-players-from-moving-into-unloa.patch b/patches/server/Add-option-to-prevent-players-from-moving-into-unloa.patch
index 8f6ba0bf62..d4465a973a 100644
--- a/patches/server/Add-option-to-prevent-players-from-moving-into-unloa.patch
+++ b/patches/server/Add-option-to-prevent-players-from-moving-into-unloa.patch
@@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
                  if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) {
                  // CraftBukkit end
-                     ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getName().getString(), this.player.getName().getString(), d6, d7, d8);
+                     ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[]{entity.getName().getString(), this.player.getName().getString(), d6, d7, d8});
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
                          float prevYaw = this.player.getYRot();
                          float prevPitch = this.player.getXRot();
diff --git a/patches/server/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch
index 247114d7a6..6cc2d44692 100644
--- a/patches/server/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch
+++ b/patches/server/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch
@@ -16,10 +16,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                          java.util.UUID uniqueId = ServerLoginPacketListenerImpl.this.gameProfile.getId();
                          final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server;
  
-                             // Paper start
-                             PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile);
--                            AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile);
-+                            AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile);
+                         // Paper start
+                         com.destroystokyo.paper.profile.PlayerProfile profile = com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile);
+-                        AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile);
++                        AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); // Paper - add rawAddress
                          server.getPluginManager().callEvent(asyncEvent);
-                             profile = asyncEvent.getPlayerProfile();
-                             profile.complete(true);
+                         profile = asyncEvent.getPlayerProfile();
+                         profile.complete(true); // Paper - setPlayerProfileAPI
diff --git a/patches/server/Add-setMaxPlayers-API.patch b/patches/server/Add-setMaxPlayers-API.patch
index 196cca7904..8585496ae5 100644
--- a/patches/server/Add-setMaxPlayers-API.patch
+++ b/patches/server/Add-setMaxPlayers-API.patch
@@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public abstract class PlayerList {
      public final PlayerDataStorage playerIo;
      private boolean doWhiteList;
-     private final RegistryAccess.RegistryHolder registryHolder;
+     private final RegistryAccess.Frozen registryHolder;
 -    protected final int maxPlayers;
 +    protected int maxPlayers; public final void setMaxPlayers(int maxPlayers) { this.maxPlayers = maxPlayers; } // Paper - remove final and add setter
      private int viewDistance;
diff --git a/patches/server/Add-velocity-warnings.patch b/patches/server/Add-velocity-warnings.patch
index f7fa993bbd..622fe906c8 100644
--- a/patches/server/Add-velocity-warnings.patch
+++ b/patches/server/Add-velocity-warnings.patch
@@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          Preconditions.checkArgument(velocity != null, "velocity");
          velocity.checkFinite();
 +        // Paper start - Warn server owners when plugins try to set super high velocities
-+        if (!(this instanceof org.bukkit.entity.Projectile || this instanceof org.bukkit.entity.Minecart) && isUnsafeVelocity(velocity)) {
++        if (!(this instanceof org.bukkit.entity.Projectile) && isUnsafeVelocity(velocity)) {
 +            CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity " + entity.getScoreboardName() + " id #" + getEntityId() + " to (" + velocity.getX() + "," + velocity.getY() + "," + velocity.getZ() + ").");
 +        }
 +        // Paper end
diff --git a/patches/server/Added-ServerResourcesReloadedEvent.patch b/patches/server/Added-ServerResourcesReloadedEvent.patch
index e35ab8dee3..73f74c5b9b 100644
--- a/patches/server/Added-ServerResourcesReloadedEvent.patch
+++ b/patches/server/Added-ServerResourcesReloadedEvent.patch
@@ -14,21 +14,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
 +    // Paper start - add cause
 +    @Deprecated
-     public CompletableFuture<Void> reloadResources(Collection<String> datapacks) {
-+        return this.reloadResources(datapacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
+     public CompletableFuture<Void> reloadResources(Collection<String> dataPacks) {
+-        RegistryAccess.Frozen iregistrycustom_dimension = this.registryAccess();
++        return this.reloadResources(dataPacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
 +    }
-+    public CompletableFuture<Void> reloadResources(Collection<String> datapacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
++    public CompletableFuture<Void> reloadResources(Collection<String> dataPacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
 +        // Paper end
          CompletableFuture<Void> completablefuture = CompletableFuture.supplyAsync(() -> {
-             Stream<String> stream = datapacks.stream(); // CraftBukkit - decompile error
+             Stream<String> stream = dataPacks.stream(); // CraftBukkit - decompile error
              PackRepository resourcepackrepository = this.packRepository;
 @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
-             this.packRepository.setSelected(datapacks);
+             this.packRepository.setSelected(dataPacks);
              this.worldData.setDataPackConfig(MinecraftServer.getSelectedPacks(this.packRepository));
-             datapackresources.updateGlobals();
+             this.resources.managers.updateRegistryTags(this.registryAccess());
 +            new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper
              if (Thread.currentThread() != this.serverThread) return; // Paper
-             //this.getPlayerList().savePlayers(); // Paper - we don't need to do this
+             //this.getPlayerList().saveAll(); // Paper - we don't need to do this
              this.getPlayerList().reloadResources();
 diff --git a/src/main/java/net/minecraft/server/commands/ReloadCommand.java b/src/main/java/net/minecraft/server/commands/ReloadCommand.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
diff --git a/patches/server/Added-getHostname-to-AsyncPlayerPreLoginEvent.patch b/patches/server/Added-getHostname-to-AsyncPlayerPreLoginEvent.patch
index 524558d70c..5ce117e8c1 100644
--- a/patches/server/Added-getHostname-to-AsyncPlayerPreLoginEvent.patch
+++ b/patches/server/Added-getHostname-to-AsyncPlayerPreLoginEvent.patch
@@ -10,10 +10,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
 @@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
  
-                             // Paper start
-                             PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile);
--                            AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile);
-+                            AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile, ServerLoginPacketListenerImpl.this.hostname);
+                         // Paper start
+                         com.destroystokyo.paper.profile.PlayerProfile profile = com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile);
+-                        AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); // Paper - add rawAddress
++                        AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile, ServerLoginPacketListenerImpl.this.hostname); // Paper - add rawAddress & hostname
                          server.getPluginManager().callEvent(asyncEvent);
-                             profile = asyncEvent.getPlayerProfile();
-                             profile.complete(true);
+                         profile = asyncEvent.getPlayerProfile();
+                         profile.complete(true); // Paper - setPlayerProfileAPI
diff --git a/patches/server/Adventure.patch b/patches/server/Adventure.patch
index fbcfba54be..ded0eadd72 100644
--- a/patches/server/Adventure.patch
+++ b/patches/server/Adventure.patch
@@ -1048,7 +1048,7 @@ diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/j
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/network/PacketEncoder.java
 +++ b/src/main/java/net/minecraft/network/PacketEncoder.java
-@@ -0,0 +0,0 @@ package net.minecraft.network;
+@@ -0,0 +0,0 @@ import com.mojang.logging.LogUtils;
  import io.netty.buffer.ByteBuf;
  import io.netty.channel.ChannelHandlerContext;
  import io.netty.handler.codec.MessageToByteEncoder;
@@ -1295,8 +1295,8 @@ diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListener
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import org.apache.commons.lang3.StringUtils;
+ import org.slf4j.Logger;
  
  // CraftBukkit start
 +import io.papermc.paper.adventure.ChatProcessor; // Paper
@@ -1419,14 +1419,6 @@ diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListene
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
 +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
-@@ -0,0 +0,0 @@ import net.minecraft.world.entity.player.Player;
- import org.apache.commons.lang3.Validate;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
-+import io.papermc.paper.adventure.PaperAdventure; // Paper
- import org.bukkit.craftbukkit.util.Waitable;
- import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
- import org.bukkit.event.player.PlayerPreLoginEvent;
 @@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
                          if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) {
                              final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId);
@@ -1441,13 +1433,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                              ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable);
                              if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) {
 -                                ServerLoginPacketListenerImpl.this.disconnect(event.getKickMessage());
-+                                ServerLoginPacketListenerImpl.this.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure
++                                ServerLoginPacketListenerImpl.this.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure
                                  return;
                              }
                          } else {
                              if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
 -                                ServerLoginPacketListenerImpl.this.disconnect(asyncEvent.getKickMessage());
-+                                ServerLoginPacketListenerImpl.this.disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure
++                                ServerLoginPacketListenerImpl.this.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure
                                  return;
                              }
                          }
@@ -1468,7 +1460,7 @@ diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/ma
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/players/PlayerList.java
 +++ b/src/main/java/net/minecraft/server/players/PlayerList.java
-@@ -0,0 +0,0 @@ import com.mojang.authlib.GameProfile;
+@@ -0,0 +0,0 @@ import com.mojang.logging.LogUtils;
  import com.mojang.serialization.DataResult;
  import com.mojang.serialization.Dynamic;
  import io.netty.buffer.Unpooled;
@@ -1476,8 +1468,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  import java.io.File;
  import java.net.SocketAddress;
  import java.nio.file.Path;
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import net.minecraft.world.scores.Team;
+ import org.slf4j.Logger;
  
  // CraftBukkit start
 +import io.papermc.paper.adventure.PaperAdventure; // Paper
@@ -1618,9 +1610,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          return this.progress;
      }
  
-     public void setProgress(float percentage) {
-+        if (this.adventure != null) this.adventure.progress(percentage); // Paper
-         this.progress = percentage;
+     public void setProgress(float percent) {
++        if (this.adventure != null) this.adventure.progress(percent); // Paper
+         this.progress = percent;
      }
  
      public BossEvent.BossBarColor getColor() {
@@ -1680,8 +1672,8 @@ diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSaved
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
 +++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import net.minecraft.world.level.saveddata.SavedData;
+ import org.slf4j.Logger;
  
  // CraftBukkit start
 +import io.papermc.paper.adventure.PaperAdventure; // Paper
diff --git a/patches/server/Allow-Saving-of-Oversized-Chunks.patch b/patches/server/Allow-Saving-of-Oversized-Chunks.patch
index 5389d28811..941e326048 100644
--- a/patches/server/Allow-Saving-of-Oversized-Chunks.patch
+++ b/patches/server/Allow-Saving-of-Oversized-Chunks.patch
@@ -47,8 +47,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import net.minecraft.nbt.CompoundTag;
 +import net.minecraft.nbt.NbtIo;
  import net.minecraft.world.level.ChunkPos;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+ import org.slf4j.Logger;
+ 
 @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
      @VisibleForTesting
      protected final RegionBitmap usedSectors;
diff --git a/patches/server/Allow-skipping-writing-of-comments-to-server.propert.patch b/patches/server/Allow-skipping-writing-of-comments-to-server.propert.patch
index 06e5af14a8..35a15c68d3 100644
--- a/patches/server/Allow-skipping-writing-of-comments-to-server.propert.patch
+++ b/patches/server/Allow-skipping-writing-of-comments-to-server.propert.patch
@@ -11,24 +11,9 @@ diff --git a/src/main/java/net/minecraft/server/dedicated/Settings.java b/src/ma
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/dedicated/Settings.java
 +++ b/src/main/java/net/minecraft/server/dedicated/Settings.java
-@@ -0,0 +0,0 @@
- package net.minecraft.server.dedicated;
+@@ -0,0 +0,0 @@ public abstract class Settings<T extends Settings<T>> {
  
- import com.google.common.base.MoreObjects;
-+
-+import java.io.BufferedOutputStream; // Paper
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
- 
- import joptsimple.OptionSet; // CraftBukkit
- import net.minecraft.core.RegistryAccess;
-+import org.jetbrains.annotations.NotNull; // Paper
- 
- public abstract class Settings<T extends Settings<T>> {
- 
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
      public final Properties properties;
 +    private static final boolean skipComments = Boolean.getBoolean("Paper.skipServerPropertiesComments"); // Paper - allow skipping server.properties comments
      // CraftBukkit start
@@ -39,17 +24,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              // CraftBukkit end
              OutputStream outputstream = Files.newOutputStream(path);
 +            // Paper start - disable writing comments to properties file
-+            BufferedOutputStream bufferedOutputStream =  !skipComments ? new BufferedOutputStream(outputstream) : new BufferedOutputStream(outputstream) {
++            java.io.BufferedOutputStream bufferedOutputStream =  !skipComments ? new java.io.BufferedOutputStream(outputstream) : new java.io.BufferedOutputStream(outputstream) {
 +                private boolean isRightAfterNewline = true; // If last written char was newline
 +                private boolean isComment = false; // Are we writing comment currently?
 +
 +                @Override
-+                public void write(@NotNull byte[] b) throws IOException {
++                public void write(@org.jetbrains.annotations.NotNull byte[] b) throws IOException {
 +                    this.write(b, 0, b.length);
 +                }
 +
 +                @Override
-+                public void write(@NotNull byte[] bbuf, int off, int len) throws IOException {
++                public void write(@org.jetbrains.annotations.NotNull byte[] bbuf, int off, int len) throws IOException {
 +                    int latest_offset = off; // The latest offset, updated when comment ends
 +                    for (int index = off; index < off + len; ++index ) {
 +                        byte c = bbuf[index];
diff --git a/patches/server/Allow-spawning-Item-entities-with-World.spawnEntity.patch b/patches/server/Allow-spawning-Item-entities-with-World.spawnEntity.patch
index 88e5283e5f..7446d2009f 100644
--- a/patches/server/Allow-spawning-Item-entities-with-World.spawnEntity.patch
+++ b/patches/server/Allow-spawning-Item-entities-with-World.spawnEntity.patch
@@ -20,5 +20,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            entity = new net.minecraft.world.entity.item.ItemEntity(world, x, y, z, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Item.byBlock(net.minecraft.world.level.block.Blocks.DIRT)));
 +            // Paper end
          } else if (FallingBlock.class.isAssignableFrom(clazz)) {
-             entity = new FallingBlockEntity(world, x, y, z, this.getHandle().getBlockState(new BlockPos(x, y, z)));
-         } else if (Projectile.class.isAssignableFrom(clazz)) {
+             BlockPos pos = new BlockPos(x, y, z);
+             entity = FallingBlockEntity.fall(world, pos, this.getHandle().getBlockState(pos));
diff --git a/patches/server/Allow-using-signs-inside-spawn-protection.patch b/patches/server/Allow-using-signs-inside-spawn-protection.patch
index fe8df8bd1f..c6c968f4f6 100644
--- a/patches/server/Allow-using-signs-inside-spawn-protection.patch
+++ b/patches/server/Allow-using-signs-inside-spawn-protection.patch
@@ -23,11 +23,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
-         // Paper end
+                 int i = this.player.level.getMaxBuildHeight();
  
-         if (blockposition.getY() < i) {
--            if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract(this.player, blockposition)) { // CraftBukkit - reuse value // Paper - revert CB change
-+            if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.mayInteract(this.player, blockposition) || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getBlockState(blockposition).getBlock() instanceof net.minecraft.world.level.block.SignBlock))) { // CraftBukkit - reuse value // Paper - revert CB change // Paper - sign check
-                 this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706
-                 InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock);
+                 if (blockposition.getY() < i) {
+-                    if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract(this.player, blockposition)) {
++                    if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.mayInteract(this.player, blockposition)  || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getBlockState(blockposition).getBlock() instanceof net.minecraft.world.level.block.SignBlock))) { // Paper - sign check
+                         this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706
+                         InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock);
  
diff --git a/patches/server/Anti-Xray.patch b/patches/server/Anti-Xray.patch
index 9a6b0b2b13..65594b2c7d 100644
--- a/patches/server/Anti-Xray.patch
+++ b/patches/server/Anti-Xray.patch
@@ -1184,10 +1184,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
 @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
      // Add env and gen to constructor, WorldData -> WorldDataServer
-     public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey<Level> resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
+     public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey<Level> resourcekey, Holder<DimensionType> holder, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
          // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error
--        super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, biomeProvider, env);
-+        super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, biomeProvider, env, executor); // Paper - Async-Anti-Xray - Pass executor
+-        super(iworlddataserver, resourcekey, holder, minecraftserver::getProfiler, false, flag, i, gen, biomeProvider, env);
++        super(iworlddataserver, resourcekey, holder, minecraftserver::getProfiler, false, flag, i, gen, biomeProvider, env, executor); // Paper - Async-Anti-Xray - Pass executor
          this.pvpMode = minecraftserver.isPvpAllowed();
          this.convertable = convertable_conversionsession;
          this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile());
@@ -1198,7 +1198,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ import org.bukkit.event.player.PlayerInteractEvent;
  public class ServerPlayerGameMode {
  
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
 -    protected ServerLevel level;
 +    public ServerLevel level; // Paper - Anti-Xray - protected -> public
      protected final ServerPlayer player;
@@ -1229,8 +1229,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      public abstract ResourceKey<LevelStem> getTypeKey();
  
--    protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, final DimensionType dimensionmanager, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) {
-+    protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, final DimensionType dimensionmanager, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor
+-    protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) {
++    protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor
          this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
          this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper
          this.generator = gen;
@@ -1291,9 +1291,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        // Paper end
          this.bottomBlockY = LevelChunkSection.getBottomBlockY(chunkPos);
 -        this.states = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
--        this.biomes = new PalettedContainer<>(biomeRegistry, (Biome) biomeRegistry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
+-        this.biomes = new PalettedContainer<>(biomeRegistry.asHolderIdMap(), biomeRegistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
 +        this.states = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES, level == null || level.chunkPacketBlockController == null ? null : level.chunkPacketBlockController.getPresetBlockStates(level, pos, this.bottomBlockY())); // Paper - Anti-Xray - Add preset block states
-+        this.biomes = new PalettedContainer<>(biomeRegistry, (Biome) biomeRegistry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null); // Paper - Anti-Xray - Add preset biomes
++        this.biomes = new PalettedContainer<>(biomeRegistry.asHolderIdMap(), biomeRegistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null); // Paper - Anti-Xray - Add preset biomes
      }
  
      public static int getBottomBlockY(int chunkPos) {
@@ -1333,7 +1333,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -    public static <T> Codec<PalettedContainer<T>> codec(IdMap<T> idList, Codec<T> entryCodec, PalettedContainer.Strategy provider, T object) {
 +    // Paper start - Anti-Xray - Add preset values
 +    @Deprecated public static <T> Codec<PalettedContainer<T>> codec(IdMap<T> idList, Codec<T> entryCodec, PalettedContainer.Strategy provider, T object) { return PalettedContainer.codec(idList, entryCodec, provider, object, null); } // Notice for updates: Please make sure this function isn't used anywhere
-+    public static <T> Codec<PalettedContainer<T>> codec(IdMap<T> idList, Codec<T> entryCodec, PalettedContainer.Strategy provider, T object, T[] presetValues) {
++    public static <T> Codec<PalettedContainer<T>> codec(IdMap<T> idList, Codec<T> entryCodec, PalettedContainer.Strategy provider, T object, T @org.jetbrains.annotations.Nullable [] presetValues) {
          return RecordCodecBuilder.create((instance) -> {
              return instance.group(entryCodec.mapResult(ExtraCodecs.orElsePartial(object)).listOf().fieldOf("palette").forGetter(PalettedContainer.DiscData::paletteEntries), Codec.LONG_STREAM.optionalFieldOf("data").forGetter(PalettedContainer.DiscData::storage)).apply(instance, PalettedContainer.DiscData::new);
          }).comapFlatMap((serialized) -> {
@@ -1391,7 +1391,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -    public PalettedContainer(IdMap<T> idList, T object, PalettedContainer.Strategy paletteProvider) {
 +    // Paper start - Anti-Xray - Add preset values
 +    @Deprecated public PalettedContainer(IdMap<T> idList, T object, PalettedContainer.Strategy paletteProvider) { this(idList, object, paletteProvider, null); } // Notice for updates: Please make sure this constructor isn't used anywhere
-+    public PalettedContainer(IdMap<T> idList, T object, PalettedContainer.Strategy paletteProvider, T[] presetValues) {
++    public PalettedContainer(IdMap<T> idList, T object, PalettedContainer.Strategy paletteProvider, T @org.jetbrains.annotations.Nullable [] presetValues) {
 +        this.presetValues = presetValues;
 +        // Paper end
          this.strategy = paletteProvider;
@@ -1514,13 +1514,13 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializ
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import org.slf4j.Logger;
  
  public class ChunkSerializer {
  
 -    public static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codec(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
 +    public static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codec(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), null); // Paper - Anti-Xray - Add preset block states
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
      private static final String TAG_UPGRADE_DATA = "UpgradeData";
      private static final String BLOCK_TICKS_TAG = "block_ticks";
 @@ -0,0 +0,0 @@ public class ChunkSerializer {
@@ -1538,7 +1538,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                      });
                      logger = ChunkSerializer.LOGGER;
                      Objects.requireNonNull(logger);
-                     datapaletteblock = (PalettedContainer) dataresult.getOrThrow(false, logger::error);
+                     datapaletteblock = (PalettedContainer) ((DataResult<PalettedContainer<BlockState>>) dataresult).getOrThrow(false, logger::error); // CraftBukkit - decompile error
                  } else {
 -                    datapaletteblock = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
 +                    datapaletteblock = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES, presetBlockStates);
@@ -1548,19 +1548,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  PalettedContainer datapaletteblock1;
 @@ -0,0 +0,0 @@ public class ChunkSerializer {
                      Objects.requireNonNull(logger);
-                     datapaletteblock1 = (PalettedContainer) dataresult.getOrThrow(false, logger::error);
+                     datapaletteblock1 = (PalettedContainer) ((DataResult<PalettedContainer<Holder<Biome>>>) dataresult).getOrThrow(false, logger::error); // CraftBukkit - decompile error
                  } else {
--                    datapaletteblock1 = new PalettedContainer<>(iregistry, (Biome) iregistry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
-+                    datapaletteblock1 = new PalettedContainer<>(iregistry, (Biome) iregistry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null); // Paper - Anti-Xray - Add preset biomes
+-                    datapaletteblock1 = new PalettedContainer<>(iregistry.asHolderIdMap(), iregistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
++                    datapaletteblock1 = new PalettedContainer<>(iregistry.asHolderIdMap(), iregistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null); // Paper - Anti-Xray - Add preset biomes);
                  }
  
                  LevelChunkSection chunksection = new LevelChunkSection(b0, datapaletteblock, datapaletteblock1);
 @@ -0,0 +0,0 @@ public class ChunkSerializer {
      }
  
-     private static Codec<PalettedContainer<Biome>> makeBiomeCodec(Registry<Biome> biomeRegistry) {
--        return PalettedContainer.codec(biomeRegistry, biomeRegistry.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, (Biome) biomeRegistry.getOrThrow(Biomes.PLAINS));
-+        return PalettedContainer.codec(biomeRegistry, biomeRegistry.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, (Biome) biomeRegistry.getOrThrow(Biomes.PLAINS), null); // Paper - Anti-Xray - Add preset biomes
+     private static Codec<PalettedContainer<Holder<Biome>>> makeBiomeCodec(Registry<Biome> biomeRegistry) {
+-        return PalettedContainer.codec(biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getHolderOrThrow(Biomes.PLAINS));
++        return PalettedContainer.codec(biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getHolderOrThrow(Biomes.PLAINS), null); // Paper - Anti-Xray - Add preset biomes
      }
  
      public static CompoundTag write(ServerLevel world, ChunkAccess chunk) {
@@ -1578,20 +1578,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      public CraftChunk(net.minecraft.world.level.chunk.LevelChunk chunk) {
 @@ -0,0 +0,0 @@ public class CraftChunk implements Chunk {
-         PalettedContainer<Biome>[] biome = (includeBiome || includeBiomeTempRain) ? new PalettedContainer[cs.length] : null;
+         PalettedContainer<Holder<Biome>>[] biome = (includeBiome || includeBiomeTempRain) ? new PalettedContainer[cs.length] : null;
  
          Registry<Biome> iregistry = this.worldServer.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
--        Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(iregistry, iregistry.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS));
++<<<<<<< HEAD
+         Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getHolderOrThrow(Biomes.PLAINS));
++=======
 +        Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(iregistry, iregistry.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS), null); // Paper - Anti-Xray - Add preset biomes
++>>>>>>> Anti-Xray
  
          for (int i = 0; i < cs.length; i++) {
              CompoundTag data = new CompoundTag();
 @@ -0,0 +0,0 @@ public class CraftChunk implements Chunk {
+             empty[i] = true;
  
              if (biome != null) {
-                 Registry<Biome> iregistry = world.getHandle().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
--                biome[i] = new PalettedContainer<>(iregistry, iregistry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
++<<<<<<< HEAD
+                 biome[i] = new PalettedContainer<>(iregistry.asHolderIdMap(), iregistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
++=======
++                Registry<Biome> iregistry = world.getHandle().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
 +                biome[i] = new PalettedContainer<>(iregistry, iregistry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null); // Paper - Anti-Xray - Add preset biomes
++>>>>>>> Anti-Xray
              }
          }
  
diff --git a/patches/server/AnvilDamageEvent.patch b/patches/server/AnvilDamageEvent.patch
index 403d8b8b9d..b540c15d39 100644
--- a/patches/server/AnvilDamageEvent.patch
+++ b/patches/server/AnvilDamageEvent.patch
@@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
 +++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
 @@ -0,0 +0,0 @@ public class AnvilMenu extends ItemCombinerMenu {
-             if (!player.getAbilities().instabuild && iblockdata.is((Tag) BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) {
+             if (!player.getAbilities().instabuild && iblockdata.is(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) {
                  BlockState iblockdata1 = AnvilBlock.damage(iblockdata);
  
 +                // Paper start
diff --git a/patches/server/Async-catch-modifications-to-critical-entity-state.patch b/patches/server/Async-catch-modifications-to-critical-entity-state.patch
index e49eeceef7..4d386210f5 100644
--- a/patches/server/Async-catch-modifications-to-critical-entity-state.patch
+++ b/patches/server/Async-catch-modifications-to-critical-entity-state.patch
@@ -129,5 +129,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          public void onRemove(Entity.RemovalReason reason) {
 +            org.spigotmc.AsyncCatcher.catchOp("Entity remove"); // Paper
              if (!this.currentSection.remove(this.entity)) {
-                 PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (destroying due to {})", this.entity, SectionPos.of(this.currentSectionKey), reason);
+                 PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (destroying due to {})", new Object[]{this.entity, SectionPos.of(this.currentSectionKey), reason});
              }
diff --git a/patches/server/Asynchronous-chunk-IO-and-loading.patch b/patches/server/Asynchronous-chunk-IO-and-loading.patch
index 010481d4b2..333df5bc61 100644
--- a/patches/server/Asynchronous-chunk-IO-and-loading.patch
+++ b/patches/server/Asynchronous-chunk-IO-and-loading.patch
@@ -2311,11 +2311,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/server/Main.java
 @@ -0,0 +0,0 @@ public class Main {
  
-             convertable_conversionsession.saveDataTag(iregistrycustom_dimension, (SaveData) object);
+             convertable_conversionsession.saveDataTag(iregistrycustom_dimension, savedata);
              */
 +            Class.forName(net.minecraft.world.entity.npc.VillagerTrades.class.getName());// Paper - load this sync so it won't fail later async
              final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.spin((thread) -> {
-                 DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataFixers.getDataFixer(), minecraftsessionservice, gameprofilerepository, usercache, LoggerChunkProgressListener::new);
+                 DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, config.get(), ops.get(), thread, convertable_conversionsession, resourcepackrepository, worldstem, dedicatedserversettings, DataFixers.getDataFixer(), minecraftsessionservice, gameprofilerepository, usercache, LoggerChunkProgressListener::new);
  
 diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@@ -2381,6 +2381,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          }
  
          gameprofilerfiller.pop();
+@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+         return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || !this.updatingChunkMap.isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.queueSorter.hasWork() || this.distanceManager.hasTickets();
      }
  
 -    private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot
@@ -2414,7 +2416,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    } catch (ThreadDeath ex) {
 +                        throw ex; // bye
 +                    } catch (Throwable ex) {
-+                        LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex);
++                        LOGGER.error("Failed to prepare async save, attempting synchronous save", ex);
 +                        this.save(ichunkaccess);
 +                    }
 +                    // Paper end - async chunk saving
@@ -3468,13 +3470,13 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorag
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
 +++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
-@@ -0,0 +0,0 @@ import net.minecraft.world.level.LevelHeightAccessor;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import net.minecraft.world.level.ChunkPos;
+ import net.minecraft.world.level.LevelHeightAccessor;
+ import org.slf4j.Logger;
  
 -public class SectionStorage<R> implements AutoCloseable {
 +public class SectionStorage<R> extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
      private static final String SECTIONS_TAG = "Sections";
 -    private final IOWorker worker;
 +    // Paper - remove mojang I/O thread
diff --git a/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch b/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch
index 4ac363c3c0..36b63e68c9 100644
--- a/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch
+++ b/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch
@@ -13,8 +13,8 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializ
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import net.minecraft.world.ticks.ProtoChunkTicks;
+ import org.slf4j.Logger;
  
  public class ChunkSerializer {
 +    // Paper start
@@ -31,7 +31,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end
  
      public static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codec(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), null); // Paper - Anti-Xray - Add preset block states
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
 @@ -0,0 +0,0 @@ public class ChunkSerializer {
          nbttagcompound.putInt("xPos", chunkcoordintpair.x);
          nbttagcompound.putInt("yPos", chunk.getMinSection());
@@ -178,7 +178,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        }
 +        ChunkPos ourLowerLeftPosition = RegionFileStorage.getRegionFileCoordinates(this.regionFile);
 +        if (ourLowerLeftPosition == null) {
-+            LOGGER.fatal("Unable to get chunk location of regionfile " + this.regionFile.toAbsolutePath() + ", cannot recover header");
++            LOGGER.error("Unable to get chunk location of regionfile " + this.regionFile.toAbsolutePath() + ", cannot recover header");
 +            return false;
 +        }
 +        synchronized (this) {
@@ -433,7 +433,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                this.file.force(true); // try to ensure it goes through...
 +                LOGGER.info("Successfully wrote new header to disk for regionfile " + this.regionFile.toAbsolutePath());
 +            } catch (IOException ex) {
-+                LOGGER.fatal("Failed to write new header to disk for regionfile " + this.regionFile.toAbsolutePath(), ex);
++                LOGGER.error("Failed to write new header to disk for regionfile " + this.regionFile.toAbsolutePath(), ex);
 +            }
 +        }
 +
@@ -444,7 +444,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end
 +
      // Paper start - Cache chunk status
-     private final ChunkStatus[] statuses = new ChunkStatus[32 * 32];
+     private final net.minecraft.world.level.chunk.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.ChunkStatus[32 * 32];
  
 @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
      public RegionFile(Path file, Path directory, boolean dsync) throws IOException {
@@ -495,7 +495,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                        sectorLength = j1; // Paper - diff on change, we expect this to be sector length of region
  
                          if (i1 < 2) {
-                             RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", file, k, i1);
+                             RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", new Object[]{file, k, i1});
 -                            this.offsets.put(k, 0);
 +                            //this.offsets.put(k, 0); // Paper - we catch this, but need it in the header for the summary change
                          } else if (j1 == 0) {
@@ -503,7 +503,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -                            this.offsets.put(k, 0);
 +                            //this.offsets.put(k, 0); // Paper - we catch this, but need it in the header for the summary change
                          } else if ((long) i1 * 4096L > j) {
-                             RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", file, k, i1);
+                             RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", new Object[]{file, k, i1});
 -                            this.offsets.put(k, 0);
 +                            //this.offsets.put(k, 0); // Paper - we catch this, but need it in the header for the summary change
                          } else {
@@ -518,7 +518,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                                break;
 +                            } else {
 +                                // location = chunkX | (chunkZ << 5);
-+                                LOGGER.fatal("Detected invalid header for regionfile " + this.regionFile.toAbsolutePath() +
++                                LOGGER.error("Detected invalid header for regionfile " + this.regionFile.toAbsolutePath() +
 +                                        "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header");
 +                                if (!hasBackedUp) {
 +                                    hasBackedUp = true;
@@ -535,7 +535,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                          }
 +                        if (failedToAllocate & !canRecalcHeader) {
 +                            // location = chunkX | (chunkZ << 5);
-+                            LOGGER.fatal("Detected invalid header for regionfile " + this.regionFile.toAbsolutePath() +
++                            LOGGER.error("Detected invalid header for regionfile " + this.regionFile.toAbsolutePath() +
 +                                    "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header");
 +                            if (!hasBackedUp) {
 +                                hasBackedUp = true;
@@ -599,7 +599,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
              ((java.nio.Buffer) bytebuffer).flip(); // CraftBukkit - decompile error
              if (bytebuffer.remaining() < 5) {
-                 RegionFile.LOGGER.error("Chunk {} header is truncated: expected {} but read {}", pos, l, bytebuffer.remaining());
+                 RegionFile.LOGGER.error("Chunk {} header is truncated: expected {} but read {}", new Object[]{pos, l, bytebuffer.remaining()});
 +                // Paper start - recalculate header on regionfile corruption
 +                if (this.canRecalcHeader && this.recalculateHeader()) {
 +                    return this.getChunkDataInputStream(pos);
@@ -640,7 +640,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                        return ret;
 +                        // Paper end - recalculate header on regionfile corruption
                      } else if (j1 > bytebuffer.remaining()) {
-                         RegionFile.LOGGER.error("Chunk {} stream is truncated: expected {} but read {}", pos, j1, bytebuffer.remaining());
+                         RegionFile.LOGGER.error("Chunk {} stream is truncated: expected {} but read {}", new Object[]{pos, j1, bytebuffer.remaining()});
 +                        // Paper start - recalculate header on regionfile corruption
 +                        if (this.canRecalcHeader && this.recalculateHeader()) {
 +                            return this.getChunkDataInputStream(pos);
diff --git a/patches/server/Avoid-hopper-searches-if-there-are-no-items.patch b/patches/server/Avoid-hopper-searches-if-there-are-no-items.patch
index 5cece0c572..f0ca482434 100644
--- a/patches/server/Avoid-hopper-searches-if-there-are-no-items.patch
+++ b/patches/server/Avoid-hopper-searches-if-there-are-no-items.patch
@@ -31,7 +31,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/entity/EntitySection.java
 +++ b/src/main/java/net/minecraft/world/level/entity/EntitySection.java
 @@ -0,0 +0,0 @@ public class EntitySection<T extends EntityAccess> {
-     protected static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
      private final ClassInstanceMultiMap<T> storage;
      private Visibility chunkStatus;
 +    // Paper start - track number of items and minecarts
diff --git a/patches/server/Bound-Treasure-Maps-to-World-Border.patch b/patches/server/Bound-Treasure-Maps-to-World-Border.patch
index 430e40b282..44d31c9011 100644
--- a/patches/server/Bound-Treasure-Maps-to-World-Border.patch
+++ b/patches/server/Bound-Treasure-Maps-to-World-Border.patch
@@ -33,15 +33,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public boolean isWithinBounds(ChunkPos pos) {
          return (double) pos.getMaxBlockX() > this.getMinX() && (double) pos.getMinBlockX() < this.getMaxX() && (double) pos.getMaxBlockZ() > this.getMinZ() && (double) pos.getMinBlockZ() < this.getMaxZ();
      }
-diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java
+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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java
-+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java
-@@ -0,0 +0,0 @@ public class StructureFeature<C extends FeatureConfiguration> {
-                         int o = j + i * m;
-                         int p = k + i * n;
-                         ChunkPos chunkPos = this.getPotentialFeatureChunk(config, worldSeed, o, p);
-+                        if (!world.getWorldBorder().isChunkInBounds(chunkPos.x, chunkPos.z)) { continue; } // Paper
-                         StructureCheckResult structureCheckResult = structureAccessor.checkStructurePresence(chunkPos, this, skipExistingChunks);
-                         if (structureCheckResult != StructureCheckResult.START_NOT_PRESENT) {
-                             if (!skipExistingChunks && structureCheckResult == StructureCheckResult.START_PRESENT) {
+--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
+@@ -0,0 +0,0 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
+                     int l1 = i + i1 * j1;
+                     int i2 = j + i1 * k1;
+                     ChunkPos chunkcoordintpair = randomspreadstructureplacement.getPotentialFeatureChunk(l, l1, i2);
++                    if (!iworldreader.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper
+                     Iterator iterator = set.iterator();
+ 
+                     while (iterator.hasNext()) {
diff --git a/patches/server/Brand-support.patch b/patches/server/Brand-support.patch
index 690571b08e..1f69f7cb2a 100644
--- a/patches/server/Brand-support.patch
+++ b/patches/server/Brand-support.patch
@@ -8,14 +8,6 @@ diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListener
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-@@ -0,0 +0,0 @@ import com.google.common.collect.Lists;
- import com.google.common.primitives.Floats;
- import com.mojang.brigadier.ParseResults;
- import com.mojang.brigadier.StringReader;
-+import io.netty.buffer.Unpooled;
- import io.netty.util.concurrent.Future;
- import io.netty.util.concurrent.GenericFutureListener;
- import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry;
 @@ -0,0 +0,0 @@ import net.minecraft.nbt.CompoundTag;
  import net.minecraft.nbt.ListTag;
  import net.minecraft.nbt.StringTag;
@@ -49,7 +41,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                // Paper start - Brand support
 +                if (packet.identifier.equals(MINECRAFT_BRAND)) {
 +                    try {
-+                        this.clientBrandName = new FriendlyByteBuf(Unpooled.copiedBuffer(data)).readUtf(256);
++                        this.clientBrandName = new FriendlyByteBuf(io.netty.buffer.Unpooled.copiedBuffer(data)).readUtf(256);
 +                    } catch (StringIndexOutOfBoundsException ex) {
 +                        this.clientBrandName = "illegal";
 +                    }
diff --git a/patches/server/Build-system-changes.patch b/patches/server/Build-system-changes.patch
index 09ada170fb..1dc1041336 100644
--- a/patches/server/Build-system-changes.patch
+++ b/patches/server/Build-system-changes.patch
@@ -12,10 +12,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  dependencies {
      implementation(project(":paper-api"))
      implementation("jline:jline:2.12.1")
--    implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") {
+-    implementation("org.apache.logging.log4j:log4j-iostreams:2.17.0") {
 -        exclude(group = "org.apache.logging.log4j", module = "log4j-api")
 -    }
-+    implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper
++    implementation("org.apache.logging.log4j:log4j-iostreams:2.17.1") // Paper
      implementation("org.ow2.asm:asm:9.2")
 +    implementation("org.ow2.asm:asm-commons:9.2") // Paper - ASM event executor generation
      runtimeOnly("org.xerial:sqlite-jdbc:3.36.0.3")
@@ -50,7 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    Date buildDate = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse(Main.class.getPackage().getImplementationVendor()); // Paper
  
                      Calendar deadline = Calendar.getInstance();
-                     deadline.add(Calendar.DAY_OF_YEAR, -28);
+                     deadline.add(Calendar.DAY_OF_YEAR, -3);
 diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
diff --git a/patches/server/Cache-block-data-strings.patch b/patches/server/Cache-block-data-strings.patch
index b1ec9712b0..839700cc8e 100644
--- a/patches/server/Cache-block-data-strings.patch
+++ b/patches/server/Cache-block-data-strings.patch
@@ -10,8 +10,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
 @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
              this.getPlayerList().reloadResources();
-             this.functionManager.replaceLibrary(this.resources.getFunctionLibrary());
-             this.structureManager.onResourceManagerReload(this.resources.getResourceManager());
+             this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary());
+             this.structureManager.onResourceManagerReload(this.resources.resourceManager);
 +            org.bukkit.craftbukkit.block.data.CraftBlockData.reloadCache(); // Paper - cache block data strings, they can be defined by datapacks so refresh it here
          }, this);
  
diff --git a/patches/server/Call-PaperServerListPingEvent-for-legacy-pings.patch b/patches/server/Call-PaperServerListPingEvent-for-legacy-pings.patch
index b997959630..2ef43ae6c1 100644
--- a/patches/server/Call-PaperServerListPingEvent-for-legacy-pings.patch
+++ b/patches/server/Call-PaperServerListPingEvent-for-legacy-pings.patch
@@ -87,14 +87,6 @@ diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
 +++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
-@@ -0,0 +0,0 @@
- package net.minecraft.server.network;
- 
-+import com.destroystokyo.paper.network.PaperLegacyStatusClient;
-+
- import io.netty.buffer.ByteBuf;
- import io.netty.buffer.Unpooled;
- import io.netty.channel.ChannelFutureListener;
 @@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter {
              MinecraftServer minecraftserver = this.serverConnectionListener.getServer();
              int i = bytebuf.readableBytes();
@@ -108,12 +100,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                      LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort());
 -                    s = String.format("%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit
 +                // Paper start - Call PaperServerListPingEvent and use results
-+                event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 39, null);
++                event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 39, null);
 +                if (event == null) {
 +                    channelhandlercontext.close();
 +                    break;
 +                }
-+                s = String.format("%s\u00a7%d\u00a7%d", PaperLegacyStatusClient.getUnformattedMotd(event), event.getNumPlayers(), event.getMaxPlayers());
++                s = String.format("%s\u00a7%d\u00a7%d", com.destroystokyo.paper.network.PaperLegacyStatusClient.getUnformattedMotd(event), event.getNumPlayers(), event.getMaxPlayers());
                      this.sendFlushAndClose(channelhandlercontext, this.createReply(s));
                      break;
                  case 1:
@@ -123,7 +115,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                      LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort());
 -                    s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit
 +                // Paper start - Call PaperServerListPingEvent and use results
-+                event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 127, null); // Paper
++                event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 127, null); // Paper
 +                if (event == null) {
 +                    channelhandlercontext.close();
 +                    break;
@@ -140,7 +132,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d",
 -                Byte.MAX_VALUE, server.getServerVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers());
 +        InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port);
-+        com.destroystokyo.paper.event.server.PaperServerListPingEvent event = PaperLegacyStatusClient.processRequest(
++        com.destroystokyo.paper.event.server.PaperServerListPingEvent event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest(
 +                server, (InetSocketAddress) ctx.channel().remoteAddress(), protocolVersion, virtualHost);
 +        if (event == null) {
 +            ctx.close();
@@ -148,7 +140,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        }
 +
 +        String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", event.getProtocolVersion(), event.getVersion(),
-+            PaperLegacyStatusClient.getMotd(event), event.getNumPlayers(), event.getMaxPlayers());
++            com.destroystokyo.paper.network.PaperLegacyStatusClient.getMotd(event), event.getNumPlayers(), event.getMaxPlayers());
          this.sendFlushAndClose(ctx, this.createReply(response));
      }
  
diff --git a/patches/server/Configurable-Grass-Spread-Tick-Rate.patch b/patches/server/Configurable-Grass-Spread-Tick-Rate.patch
index df68a362cf..b4c694f0b8 100644
--- a/patches/server/Configurable-Grass-Spread-Tick-Rate.patch
+++ b/patches/server/Configurable-Grass-Spread-Tick-Rate.patch
@@ -30,7 +30,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import net.minecraft.server.MinecraftServer;
  import net.minecraft.server.level.ServerLevel;
  import net.minecraft.tags.FluidTags;
- import net.minecraft.tags.Tag;
+ import net.minecraft.world.level.LevelReader;
 @@ -0,0 +0,0 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
  
      @Override
diff --git a/patches/server/Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/Configurable-Keep-Spawn-Loaded-range-per-world.patch
index e5f6873116..5fa7f791e2 100644
--- a/patches/server/Configurable-Keep-Spawn-Loaded-range-per-world.patch
+++ b/patches/server/Configurable-Keep-Spawn-Loaded-range-per-world.patch
@@ -199,12 +199,12 @@ diff --git a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgre
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java
 +++ b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import org.slf4j.Logger;
  
  public class LoggerChunkProgressListener implements ChunkProgressListener {
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
 -    private final int maxCount;
-+    private int maxCount; // Paper - remove final
++    private int maxCount;// Paper - remove final
      private int count;
      private long startTime;
      private long nextTickTime = Long.MAX_VALUE;
diff --git a/patches/server/Configurable-Player-Collision.patch b/patches/server/Configurable-Player-Collision.patch
index 7353e8aa14..589c003ad8 100644
--- a/patches/server/Configurable-Player-Collision.patch
+++ b/patches/server/Configurable-Player-Collision.patch
@@ -41,8 +41,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  import net.minecraft.world.phys.Vec3;
 +import net.minecraft.world.scores.PlayerTeam; // Paper
  import org.apache.commons.lang3.Validate;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+ import org.slf4j.Logger;
+ 
 @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
              this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(worldserver.getWorld()));
          }
@@ -74,15 +74,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  import net.minecraft.world.scores.PlayerTeam;
 +import net.minecraft.world.scores.Scoreboard; // Paper
  import net.minecraft.world.scores.Team;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+ import org.slf4j.Logger;
+ 
 @@ -0,0 +0,0 @@ public abstract class PlayerList {
      // CraftBukkit start
      private CraftServer cserver;
      private final Map<String,ServerPlayer> playersByName = new java.util.HashMap<>();
 +    public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule
  
-     public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) {
+     public PlayerList(MinecraftServer server, RegistryAccess.Frozen registryManager, PlayerDataStorage saveHandler, int maxPlayers) {
          this.cserver = server.server = new CraftServer((DedicatedServer) server, this);
 @@ -0,0 +0,0 @@ public abstract class PlayerList {
  
diff --git a/patches/server/Configurable-RCON-IP-address.patch b/patches/server/Configurable-RCON-IP-address.patch
index dced46e09f..305b9c7cbf 100644
--- a/patches/server/Configurable-RCON-IP-address.patch
+++ b/patches/server/Configurable-RCON-IP-address.patch
@@ -19,9 +19,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public DedicatedServerProperties(Properties properties, OptionSet optionset) {
          super(properties, optionset);
 @@ -0,0 +0,0 @@ public class DedicatedServerProperties extends Settings<DedicatedServerPropertie
-         this.textFilteringConfig = this.get("text-filtering-config", "");
-         this.playerIdleTimeout = this.getMutable("player-idle-timeout", 0);
-         this.whiteList = this.getMutable("white-list", false);
+         }, new JsonObject()), this.get("generate-structures", true), (String) this.get("level-type", (s) -> {
+             return s.toLowerCase(Locale.ROOT);
+         }, "default"));
 +        // Paper start - Configurable rcon ip
 +        final String rconIp = this.getStringRaw("rcon.ip");
 +        this.rconIp = rconIp == null ? this.serverIp : rconIp;
diff --git a/patches/server/Configurable-feature-seeds.patch b/patches/server/Configurable-feature-seeds.patch
index 610fd655f7..37566cb518 100644
--- a/patches/server/Configurable-feature-seeds.patch
+++ b/patches/server/Configurable-feature-seeds.patch
@@ -86,11 +86,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              int j = list.size();
  
              try {
--                Registry<PlacedFeature> iregistry = generatoraccessseed.registryAccess().registryOrThrow(Registry.PLACED_FEATURE_REGISTRY);
-+                Registry<PlacedFeature> iregistry = generatoraccessseed.registryAccess().registryOrThrow(Registry.PLACED_FEATURE_REGISTRY); // Paper - diff on change
-                 Registry<StructureFeature<?>> iregistry1 = generatoraccessseed.registryAccess().registryOrThrow(Registry.STRUCTURE_FEATURE_REGISTRY);
+-                Registry<PlacedFeature> iregistry1 = generatoraccessseed.registryAccess().registryOrThrow(Registry.PLACED_FEATURE_REGISTRY);
++                Registry<PlacedFeature> iregistry1 = generatoraccessseed.registryAccess().registryOrThrow(Registry.PLACED_FEATURE_REGISTRY); // Paper - diff on change
                  int k = Math.max(GenerationStep.Decoration.values().length, j);
  
+                 for (int l = 0; l < k; ++l) {
 @@ -0,0 +0,0 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
                                  return (String) optional.orElseGet(placedfeature::toString);
                              };
@@ -98,7 +98,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -                            seededrandom.setFeatureSeed(i, l1, l);
 +                            // Paper start - change populationSeed used in random
 +                            long featurePopulationSeed = i;
-+                            final net.minecraft.resources.ResourceLocation location = iregistry.getKey(placedfeature);
++                            final net.minecraft.resources.ResourceLocation location = iregistry1.getKey(placedfeature);
 +                            final long configFeatureSeed = generatoraccessseed.getMinecraftWorld().paperConfig.featureSeeds.getLong(location);
 +                            if (configFeatureSeed != -1) {
 +                                featurePopulationSeed = seededrandom.setDecorationSeed(configFeatureSeed, blockposition.getX(), blockposition.getZ()); // See seededrandom.setDecorationSeed from above
diff --git a/patches/server/Configurable-flying-kick-messages.patch b/patches/server/Configurable-flying-kick-messages.patch
index 1f514b8a6b..9cfcec2944 100644
--- a/patches/server/Configurable-flying-kick-messages.patch
+++ b/patches/server/Configurable-flying-kick-messages.patch
@@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
-         if (this.clientIsFloating && !this.player.isSleeping()) {
+         if (this.clientIsFloating && !this.player.isSleeping() && !this.player.isPassenger()) {
              if (++this.aboveGroundTickCount > 80) {
                  ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString());
 -                this.disconnect(new TranslatableComponent("multiplayer.disconnect.flying"));
diff --git a/patches/server/Custom-Potion-Mixes.patch b/patches/server/Custom-Potion-Mixes.patch
index 8ad590181a..291bcf5c8d 100644
--- a/patches/server/Custom-Potion-Mixes.patch
+++ b/patches/server/Custom-Potion-Mixes.patch
@@ -28,13 +28,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/MinecraftServer.java
 +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
 @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
-             this.packRepository.setSelected(datapacks);
+             this.packRepository.setSelected(dataPacks);
              this.worldData.setDataPackConfig(MinecraftServer.getSelectedPacks(this.packRepository));
-             datapackresources.updateGlobals();
+             this.resources.managers.updateRegistryTags(this.registryAccess());
 +            net.minecraft.world.item.alchemy.PotionBrewing.reload(); // Paper
              new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper
              if (Thread.currentThread() != this.serverThread) return; // Paper
-             //this.getPlayerList().savePlayers(); // Paper - we don't need to do this
+             //this.getPlayerList().saveAll(); // Paper - we don't need to do this
 diff --git a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java b/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
diff --git a/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch b/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch
index 2e0a552b01..59b13d858f 100644
--- a/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch
+++ b/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch
@@ -34,7 +34,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      implementation("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - implementation
 +    annotationProcessor("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - Needed to generate meta for our Log4j plugins
      // Paper end
-     implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper
+     implementation("org.apache.logging.log4j:log4j-iostreams:2.17.1") // Paper
      implementation("org.ow2.asm:asm:9.2")
 @@ -0,0 +0,0 @@ dependencies {
      runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.2")
@@ -534,7 +534,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/network/Connection.java
 +++ b/src/main/java/net/minecraft/network/Connection.java
 @@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
-     public static final Marker PACKET_MARKER = MarkerManager.getMarker("NETWORK_PACKETS", Connection.ROOT_MARKER);
+     });
      public static final AttributeKey<ConnectionProtocol> ATTRIBUTE_PROTOCOL = AttributeKey.valueOf("protocol");
      public static final LazyLoadedValue<NioEventLoopGroup> NETWORK_WORKER_GROUP = new LazyLoadedValue<>(() -> {
 -        return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Client IO #%d").setDaemon(true).build());
@@ -581,7 +581,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
 @@ -0,0 +0,0 @@ public class ServerConnectionListener {
  
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
      public static final LazyLoadedValue<NioEventLoopGroup> SERVER_EVENT_GROUP = new LazyLoadedValue<>(() -> {
 -        return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Server IO #%d").setDaemon(true).build());
 +        return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Server IO #%d").setDaemon(true).setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(LOGGER)).build()); // Paper
diff --git a/patches/server/Detail-more-information-in-watchdog-dumps.patch b/patches/server/Detail-more-information-in-watchdog-dumps.patch
index 441e010e98..d9445888eb 100644
--- a/patches/server/Detail-more-information-in-watchdog-dumps.patch
+++ b/patches/server/Detail-more-information-in-watchdog-dumps.patch
@@ -31,7 +31,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
 @@ -0,0 +0,0 @@ public class PacketUtils {
  
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
  
 +    // Paper start - detailed watchdog information
 +    public static final java.util.concurrent.ConcurrentLinkedDeque<PacketListener> packetProcessing = new java.util.concurrent.ConcurrentLinkedDeque<>();
@@ -55,14 +55,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, ServerLevel world) throws RunningOnDifferentThreadException {
 @@ -0,0 +0,0 @@ public class PacketUtils {
+     public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, BlockableEventLoop<?> engine) throws RunningOnDifferentThreadException {
          if (!engine.isSameThread()) {
-             Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings
-             engine.execute(() -> {
+             engine.executeIfPossible(() -> {
 +                packetProcessing.push(listener); // Paper - detailed watchdog information
 +                try { // Paper - detailed watchdog information
                  if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerGamePacketListenerImpl && ((ServerGamePacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590
                  if (listener.getConnection().isConnected()) {
-                     try (Timing ignored = timing.startTiming()) { // Paper - timings
+                     co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings
 @@ -0,0 +0,0 @@ public class PacketUtils {
                  } else {
                      PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet);
diff --git a/patches/server/Disable-ice-and-snow.patch b/patches/server/Disable-ice-and-snow.patch
index 7ce5dc1786..9e4b78ca85 100644
--- a/patches/server/Disable-ice-and-snow.patch
+++ b/patches/server/Disable-ice-and-snow.patch
@@ -30,4 +30,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow
              blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.getBlockRandomPos(j, 0, k, 15));
              BlockPos blockposition1 = blockposition.below();
-             Biome biomebase = this.getBiome(blockposition);
+             Biome biomebase = (Biome) this.getBiome(blockposition).value();
diff --git a/patches/server/Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/Do-not-allow-bees-to-load-chunks-for-beehives.patch
index 4123b6d1e3..fbaa55bfb0 100644
--- a/patches/server/Do-not-allow-bees-to-load-chunks-for-beehives.patch
+++ b/patches/server/Do-not-allow-bees-to-load-chunks-for-beehives.patch
@@ -27,7 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
          @Override
          public boolean canBeeUse() {
-             if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerThan((Position) Bee.this.position(), 2.0D)) {
+             if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerToCenterThan(Bee.this.position(), 2.0D)) {
 +                if (!Bee.this.level.isLoadedAndInBounds(Bee.this.hivePos)) return false; // Paper
                  BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos);
  
diff --git a/patches/server/Do-not-allow-ticket-level-changes-while-unloading-pl.patch b/patches/server/Do-not-allow-ticket-level-changes-while-unloading-pl.patch
index e181843062..11cae988fa 100644
--- a/patches/server/Do-not-allow-ticket-level-changes-while-unloading-pl.patch
+++ b/patches/server/Do-not-allow-ticket-level-changes-while-unloading-pl.patch
@@ -41,9 +41,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  boolean removed;
                  if ((removed = this.pendingUnloads.remove(pos, holder)) && ichunkaccess != null) {
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
-                         this.regionManagers.get(index).removeChunk(holder.pos.x, holder.pos.z);
-                     }
-                 } // Paper end
+                     this.regionManagers.get(index).removeChunk(holder.pos.x, holder.pos.z);
+                 }
+             } // Paper end
 +                } finally { this.unloadingPlayerChunk = unloadingBefore; } // Paper - do not allow ticket level changes while unloading chunks
  
              }
diff --git a/patches/server/Do-not-submit-profile-lookups-to-worldgen-threads.patch b/patches/server/Do-not-submit-profile-lookups-to-worldgen-threads.patch
index 6430e16d2d..fe95fc929c 100644
--- a/patches/server/Do-not-submit-profile-lookups-to-worldgen-threads.patch
+++ b/patches/server/Do-not-submit-profile-lookups-to-worldgen-threads.patch
@@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread
      private static final ExecutorService IO_POOL = makeIoExecutor();
      public static LongSupplier timeSource = System::nanoTime;
-     public static final UUID NIL_UUID = new UUID(0L, 0L);
+     public static final Ticker TICKER = new Ticker() {
 diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
diff --git a/patches/server/Don-t-allow-digging-into-unloaded-chunks.patch b/patches/server/Don-t-allow-digging-into-unloaded-chunks.patch
index b7eacd8cfd..efb1faba94 100644
--- a/patches/server/Don-t-allow-digging-into-unloaded-chunks.patch
+++ b/patches/server/Don-t-allow-digging-into-unloaded-chunks.patch
@@ -39,9 +39,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
          if (d3 > 36.0D) {
 +            if (true) return; // Paper - Don't notify if unreasonably far away
-             this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, false, "too far"));
-         } else if (pos.getY() >= worldHeight) {
-             this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, false, "too high"));
+             BlockState iblockdata;
+ 
+             if (this.player.level.getServer() != null && this.player.chunkPosition().getChessboardDistance(new ChunkPos(pos)) < this.player.level.getServer().getPlayerList().getViewDistance()) {
 @@ -0,0 +0,0 @@ public class ServerPlayerGameMode {
                  this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "stopped destroying"));
              } else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) {
diff --git a/patches/server/Drop-falling-block-and-tnt-entities-at-the-specified.patch b/patches/server/Drop-falling-block-and-tnt-entities-at-the-specified.patch
index 927d2f5c6c..f0126547fb 100644
--- a/patches/server/Drop-falling-block-and-tnt-entities-at-the-specified.patch
+++ b/patches/server/Drop-falling-block-and-tnt-entities-at-the-specified.patch
@@ -44,7 +44,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            }
 +            // Paper end
              if (!this.level.isClientSide) {
-                 blockposition = this.blockPosition();
+                 BlockPos blockposition = this.blockPosition();
                  boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock;
 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
diff --git a/patches/server/Entity-Activation-Range-2.0.patch b/patches/server/Entity-Activation-Range-2.0.patch
index f9c6d933f6..98fb657011 100644
--- a/patches/server/Entity-Activation-Range-2.0.patch
+++ b/patches/server/Entity-Activation-Range-2.0.patch
@@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -import co.aikar.timings.Timings; // Paper
  import com.google.common.collect.Lists;
  import com.mojang.datafixers.DataFixer;
- import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+ import com.mojang.datafixers.util.Pair;
 @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
          ++TimingHistory.entityTicks; // Paper - timings
          // Spigot start
diff --git a/patches/server/Entity-load-save-limit-per-chunk.patch b/patches/server/Entity-load-save-limit-per-chunk.patch
index b670133c64..cb1873520b 100644
--- a/patches/server/Entity-load-save-limit-per-chunk.patch
+++ b/patches/server/Entity-load-save-limit-per-chunk.patch
@@ -65,7 +65,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/entity/EntityType.java
 +++ b/src/main/java/net/minecraft/world/entity/EntityType.java
 @@ -0,0 +0,0 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T> {
-         final Spliterator<? extends net.minecraft.nbt.Tag> spliterator = entityNbtList.spliterator();
+         final Spliterator<? extends Tag> spliterator = entityNbtList.spliterator();
  
          return StreamSupport.stream(new Spliterator<Entity>() {
 +            final java.util.Map<EntityType<?>, Integer> loadedEntityCounts = new java.util.HashMap<>(); // Paper
diff --git a/patches/server/Execute-chunk-tasks-mid-tick.patch b/patches/server/Execute-chunk-tasks-mid-tick.patch
index 8f95ce8169..8a15d93c55 100644
--- a/patches/server/Execute-chunk-tasks-mid-tick.patch
+++ b/patches/server/Execute-chunk-tasks-mid-tick.patch
@@ -23,9 +23,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/MinecraftServer.java
 +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
 @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
-         return s0;
-     }
  
+     private boolean pollTaskInternal() {
+         if (super.pollTask()) {
++            this.executeMidTickTasks(); // Paper - execute chunk tasks mid tick
+             return true;
+         } else {
+             if (this.haveTime()) {
+@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+         }
+     }
+     // Paper end
++
 +    // Paper start - execute chunk tasks mid tick
 +    static final long CHUNK_TASK_QUEUE_BACKOFF_MIN_TIME = 25L * 1000L; // 25us
 +    static final long MAX_CHUNK_EXEC_TIME = 1000L; // 1us
@@ -95,18 +104,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        }
 +    }
 +    // Paper end - execute chunk tasks mid tick
-+
-     public MinecraftServer(OptionSet options, DataPackConfig datapackconfiguration, Thread thread, RegistryAccess.RegistryHolder iregistrycustom_dimension, LevelStorageSource.LevelStorageAccess convertable_conversionsession, WorldData savedata, PackRepository resourcepackrepository, Proxy proxy, DataFixer datafixer, ServerResources datapackresources, @Nullable MinecraftSessionService minecraftsessionservice, @Nullable GameProfileRepository gameprofilerepository, @Nullable GameProfileCache usercache, ChunkProgressListenerFactory worldloadlistenerfactory) {
-         super("Server");
-         SERVER = this; // Paper - better singleton
-@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
- 
-     private boolean pollTaskInternal() {
-         if (super.pollTask()) {
-+            this.executeMidTickTasks(); // Paper - execute chunk tasks mid tick
-             return true;
-         } else {
-             if (this.haveTime()) {
+ }
 diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
diff --git a/patches/server/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch
index 9327621721..99383b8861 100644
--- a/patches/server/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch
+++ b/patches/server/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch
@@ -241,7 +241,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                        entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper
                      }
                      // CraftBukkit end
-                     if (itemstack1.is((Tag) ItemTags.FISHES)) {
+                     if (itemstack1.is(ItemTags.FISHES)) {
 diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java
diff --git a/patches/server/Expose-vanilla-BiomeProvider-from-WorldInfo.patch b/patches/server/Expose-vanilla-BiomeProvider-from-WorldInfo.patch
index cc2a46e6a9..84e39932dd 100644
--- a/patches/server/Expose-vanilla-BiomeProvider-from-WorldInfo.patch
+++ b/patches/server/Expose-vanilla-BiomeProvider-from-WorldInfo.patch
@@ -12,8 +12,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  chunkgenerator = worlddimension.generator();
              }
  
--            org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), dimensionmanager);
-+            org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), dimensionmanager, chunkgenerator, this.registryAccess().registryOrThrow(net.minecraft.core.Registry.BIOME_REGISTRY)); // Paper
+-            org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), holder.value());
++            org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), holder.value(), chunkgenerator, this.registryAccess().registryOrThrow(net.minecraft.core.Registry.BIOME_REGISTRY)); // Paper
              if (biomeProvider == null && gen != null) {
                  biomeProvider = gen.getDefaultBiomeProvider(worldInfo);
              }
@@ -25,8 +25,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              chunkgenerator = worlddimension.generator();
          }
  
--        WorldInfo worldInfo = new CraftWorldInfo(worlddata, worldSession, creator.environment(), dimensionmanager);
-+        WorldInfo worldInfo = new CraftWorldInfo(worlddata, worldSession, creator.environment(), dimensionmanager, chunkgenerator, this.getHandle().getServer().registryAccess().registryOrThrow(net.minecraft.core.Registry.BIOME_REGISTRY)); // Paper
+-        WorldInfo worldInfo = new CraftWorldInfo(worlddata, worldSession, creator.environment(), holder.value());
++        WorldInfo worldInfo = new CraftWorldInfo(worlddata, worldSession, creator.environment(), holder.value(), chunkgenerator, this.getHandle().getServer().registryAccess().registryOrThrow(net.minecraft.core.Registry.BIOME_REGISTRY)); // Paper
          if (biomeProvider == null && generator != null) {
              biomeProvider = generator.getDefaultBiomeProvider(worldInfo);
          }
diff --git a/patches/server/Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server/Fix-Chunk-Post-Processing-deadlock-risk.patch
index 71cb9cb2c5..c1bff5e2d9 100644
--- a/patches/server/Fix-Chunk-Post-Processing-deadlock-risk.patch
+++ b/patches/server/Fix-Chunk-Post-Processing-deadlock-risk.patch
@@ -37,14 +37,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets<ServerPlayer> pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>();
  
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
-                 return Either.left(chunk);
+                 return chunk;
              });
          }, (runnable) -> {
 -            this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable));
 +            this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, () -> ChunkMap.this.chunkLoadConversionCallbackExecutor.execute(runnable))); // Paper - delay running Chunk post processing until outside of the sorter to prevent a deadlock scenario when post processing causes another chunk request.
          });
+     }
  
-         completablefuture1.thenAcceptAsync((either) -> {
 diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
diff --git a/patches/server/Fix-ChunkSnapshot-isSectionEmpty-int-and-optimize-Pa.patch b/patches/server/Fix-ChunkSnapshot-isSectionEmpty-int-and-optimize-Pa.patch
index 64a2ed1e56..341009953d 100644
--- a/patches/server/Fix-ChunkSnapshot-isSectionEmpty-int-and-optimize-Pa.patch
+++ b/patches/server/Fix-ChunkSnapshot-isSectionEmpty-int-and-optimize-Pa.patch
@@ -11,10 +11,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
 @@ -0,0 +0,0 @@ public class CraftChunk implements Chunk {
          boolean[] sectionEmpty = new boolean[cs.length];
-         PalettedContainer<Biome>[] biome = (includeBiome || includeBiomeTempRain) ? new PalettedContainer[cs.length] : null;
+         PalettedContainer<Holder<Biome>>[] biome = (includeBiome || includeBiomeTempRain) ? new PalettedContainer[cs.length] : null;
  
--        Registry<Biome> iregistry = this.worldServer.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
--        Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(iregistry, iregistry.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS), null); // Paper - Anti-Xray - Add preset biomes
++<<<<<<< HEAD
+         Registry<Biome> iregistry = this.worldServer.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
+ <<<<<<< HEAD
+         Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getHolderOrThrow(Biomes.PLAINS));
+ =======
+         Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(iregistry, iregistry.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS), null); // Paper - Anti-Xray - Add preset biomes
+ >>>>>>> Anti-Xray
++=======
++>>>>>>> Fix ChunkSnapshot#isSectionEmpty(int) and optimize PalettedContainer copying by not using codecs
  
          for (int i = 0; i < cs.length; i++) {
 -            CompoundTag data = new CompoundTag();
diff --git a/patches/server/Fix-Not-a-string-Map-Conversion-spam.patch b/patches/server/Fix-Not-a-string-Map-Conversion-spam.patch
index dddea1b07f..04e422aaf4 100644
--- a/patches/server/Fix-Not-a-string-Map-Conversion-spam.patch
+++ b/patches/server/Fix-Not-a-string-Map-Conversion-spam.patch
@@ -28,7 +28,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      public static MapItemSavedData load(CompoundTag nbt) {
--        DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbt.get("dimension")));
+-        DataResult<ResourceKey<Level>> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbt.get("dimension"))); // CraftBukkit - decompile error
 +        // Paper start - fix "Not a string" spam
 +        Tag dimension = nbt.get("dimension");
 +        if (dimension instanceof NumericTag && ((NumericTag) dimension).getAsInt() >= CraftWorld.CUSTOM_DIMENSION_OFFSET) {
diff --git a/patches/server/Fix-Old-Sign-Conversion.patch b/patches/server/Fix-Old-Sign-Conversion.patch
index 8470853e5f..5249919d30 100644
--- a/patches/server/Fix-Old-Sign-Conversion.patch
+++ b/patches/server/Fix-Old-Sign-Conversion.patch
@@ -13,13 +13,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
 +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
 @@ -0,0 +0,0 @@ public abstract class BlockEntity implements io.papermc.paper.util.KeyedObject {
+     private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
      public CraftPersistentDataContainer persistentDataContainer;
      // CraftBukkit end
-     private static final Logger LOGGER = LogManager.getLogger();
 +    public boolean isLoadingStructure = false; // Paper
+     private static final Logger LOGGER = LogUtils.getLogger();
      private final BlockEntityType<?> type;
      @Nullable
-     protected Level level;
 diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
diff --git a/patches/server/Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/patches/server/Fix-Per-World-Difficulty-Remembering-Difficulty.patch
index 7413d1c777..c1976d7317 100644
--- a/patches/server/Fix-Per-World-Difficulty-Remembering-Difficulty.patch
+++ b/patches/server/Fix-Per-World-Difficulty-Remembering-Difficulty.patch
@@ -54,17 +54,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/commands/DifficultyCommand.java
 +++ b/src/main/java/net/minecraft/server/commands/DifficultyCommand.java
 @@ -0,0 +0,0 @@ public class DifficultyCommand {
- 
-     public static int setDifficulty(CommandSourceStack source, Difficulty difficulty) throws CommandSyntaxException {
-         MinecraftServer minecraftServer = source.getServer();
--        if (minecraftServer.getWorldData().getDifficulty() == difficulty) {
-+        net.minecraft.server.level.ServerLevel level = source.getLevel(); // Paper
-+        if (level.serverLevelData.getDifficulty() == difficulty) { // Paper
-             throw ERROR_ALREADY_DIFFICULT.create(difficulty.getKey());
+         if (worldServer.getDifficulty() == difficulty) { // CraftBukkit
+             throw DifficultyCommand.ERROR_ALREADY_DIFFICULT.create(difficulty.getKey());
          } else {
--            minecraftServer.setDifficulty(difficulty, true);
-+            minecraftServer.setDifficulty(level, difficulty, true); // Paper - use world
-             source.sendSuccess(new TranslatableComponent("commands.difficulty.success", difficulty.getDisplayName()), true);
+-            worldServer.serverLevelData.setDifficulty(difficulty); // CraftBukkit
++            minecraftserver.setDifficulty(worldServer, difficulty, true); // Paper - don't skip other difficulty-changing logic (fix upstream's fix)
+             source.sendSuccess(new TranslatableComponent("commands.difficulty.success", new Object[]{difficulty.getDisplayName()}), true);
              return 0;
          }
 diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -87,9 +82,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
                  this.isChangingDimension = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds
  
-                 this.connection.send(new ClientboundRespawnPacket(worldserver.dimensionType(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), true));
+                 this.connection.send(new ClientboundRespawnPacket(worldserver.dimensionTypeRegistration(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), true));
 -                this.connection.send(new ClientboundChangeDifficultyPacket(this.level.getDifficulty(), this.level.getLevelData().isDifficultyLocked()));
-+                this.connection.send(new ClientboundChangeDifficultyPacket(worldserver.getDifficulty(), worldserver.getLevelData().isDifficultyLocked())); // Paper - fix difficulty sync issue
++                this.connection.send(new ClientboundChangeDifficultyPacket(worldserver.getDifficulty(), this.level.getLevelData().isDifficultyLocked())); // Paper - fix difficulty sync issue
                  PlayerList playerlist = this.server.getPlayerList();
  
                  playerlist.sendPlayerPermissionLevel(this);
diff --git a/patches/server/Fix-World-isChunkGenerated-calls.patch b/patches/server/Fix-World-isChunkGenerated-calls.patch
index 1e52306f13..2652a53271 100644
--- a/patches/server/Fix-World-isChunkGenerated-calls.patch
+++ b/patches/server/Fix-World-isChunkGenerated-calls.patch
@@ -128,25 +128,17 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.ja
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
 +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
-@@ -0,0 +0,0 @@ import net.minecraft.Util;
- import net.minecraft.nbt.CompoundTag;
- import net.minecraft.nbt.NbtIo;
- import net.minecraft.world.level.ChunkPos;
-+import net.minecraft.world.level.chunk.ChunkStatus;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
- 
 @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
      public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper
      public final Path regionFile; // Paper
  
 +    // Paper start - Cache chunk status
-+    private final ChunkStatus[] statuses = new ChunkStatus[32 * 32];
++    private final net.minecraft.world.level.chunk.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.ChunkStatus[32 * 32];
 +
 +    private boolean closed;
 +
 +    // invoked on write/read
-+    public void setStatus(int x, int z, ChunkStatus status) {
++    public void setStatus(int x, int z, net.minecraft.world.level.chunk.ChunkStatus status) {
 +        if (this.closed) {
 +            // We've used an invalid region file.
 +            throw new IllegalStateException("RegionFile is closed");
@@ -154,7 +146,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        this.statuses[getChunkLocation(x, z)] = status;
 +    }
 +
-+    public ChunkStatus getStatusIfCached(int x, int z) {
++    public net.minecraft.world.level.chunk.ChunkStatus getStatusIfCached(int x, int z) {
 +        if (this.closed) {
 +            // We've used an invalid region file.
 +            throw new IllegalStateException("RegionFile is closed");
diff --git a/patches/server/Fix-WorldGenRegion-leak-when-converting-pre-1.18-chu.patch b/patches/server/Fix-WorldGenRegion-leak-when-converting-pre-1.18-chu.patch
deleted file mode 100644
index 1908e8f6e1..0000000000
--- a/patches/server/Fix-WorldGenRegion-leak-when-converting-pre-1.18-chu.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
-Date: Sun, 12 Dec 2021 04:43:30 -0800
-Subject: [PATCH] Fix WorldGenRegion leak when converting pre-1.18 chunks
-
-The Blender passed in here holds a WorldGenRegion which contains a list of surrounding chunks
-
-diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
-+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
-@@ -0,0 +0,0 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
-     }
- 
-     public NoiseChunk getOrCreateNoiseChunk(NoiseSampler noiseColumnSampler, Supplier<NoiseChunk.NoiseFiller> columnSampler, NoiseGeneratorSettings chunkGeneratorSettings, Aquifer.FluidPicker fluidLevelSampler, Blender blender) {
-+        // Paper start - create a new one each time to avoid leaking
-+        if (blender != Blender.empty()) {
-+            return NoiseChunk.forChunk(this, noiseColumnSampler, columnSampler, chunkGeneratorSettings, fluidLevelSampler, blender);
-+        }
-+        // Paper end
-         if (this.noiseChunk == null) {
-             this.noiseChunk = NoiseChunk.forChunk(this, noiseColumnSampler, columnSampler, chunkGeneratorSettings, fluidLevelSampler, blender);
-         }
diff --git a/patches/server/Fix-and-optimise-world-force-upgrading.patch b/patches/server/Fix-and-optimise-world-force-upgrading.patch
index a7ddac1179..29f9fcdeeb 100644
--- a/patches/server/Fix-and-optimise-world-force-upgrading.patch
+++ b/patches/server/Fix-and-optimise-world-force-upgrading.patch
@@ -249,9 +249,9 @@ diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/mi
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/Main.java
 +++ b/src/main/java/net/minecraft/server/Main.java
-@@ -0,0 +0,0 @@ import java.nio.file.Paths;
+@@ -0,0 +0,0 @@ import java.nio.file.Path;
+ import java.nio.file.Paths;
  import java.util.Optional;
- import java.util.concurrent.CompletableFuture;
  import java.util.function.BooleanSupplier;
 +import io.papermc.paper.world.ThreadedWorldUpgrader;
  import joptsimple.NonOptionArgumentSpec;
diff --git a/patches/server/Fix-chunks-refusing-to-unload-at-low-TPS.patch b/patches/server/Fix-chunks-refusing-to-unload-at-low-TPS.patch
index 7a2e85f2a8..506d0979ea 100644
--- a/patches/server/Fix-chunks-refusing-to-unload-at-low-TPS.patch
+++ b/patches/server/Fix-chunks-refusing-to-unload-at-low-TPS.patch
@@ -18,7 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  return chunk;
              });
 -        }, (runnable) -> {
--            this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable));
+-            this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, () -> ChunkMap.this.chunkLoadConversionCallbackExecutor.execute(runnable))); // Paper - delay running Chunk post processing until outside of the sorter to prevent a deadlock scenario when post processing causes another chunk request.
 -        });
 +        }, this.mainThreadExecutor); // Paper - queue to execute immediately so this doesn't delay chunk unloading
      }
diff --git a/patches/server/Fix-entity-type-tags-suggestions-in-selectors.patch b/patches/server/Fix-entity-type-tags-suggestions-in-selectors.patch
deleted file mode 100644
index 06f354ad9b..0000000000
--- a/patches/server/Fix-entity-type-tags-suggestions-in-selectors.patch
+++ /dev/null
@@ -1,160 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Jake Potrebic <jake.m.potrebic@gmail.com>
-Date: Sun, 22 Aug 2021 15:21:57 -0700
-Subject: [PATCH] Fix entity type tags suggestions in selectors
-
-This would really be better as a client fix because just to fix it
-all EntityArguments have been told to ask the server for completions
-when if this was fixed on the client, that wouldn't be needed.
-
-Mojira Issue: https://bugs.mojang.com/browse/MC-235045
-
-diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
-+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
-@@ -0,0 +0,0 @@ public class PaperConfig {
-         itemValidationBookPageLength = getInt("settings.item-validation.book.page", itemValidationBookPageLength);
-     }
- 
-+    public static boolean fixTargetSelectorTagCompletion = true;
-+    private static void fixTargetSelectorTagCompletion() {
-+        fixTargetSelectorTagCompletion = getBoolean("settings.fix-target-selector-tag-completion", fixTargetSelectorTagCompletion);
-+    }
-+
-     public static final class PacketLimit {
-         public final double packetLimitInterval;
-         public final double maxPacketRate;
-diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/commands/CommandSourceStack.java
-+++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java
-@@ -0,0 +0,0 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy
-         return this.source.getBukkitSender(this);
-     }
-     // CraftBukkit end
-+    // Paper start - override getSelectedEntities
-+    @Override
-+    public Collection<String> getSelectedEntities() {
-+        if (com.destroystokyo.paper.PaperConfig.fixTargetSelectorTagCompletion && this.source instanceof ServerPlayer player) {
-+            double pickDistance = player.gameMode.getGameModeForPlayer().isCreative() ? 5.0F : 4.5F;
-+            Vec3 min = player.getEyePosition(1.0F);
-+            Vec3 viewVector = player.getViewVector(1.0F);
-+            Vec3 max = min.add(viewVector.x * pickDistance, viewVector.y * pickDistance, viewVector.z * pickDistance);
-+            net.minecraft.world.phys.AABB aabb = player.getBoundingBox().expandTowards(viewVector.scale(pickDistance)).inflate(1.0D, 1.0D, 1.0D);
-+            pickDistance = player.gameMode.getGameModeForPlayer().isCreative() ? 6.0F : pickDistance;
-+            net.minecraft.world.phys.EntityHitResult hitResult = net.minecraft.world.entity.projectile.ProjectileUtil.getEntityHitResult(player, min, max, aabb, (e) -> !e.isSpectator() && e.isPickable(), pickDistance);
-+            return hitResult != null ? java.util.Collections.singletonList(hitResult.getEntity().getStringUUID()) : SharedSuggestionProvider.super.getSelectedEntities();
-+        }
-+        return SharedSuggestionProvider.super.getSelectedEntities();
-+    }
-+    // Paper end
- }
-diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/commands/Commands.java
-+++ b/src/main/java/net/minecraft/commands/Commands.java
-@@ -0,0 +0,0 @@ public class Commands {
-     private void fillUsableCommands(CommandNode<CommandSourceStack> tree, CommandNode<SharedSuggestionProvider> result, CommandSourceStack source, Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> resultNodes) {
-         Iterator iterator = tree.getChildren().iterator();
- 
-+        boolean registeredAskServerSuggestionsForTree = false; // Paper - tell clients to ask server for suggestions for EntityArguments
-         while (iterator.hasNext()) {
-             CommandNode<CommandSourceStack> commandnode2 = (CommandNode) iterator.next();
-             if ( !org.spigotmc.SpigotConfig.sendNamespaced && commandnode2.getName().contains( ":" ) ) continue; // Spigot
-@@ -0,0 +0,0 @@ public class Commands {
- 
-                     if (requiredargumentbuilder.getSuggestionsProvider() != null) {
-                         requiredargumentbuilder.suggests(SuggestionProviders.safelySwap(requiredargumentbuilder.getSuggestionsProvider()));
-+                        // Paper start - tell clients to ask server for suggestions for EntityArguments
-+                        registeredAskServerSuggestionsForTree = requiredargumentbuilder.getSuggestionsProvider() == net.minecraft.commands.synchronization.SuggestionProviders.ASK_SERVER;
-+                    } else if (com.destroystokyo.paper.PaperConfig.fixTargetSelectorTagCompletion && !registeredAskServerSuggestionsForTree && requiredargumentbuilder.getType() instanceof net.minecraft.commands.arguments.EntityArgument) {
-+                        requiredargumentbuilder.suggests(requiredargumentbuilder.getType()::listSuggestions);
-+                        registeredAskServerSuggestionsForTree = true; // You can only
-+                        // Paper end - tell clients to ask server for suggestions for EntityArguments
-                     }
-                 }
- 
-diff --git a/src/main/java/net/minecraft/commands/arguments/EntityArgument.java b/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
-+++ b/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
-@@ -0,0 +0,0 @@ public class EntityArgument implements ArgumentType<EntitySelector> {
- 
-             stringreader.setCursor(suggestionsbuilder.getStart());
-             SharedSuggestionProvider icompletionprovider = (SharedSuggestionProvider) commandcontext.getSource();
--            EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, icompletionprovider.hasPermission(2));
-+            EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, icompletionprovider.hasPermission(2), true); // Paper
- 
-             try {
-                 argumentparserselector.parse();
-diff --git a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelectorParser.java b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
-+++ b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
-@@ -0,0 +0,0 @@ public class EntitySelectorParser {
-     private boolean hasScores;
-     private boolean hasAdvancements;
-     private boolean usesSelectors;
-+    public boolean parsingEntityArgumentSuggestions; // Paper - track when parsing EntityArgument suggestions
- 
-     public EntitySelectorParser(StringReader reader) {
-         this(reader, true);
-     }
- 
-     public EntitySelectorParser(StringReader reader, boolean atAllowed) {
-+        // Paper start
-+        this(reader, atAllowed, false);
-+    }
-+    public EntitySelectorParser(StringReader reader, boolean atAllowed, boolean parsingEntityArgumentSuggestions) {
-+        this.parsingEntityArgumentSuggestions = parsingEntityArgumentSuggestions;
-+        // Paper end
-         this.distance = MinMaxBounds.Doubles.ANY;
-         this.level = MinMaxBounds.Ints.ANY;
-         this.rotX = WrappedMinMaxBounds.ANY;
-diff --git a/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java b/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
-+++ b/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
-@@ -0,0 +0,0 @@ public class EntitySelectorOptions {
-     public static final DynamicCommandExceptionType ERROR_ENTITY_TYPE_INVALID = new DynamicCommandExceptionType((entity) -> {
-         return new TranslatableComponent("argument.entity.options.type.invalid", entity);
-     });
-+    // Paper start
-+    public static final DynamicCommandExceptionType ERROR_ENTITY_TAG_INVALID = new DynamicCommandExceptionType((object) -> {
-+        return io.papermc.paper.adventure.PaperAdventure
-+            .asVanilla(net.kyori.adventure.text.Component
-+                .text("Invalid or unknown entity type tag '" + object + "'")
-+                .hoverEvent(net.kyori.adventure.text.event.HoverEvent
-+                    .showText(net.kyori.adventure.text.Component
-+                        .text("You can disable this error in 'paper.yml'")
-+                    )
-+                )
-+            );
-+    });
-+    // Paper end
- 
-     private static void register(String id, EntitySelectorOptions.Modifier handler, Predicate<EntitySelectorParser> condition, Component description) {
-         OPTIONS.put(id, new EntitySelectorOptions.Option(handler, condition, description));
-@@ -0,0 +0,0 @@ public class EntitySelectorOptions {
- 
-                     if (reader.isTag()) {
-                         ResourceLocation resourceLocation = ResourceLocation.read(reader.getReader());
-+                        // Paper start - throw error if invalid entity tag (only on suggestions to keep cmd success behavior)
-+                        final net.minecraft.tags.Tag<EntityType<?>> tag;
-+                        if (com.destroystokyo.paper.PaperConfig.fixTargetSelectorTagCompletion && reader.parsingEntityArgumentSuggestions) {
-+                            tag = EntityTypeTags.getAllTags().getTag(resourceLocation);
-+                        } else {
-+                            tag = EntityTypeTags.getAllTags().getTagOrEmpty(resourceLocation);
-+                        }
-+                        if (tag == null) {
-+                            reader.getReader().setCursor(i);
-+                            throw ERROR_ENTITY_TAG_INVALID.createWithContext(reader.getReader(), resourceLocation.toString());
-+                        }
-+                        // Paper end
-                         reader.addPredicate((entity) -> {
--                            return entity.getType().is(entity.getServer().getTags().getOrEmpty(Registry.ENTITY_TYPE_REGISTRY).getTagOrEmpty(resourceLocation)) != bl;
-+                            return entity.getType().is(tag) != bl; // Paper
-                         });
-                     } else {
-                         ResourceLocation resourceLocation2 = ResourceLocation.read(reader.getReader());
diff --git a/patches/server/Fix-for-large-move-vectors-crashing-server.patch b/patches/server/Fix-for-large-move-vectors-crashing-server.patch
index 1e760d1632..3b582766e9 100644
--- a/patches/server/Fix-for-large-move-vectors-crashing-server.patch
+++ b/patches/server/Fix-for-large-move-vectors-crashing-server.patch
@@ -59,9 +59,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
 +                d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; // Paper - diff on change, used for checking large move vectors above
 +                d8 = d5 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above
-                 entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
-                 double d11 = d7;
+                 boolean flag1 = entity.verticalCollisionBelow;
  
+                 entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
                          float prevPitch = this.player.getXRot();
                          // CraftBukkit end
diff --git a/patches/server/Fix-int-overflow-in-chunk-range-check.patch b/patches/server/Fix-int-overflow-in-chunk-range-check.patch
deleted file mode 100644
index 31a9153033..0000000000
--- a/patches/server/Fix-int-overflow-in-chunk-range-check.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Nassim Jahnke <nassim@njahnke.dev>
-Date: Tue, 11 Jan 2022 19:31:46 +0100
-Subject: [PATCH] Fix int overflow in chunk range check
-
-
-diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/server/level/ChunkMap.java
-+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
-@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
-     public static boolean isChunkInRange(int x1, int z1, int x2, int z2, int distance) {
-         int j1 = Math.max(0, Math.abs(x1 - x2) - 1);
-         int k1 = Math.max(0, Math.abs(z1 - z2) - 1);
--        int l1 = Math.max(0, Math.max(j1, k1) - 1);
--        int i2 = Math.min(j1, k1);
--        int j2 = i2 * i2 + l1 * l1;
-+        // Paper start - fix integer overflow
-+        long l1 = Math.max(0, Math.max(j1, k1) - 1);
-+        long i2 = Math.min(j1, k1);
-+        long j2 = i2 * i2 + l1 * l1;
-+        // Paper end
-         int k2 = distance - 1;
-         int l2 = k2 * k2;
- 
diff --git a/patches/server/Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/Fix-interact-event-not-being-called-in-adventure.patch
index 52b63ef50b..af03127f15 100644
--- a/patches/server/Fix-interact-event-not-being-called-in-adventure.patch
+++ b/patches/server/Fix-interact-event-not-being-called-in-adventure.patch
@@ -10,14 +10,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
-                     MutableComponent ichatmutablecomponent = (new TranslatableComponent("build.tooHigh", new Object[]{i - 1})).withStyle(ChatFormatting.RED);
+                             MutableComponent ichatmutablecomponent = (new TranslatableComponent("build.tooHigh", new Object[]{i - 1})).withStyle(ChatFormatting.RED);
  
-                     this.player.sendMessage(ichatmutablecomponent, ChatType.GAME_INFO, Util.NIL_UUID);
--                } else if (enuminteractionresult.shouldSwing()) {
+                             this.player.sendMessage(ichatmutablecomponent, ChatType.GAME_INFO, Util.NIL_UUID);
+-                        } else if (enuminteractionresult.shouldSwing()) {
 +                } else if (enuminteractionresult.shouldSwing() && !this.player.gameMode.interactResult) {
-                     this.player.swing(enumhand, true);
-                 }
-             }
+                             this.player.swing(enumhand, true);
+                         }
+                     }
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
          Vec3 vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3);
          HitResult movingobjectposition = this.player.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.player));
diff --git a/patches/server/Fix-missing-Level-LevelStem-in-StructureCheck-from-C.patch b/patches/server/Fix-missing-Level-LevelStem-in-StructureCheck-from-C.patch
index 3c33567a83..12f895be5f 100644
--- a/patches/server/Fix-missing-Level-LevelStem-in-StructureCheck-from-C.patch
+++ b/patches/server/Fix-missing-Level-LevelStem-in-StructureCheck-from-C.patch
@@ -23,8 +23,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
 +++ b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
 @@ -0,0 +0,0 @@ public class StructureCheck {
-     private final RegistryAccess registryAccess;
      private final Registry<Biome> biomes;
+     private final Registry<ConfiguredStructureFeature<?, ?>> structureConfigs;
      private final StructureManager structureManager;
 -    private final ResourceKey<Level> dimension;
 +    private final ResourceKey<net.minecraft.world.level.dimension.LevelStem> dimension; // Paper - fix missing CB diff
@@ -32,8 +32,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      private final LevelHeightAccessor heightAccessor;
      private final BiomeSource biomeSource;
 @@ -0,0 +0,0 @@ public class StructureCheck {
-     private final Long2ObjectMap<Object2IntMap<StructureFeature<?>>> loadedChunks = new Long2ObjectOpenHashMap<>();
-     private final Map<StructureFeature<?>, Long2BooleanMap> featureChecks = new HashMap<>();
+     private final Long2ObjectMap<Object2IntMap<ConfiguredStructureFeature<?, ?>>> loadedChunks = new Long2ObjectOpenHashMap<>();
+     private final Map<ConfiguredStructureFeature<?, ?>, Long2BooleanMap> featureChecks = new HashMap<>();
  
 -    public StructureCheck(ChunkScanAccess chunkIoWorker, RegistryAccess registryManager, StructureManager structureManager, ResourceKey<Level> worldKey, ChunkGenerator chunkGenerator, LevelHeightAccessor world, BiomeSource biomeSource, long seed, DataFixer dataFixer) {
 +    public StructureCheck(ChunkScanAccess chunkIoWorker, RegistryAccess registryManager, StructureManager structureManager, ResourceKey<net.minecraft.world.level.dimension.LevelStem> worldKey, ChunkGenerator chunkGenerator, LevelHeightAccessor world, BiomeSource biomeSource, long seed, DataFixer dataFixer) { // Paper - fix missing CB diff
diff --git a/patches/server/Fix-riding-distance-statistics.patch b/patches/server/Fix-riding-distance-statistics.patch
deleted file mode 100644
index d58922552c..0000000000
--- a/patches/server/Fix-riding-distance-statistics.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Marvin Rieple <derrieple@gmail.com>
-Date: Sun, 5 Dec 2021 16:42:07 +0100
-Subject: [PATCH] Fix riding distance statistics
-
-Fixes entity ride distance stats not being awarded correctly.
-Based upon https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/pull-requests/900
-
-diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
-                 Location curPos = this.getCraftPlayer().getLocation(); // Spigot
- 
-                 entity.absMoveTo(d3, d4, d5, f, f1);
--                this.player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
-+                // Paper start - SPIGOT-4396: Synchronize player and vehicle
-+                // Based upon https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/pull-requests/900
-+                Vec3 oldPlayerPosition = this.player.position();
-+                entity.positionRider(this.player);
-+                this.player.xo = oldPlayerPosition.x;
-+                this.player.yo = oldPlayerPosition.y;
-+                this.player.zo = oldPlayerPosition.z;
-+                // Paper end
-                 // Paper start - optimise out extra getCubes
-                 boolean teleportBack = flag1; // violating this is always a fail
-                 if (!teleportBack) {
-@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
-                 }
-                 if (teleportBack) { // Paper end - optimise out extra getCubes
-                     entity.absMoveTo(d0, d1, d2, f, f1);
--                    this.player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
-+                    // Paper start - SPIGOT-6475
-+                    entity.positionRider(this.player);
-+                    this.player.xo = oldPlayerPosition.x;
-+                    this.player.yo = oldPlayerPosition.y;
-+                    this.player.zo = oldPlayerPosition.z;
-+                    // Paper end
-                     this.connection.send(new ClientboundMoveVehiclePacket(entity));
-                     return;
-                 }
-+                player.checkRidingStatistics(player.getX() - oldPlayerPosition.x, player.getY() - oldPlayerPosition.y, player.getZ() - oldPlayerPosition.z); // Paper - SPIGOT-6475: Update riding statistic
- 
-                 // CraftBukkit start - fire PlayerMoveEvent
-                 Player player = this.getCraftPlayer();
diff --git a/patches/server/Fix-sand-duping.patch b/patches/server/Fix-sand-duping.patch
index adf2b20e08..8a8245a06d 100644
--- a/patches/server/Fix-sand-duping.patch
+++ b/patches/server/Fix-sand-duping.patch
@@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        // Paper end - fix sand duping
          if (this.blockState.isAir()) {
              this.discard();
-         } else if (this.level.isClientSide && this.removeAtMillis > 0L) {
+         } else {
 @@ -0,0 +0,0 @@ public class FallingBlockEntity extends Entity {
  
              this.move(MoverType.SELF, this.getDeltaMovement());
diff --git a/patches/server/Fix-this-stupid-bullshit.patch b/patches/server/Fix-this-stupid-bullshit.patch
index 0172efd719..d0711f324a 100644
--- a/patches/server/Fix-this-stupid-bullshit.patch
+++ b/patches/server/Fix-this-stupid-bullshit.patch
@@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/org/bukkit/craftbukkit/Main.java
 @@ -0,0 +0,0 @@ public class Main {
                      Calendar deadline = Calendar.getInstance();
-                     deadline.add(Calendar.DAY_OF_YEAR, -28);
+                     deadline.add(Calendar.DAY_OF_YEAR, -3);
                      if (buildDate.before(deadline.getTime())) {
 -                        System.err.println("*** Error, this build is outdated ***");
 +                        // Paper start - This is some stupid bullshit
diff --git a/patches/server/Fix-xp-reward-for-baby-zombies.patch b/patches/server/Fix-xp-reward-for-baby-zombies.patch
index 0f4be6fe53..db6af156d1 100644
--- a/patches/server/Fix-xp-reward-for-baby-zombies.patch
+++ b/patches/server/Fix-xp-reward-for-baby-zombies.patch
@@ -18,7 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      protected int getExperienceReward(Player player) {
 +        final int previousReward = this.xpReward; // Paper - store previous value to reset after calculating XP reward
          if (this.isBaby()) {
-             this.xpReward = (int) ((float) this.xpReward * 2.5F);
+             this.xpReward = (int) ((double) this.xpReward * 2.5D);
          }
  
 -        return super.getExperienceReward(player);
diff --git a/patches/server/Flat-bedrock-generator-settings.patch b/patches/server/Flat-bedrock-generator-settings.patch
index f2ba1c410c..85d02da376 100644
--- a/patches/server/Flat-bedrock-generator-settings.patch
+++ b/patches/server/Flat-bedrock-generator-settings.patch
@@ -76,7 +76,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          SurfaceRules.ConditionSource conditionSource = SurfaceRules.yBlockCheck(VerticalAnchor.absolute(97), 2);
          SurfaceRules.ConditionSource conditionSource2 = SurfaceRules.yBlockCheck(VerticalAnchor.absolute(256), 0);
 @@ -0,0 +0,0 @@ public class SurfaceRuleData {
-         SurfaceRules.RuleSource ruleSource9 = SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.WOODED_BADLANDS), SurfaceRules.ifTrue(conditionSource, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource14, COARSE_DIRT), SurfaceRules.ifTrue(conditionSource15, COARSE_DIRT), SurfaceRules.ifTrue(conditionSource16, COARSE_DIRT), ruleSource))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.SWAMP), SurfaceRules.ifTrue(conditionSource5, SurfaceRules.ifTrue(SurfaceRules.not(conditionSource6), SurfaceRules.ifTrue(SurfaceRules.noiseCondition(Noises.SWAMP, 0.0D), WATER)))))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.BADLANDS, Biomes.ERODED_BADLANDS, Biomes.WOODED_BADLANDS), SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource2, ORANGE_TERRACOTTA), SurfaceRules.ifTrue(conditionSource4, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource14, TERRACOTTA), SurfaceRules.ifTrue(conditionSource15, TERRACOTTA), SurfaceRules.ifTrue(conditionSource16, TERRACOTTA), SurfaceRules.bandlands())), SurfaceRules.ifTrue(conditionSource7, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_CEILING, RED_SANDSTONE), RED_SAND)), SurfaceRules.ifTrue(SurfaceRules.not(conditionSource10), ORANGE_TERRACOTTA), SurfaceRules.ifTrue(conditionSource9, WHITE_TERRACOTTA), ruleSource3)), SurfaceRules.ifTrue(conditionSource3, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource6, SurfaceRules.ifTrue(SurfaceRules.not(conditionSource4), ORANGE_TERRACOTTA)), SurfaceRules.bandlands())), SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, SurfaceRules.ifTrue(conditionSource9, WHITE_TERRACOTTA)))), SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.ifTrue(conditionSource7, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource11, SurfaceRules.ifTrue(conditionSource10, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource8, AIR), SurfaceRules.ifTrue(SurfaceRules.temperature(), ICE), WATER))), ruleSource8))), SurfaceRules.ifTrue(conditionSource9, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.ifTrue(conditionSource11, SurfaceRules.ifTrue(conditionSource10, WATER))), SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, ruleSource7), SurfaceRules.ifTrue(conditionSource13, SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(0, true, true, CaveSurface.FLOOR), SANDSTONE)))), SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.FROZEN_PEAKS, Biomes.JAGGED_PEAKS), STONE), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.WARM_OCEAN, Biomes.LUKEWARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN), ruleSource2), ruleSource3)));
+         SurfaceRules.RuleSource ruleSource9 = SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.WOODED_BADLANDS), SurfaceRules.ifTrue(conditionSource, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource15, COARSE_DIRT), SurfaceRules.ifTrue(conditionSource16, COARSE_DIRT), SurfaceRules.ifTrue(conditionSource17, COARSE_DIRT), ruleSource))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.SWAMP), SurfaceRules.ifTrue(conditionSource5, SurfaceRules.ifTrue(SurfaceRules.not(conditionSource6), SurfaceRules.ifTrue(SurfaceRules.noiseCondition(Noises.SWAMP, 0.0D), WATER)))))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.BADLANDS, Biomes.ERODED_BADLANDS, Biomes.WOODED_BADLANDS), SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource2, ORANGE_TERRACOTTA), SurfaceRules.ifTrue(conditionSource4, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource15, TERRACOTTA), SurfaceRules.ifTrue(conditionSource16, TERRACOTTA), SurfaceRules.ifTrue(conditionSource17, TERRACOTTA), SurfaceRules.bandlands())), SurfaceRules.ifTrue(conditionSource7, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_CEILING, RED_SANDSTONE), RED_SAND)), SurfaceRules.ifTrue(SurfaceRules.not(conditionSource10), ORANGE_TERRACOTTA), SurfaceRules.ifTrue(conditionSource9, WHITE_TERRACOTTA), ruleSource3)), SurfaceRules.ifTrue(conditionSource3, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource6, SurfaceRules.ifTrue(SurfaceRules.not(conditionSource4), ORANGE_TERRACOTTA)), SurfaceRules.bandlands())), SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, SurfaceRules.ifTrue(conditionSource9, WHITE_TERRACOTTA)))), SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.ifTrue(conditionSource7, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource11, SurfaceRules.ifTrue(conditionSource10, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource8, AIR), SurfaceRules.ifTrue(SurfaceRules.temperature(), ICE), WATER))), ruleSource8))), SurfaceRules.ifTrue(conditionSource9, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.ifTrue(conditionSource11, SurfaceRules.ifTrue(conditionSource10, WATER))), SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, ruleSource7), SurfaceRules.ifTrue(conditionSource13, SurfaceRules.ifTrue(SurfaceRules.DEEP_UNDER_FLOOR, SANDSTONE)), SurfaceRules.ifTrue(conditionSource14, SurfaceRules.ifTrue(SurfaceRules.VERY_DEEP_UNDER_FLOOR, SANDSTONE)))), SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.FROZEN_PEAKS, Biomes.JAGGED_PEAKS), STONE), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.WARM_OCEAN, Biomes.LUKEWARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN), ruleSource2), ruleSource3)));
          Builder<SurfaceRules.RuleSource> builder = ImmutableList.builder();
          if (bedrockRoof) {
 -            builder.add(SurfaceRules.ifTrue(SurfaceRules.not(SurfaceRules.verticalGradient("bedrock_roof", VerticalAnchor.belowTop(5), VerticalAnchor.top())), BEDROCK));
@@ -107,16 +107,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public void buildSurface(WorldGenRegion region, StructureFeatureManager structures, ChunkAccess chunk) {
          if (!SharedConstants.debugVoidTerrain(chunk.getPos())) {
 -            WorldGenerationContext worldgenerationcontext = new WorldGenerationContext(this, region);
-+            WorldGenerationContext worldgenerationcontext = new WorldGenerationContext(this, region, structures.getWorld()); // Paper
-             NoiseGeneratorSettings generatorsettingbase = (NoiseGeneratorSettings) this.settings.get();
-             NoiseChunk noisechunk = chunk.getOrCreateNoiseChunk(this.sampler, () -> {
++            WorldGenerationContext worldgenerationcontext = new WorldGenerationContext(this, region, region.getLevel()); // Paper
+             NoiseGeneratorSettings generatorsettingbase = (NoiseGeneratorSettings) this.settings.value();
+             NoiseChunk noisechunk = chunk.getOrCreateNoiseChunk(this.router, () -> {
                  return new Beardifier(structures, chunk);
 @@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
              return new Beardifier(structureAccessor, chunk);
-         }, (NoiseGeneratorSettings) this.settings.get(), this.globalFluidPicker, Blender.of(chunkRegion));
+         }, (NoiseGeneratorSettings) this.settings.value(), this.globalFluidPicker, Blender.of(chunkRegion));
          Aquifer aquifer = noisechunk.aquifer();
 -        CarvingContext carvingcontext = new CarvingContext(this, chunkRegion.registryAccess(), chunk.getHeightAccessorForGeneration(), noisechunk);
-+        CarvingContext carvingcontext = new CarvingContext(this, chunkRegion.registryAccess(), chunk.getHeightAccessorForGeneration(), noisechunk, structureAccessor.getWorld()); // Paper
++        CarvingContext carvingcontext = new CarvingContext(this, chunkRegion.registryAccess(), chunk.getHeightAccessorForGeneration(), noisechunk, chunkRegion.getLevel()); // Paper
          CarvingMask carvingmask = ((ProtoChunk) chunk).getOrCreateCarvingMask(generationStep);
  
          for (int j = -8; j <= 8; ++j) {
diff --git a/patches/server/Goat-ram-API.patch b/patches/server/Goat-ram-API.patch
index 18f82c31df..6e3fed2f1b 100644
--- a/patches/server/Goat-ram-API.patch
+++ b/patches/server/Goat-ram-API.patch
@@ -9,9 +9,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
 +++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
 @@ -0,0 +0,0 @@ public class Goat extends Animal {
-         return world.getBlockState(pos.below()).is((Tag) BlockTags.GOATS_SPAWNABLE_ON) && isBrightEnoughToSpawn(world, pos);
+     public static boolean checkGoatSpawnRules(EntityType<? extends Animal> entityType, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) {
+         return world.getBlockState(pos.below()).is(BlockTags.GOATS_SPAWNABLE_ON) && isBrightEnoughToSpawn(world, pos);
      }
- 
++
 +    // Paper start - Goat ram API
 +    public void ram(net.minecraft.world.entity.LivingEntity entity) {
 +        Brain<Goat> brain = this.getBrain();
@@ -22,10 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        brain.setActiveActivityIfPossible(net.minecraft.world.entity.schedule.Activity.RAM);
 +    }
 +    // Paper end
-+
-     private static class GoatPathNavigation extends GroundPathNavigation {
- 
-         GoatPathNavigation(Goat goat, Level world) {
+ }
 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java
diff --git a/patches/server/Guard-against-serializing-mismatching-chunk-coordina.patch b/patches/server/Guard-against-serializing-mismatching-chunk-coordina.patch
index f0b5055770..3788aecc03 100644
--- a/patches/server/Guard-against-serializing-mismatching-chunk-coordina.patch
+++ b/patches/server/Guard-against-serializing-mismatching-chunk-coordina.patch
@@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        ChunkPos chunkcoordintpair1 = new ChunkPos(nbt.getInt("xPos"), nbt.getInt("zPos")); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate
  
          if (!Objects.equals(chunkPos, chunkcoordintpair1)) {
-             ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkPos, chunkPos, chunkcoordintpair1);
+             ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", new Object[]{chunkPos, chunkPos, chunkcoordintpair1});
 diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
diff --git a/patches/server/Handle-plugin-prefixes-using-Log4J-configuration.patch b/patches/server/Handle-plugin-prefixes-using-Log4J-configuration.patch
index fb4647a7d3..6f2c39e57f 100644
--- a/patches/server/Handle-plugin-prefixes-using-Log4J-configuration.patch
+++ b/patches/server/Handle-plugin-prefixes-using-Log4J-configuration.patch
@@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -    runtimeOnly("org.apache.logging.log4j:log4j-core:2.14.1")
 +    implementation("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - implementation
      // Paper end
-     implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper
+     implementation("org.apache.logging.log4j:log4j-iostreams:2.17.1") // Paper
      implementation("org.ow2.asm:asm:9.2")
 diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
diff --git a/patches/server/Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch b/patches/server/Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch
index 5601e4fe5d..4dd397fe5e 100644
--- a/patches/server/Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch
+++ b/patches/server/Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch
@@ -1209,7 +1209,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          // CraftBukkit end
  
          worldserver1.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper
--        while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) {
+-        while (avoidSuffocation && !worldserver1.noCollision((Entity) entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) {
 +        while (avoidSuffocation && !worldserver1.noCollision(entityplayer1, entityplayer1.getBoundingBox(), true) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { // Paper - make sure this loads chunks, we default to NOT loading now
              entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ());
          }
@@ -1223,7 +1223,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
                  this.setDeltaMovement(this.getDeltaMovement().multiply((double) f2, 1.0D, (double) f2));
 -                if (this.level.getBlockStatesIfLoaded(this.getBoundingBox().deflate(1.0E-6D)).noneMatch((iblockdata1) -> {
--                    return iblockdata1.is((Tag) BlockTags.FIRE) || iblockdata1.is(Blocks.LAVA);
+-                    return iblockdata1.is(BlockTags.FIRE) || iblockdata1.is(Blocks.LAVA);
 -                })) {
 +                // Paper start - remove expensive streams from here
 +                boolean noneMatch = true;
@@ -1253,7 +1253,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                                }
 +
 +                                BlockState type = chunk.getBlockStateFinal(fx, fy, fz);
-+                                if (type.is((Tag) BlockTags.FIRE) || type.is(Blocks.LAVA)) {
++                                if (type.is(BlockTags.FIRE) || type.is(Blocks.LAVA)) {
 +                                    noneMatch = false;
 +                                    // can't break, we need to retain vanilla behavior by ensuring ALL chunks are loaded
 +                                }
@@ -1368,19 +1368,36 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public static Vec3 collideBoundingBox(@Nullable Entity entity, Vec3 movement, AABB entityBoundingBox, Level world, List<VoxelShape> collisions) {
 @@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i
              float f = this.dimensions.width * 0.8F;
-             AABB axisalignedbb = AABB.ofSize(vec3d, (double) f, 1.0E-6D, (double) f);
+             AABB axisalignedbb = AABB.ofSize(this.getEyePosition(), (double) f, 1.0E-6D, (double) f);
  
--            return this.level.getBlockStates(axisalignedbb).filter(Predicate.not(BlockBehaviour.BlockStateBase::isAir)).anyMatch((iblockdata) -> {
--                BlockPos blockposition = new BlockPos(vec3d);
--
--                return iblockdata.isSuffocating(this.level, blockposition) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level, blockposition).move(vec3d.x, vec3d.y, vec3d.z), Shapes.create(axisalignedbb), BooleanOp.AND);
+-            return BlockPos.betweenClosedStream(axisalignedbb).anyMatch((blockposition) -> {
+-                BlockState iblockdata = this.level.getBlockState(blockposition);
++            BlockPos.MutableBlockPos blockposition = new BlockPos.MutableBlockPos();
++            int minX = Mth.floor(axisalignedbb.minX);
++            int minY = Mth.floor(axisalignedbb.minY);
++            int minZ = Mth.floor(axisalignedbb.minZ);
++            int maxX = Mth.floor(axisalignedbb.maxX);
++            int maxY = Mth.floor(axisalignedbb.maxY);
++            int maxZ = Mth.floor(axisalignedbb.maxZ);
++            for (int fz = minZ; fz <= maxZ; ++fz) {
++                for (int fx = minX; fx <= maxX; ++fx) {
++                    for (int fy = minY; fy <= maxY; ++fy) {
++                        net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk)this.level.getChunkIfLoadedImmediately(fx >> 4, fz >> 4);
++                        if (chunk == null) {
++                            continue;
++                        }
+ 
+-                return !iblockdata.isAir() && iblockdata.isSuffocating(this.level, blockposition) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level, blockposition).move((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()), Shapes.create(axisalignedbb), BooleanOp.AND);
 -            });
-+            // Paper start
-+            return io.papermc.paper.util.CollisionUtil.getCollisionsForBlocksOrWorldBorder(this.level, this, axisalignedbb, null,
-+                false, false, false, true, (BlockState blockState, BlockPos blockPos) -> {
-+                    return blockState.isSuffocating(this.level, blockPos);
-+                });
-+            // Paper end
++                        BlockState iblockdata = chunk.getBlockStateFinal(fx, fy, fz);
++                        blockposition.set(fx, fy, fz);
++                        if (!iblockdata.isAir() && iblockdata.isSuffocating(this.level, blockposition) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level, blockposition).move((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()), Shapes.create(axisalignedbb), BooleanOp.AND)) {
++                            return true;
++                        }
++                    }
++                }
++            }
++            return false;
          }
      }
  
@@ -1535,7 +1552,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
 +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
 @@ -0,0 +0,0 @@ public class LevelChunkSection {
-         this.biomes = new PalettedContainer<>(biomeRegistry, (Biome) biomeRegistry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null); // Paper - Anti-Xray - Add preset biomes
+         this.biomes = new PalettedContainer<>(biomeRegistry.asHolderIdMap(), biomeRegistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null); // Paper - Anti-Xray - Add preset biomes
      }
  
 +    // Paper start
@@ -1665,9 +1682,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
 @@ -0,0 +0,0 @@ public class LevelChunkSection {
-             }
  
          });
+         // Paper end
 +        this.initBlockCollisionData(); // Paper
      }
  
diff --git a/patches/server/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch
index 683df8ad28..6b29499007 100644
--- a/patches/server/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch
+++ b/patches/server/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch
@@ -833,25 +833,9 @@ diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.j
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
 +++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
-@@ -0,0 +0,0 @@
- package net.minecraft.server.level;
- 
- import com.mojang.datafixers.util.Pair;
-+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; // Paper
- import it.unimi.dsi.fastutil.objects.ObjectArrayList;
- import it.unimi.dsi.fastutil.objects.ObjectList;
- import it.unimi.dsi.fastutil.objects.ObjectListIterator;
-@@ -0,0 +0,0 @@ import net.minecraft.util.thread.ProcessorMailbox;
- import net.minecraft.world.level.ChunkPos;
- import net.minecraft.world.level.LightLayer;
- import net.minecraft.world.level.chunk.ChunkAccess;
-+import net.minecraft.world.level.chunk.ChunkStatus;
- import net.minecraft.world.level.chunk.DataLayer;
- import net.minecraft.world.level.chunk.LevelChunkSection;
- import net.minecraft.world.level.chunk.LightChunkGetter;
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import org.slf4j.Logger;
  public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCloseable {
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
      private final ProcessorMailbox<Runnable> taskMailbox;
 -    private final ObjectList<Pair<ThreadedLevelLightEngine.TaskType, Runnable>> lightTasks = new ObjectArrayList<>();
 -    private final ChunkMap chunkMap;
@@ -886,13 +870,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Retain the chunks priority level for queued light tasks
 +    class LightQueue {
 +        private int size = 0;
-+        private final Long2ObjectLinkedOpenHashMap<ChunkLightQueue>[] buckets = new Long2ObjectLinkedOpenHashMap[MAX_PRIORITIES];
++        private final it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap<ChunkLightQueue>[] buckets = new it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap[MAX_PRIORITIES];
 +        private final java.util.concurrent.ConcurrentLinkedQueue<PendingLightTask> pendingTasks = new java.util.concurrent.ConcurrentLinkedQueue<>();
 +        private final java.util.concurrent.ConcurrentLinkedQueue<Runnable> priorityChanges = new java.util.concurrent.ConcurrentLinkedQueue<>();
 +
 +        private LightQueue() {
 +            for (int i = 0; i < buckets.length; i++) {
-+                buckets[i] = new Long2ObjectLinkedOpenHashMap<>();
++                buckets[i] = new it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap<>();
 +            }
 +        }
 +
@@ -952,10 +936,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                run.run();
 +            }
 +            boolean hasWork = false;
-+            Long2ObjectLinkedOpenHashMap<ChunkLightQueue>[] buckets = this.buckets;
++            it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap<ChunkLightQueue>[] buckets = this.buckets;
 +            int priority = 0;
 +            while (priority < MAX_PRIORITIES && !isEmpty()) {
-+                Long2ObjectLinkedOpenHashMap<ChunkLightQueue> bucket = buckets[priority];
++                it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap<ChunkLightQueue> bucket = buckets[priority];
 +                if (bucket.isEmpty()) {
 +                    priority++;
 +                    if (hasWork) {
diff --git a/patches/server/Implement-Keyed-on-World.patch b/patches/server/Implement-Keyed-on-World.patch
index 19fe1cf191..ef96a97380 100644
--- a/patches/server/Implement-Keyed-on-World.patch
+++ b/patches/server/Implement-Keyed-on-World.patch
@@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, new net.minecraft.resources.ResourceLocation(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper
          }
  
-         ServerLevel internal = (ServerLevel) new ServerLevel(this.console, console.executor, worldSession, worlddata, worldKey, dimensionmanager, this.getServer().progressListenerFactory.create(11),
+         ServerLevel internal = (ServerLevel) new ServerLevel(this.console, console.executor, worldSession, worlddata, worldKey, holder, this.getServer().progressListenerFactory.create(11),
 @@ -0,0 +0,0 @@ public final class CraftServer implements Server {
          return null;
      }
diff --git a/patches/server/Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/patches/server/Improve-Server-Thread-Pool-and-Thread-Priorities.patch
index 9b2faf2514..44aab3b60c 100644
--- a/patches/server/Improve-Server-Thread-Pool-and-Thread-Priorities.patch
+++ b/patches/server/Improve-Server-Thread-Pool-and-Thread-Priorities.patch
@@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main", -1); // Paper - add -1 priority
      private static final ExecutorService IO_POOL = makeIoExecutor();
      public static LongSupplier timeSource = System::nanoTime;
-     public static final UUID NIL_UUID = new UUID(0L, 0L);
+     public static final Ticker TICKER = new Ticker() {
 @@ -0,0 +0,0 @@ public class Util {
          return Instant.now().toEpochMilli();
      }
diff --git a/patches/server/Improve-ServerGUI.patch b/patches/server/Improve-ServerGUI.patch
index 7324158763..861fa7c8db 100644
--- a/patches/server/Improve-ServerGUI.patch
+++ b/patches/server/Improve-ServerGUI.patch
@@ -42,18 +42,6 @@ diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/sr
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
 +++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
-@@ -0,0 +0,0 @@ import net.minecraft.DefaultUncaughtExceptionHandler;
- import net.minecraft.server.dedicated.DedicatedServer;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
-+// Paper start
-+import java.io.IOException;
-+import java.util.Objects;
-+import javax.imageio.ImageIO;
-+// Paper end
- 
- public class MinecraftServerGui extends JComponent {
- 
 @@ -0,0 +0,0 @@ public class MinecraftServerGui extends JComponent {
          jframe.pack();
          jframe.setLocationRelativeTo((Component) null);
@@ -62,8 +50,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +        // Paper start - Add logo as frame image
 +        try {
-+            jframe.setIconImage(ImageIO.read(Objects.requireNonNull(MinecraftServerGui.class.getClassLoader().getResourceAsStream("logo.png"))));
-+        } catch (IOException ignore) {
++            jframe.setIconImage(javax.imageio.ImageIO.read(Objects.requireNonNull(MinecraftServerGui.class.getClassLoader().getResourceAsStream("logo.png"))));
++        } catch (java.io.IOException ignore) {
 +        }
 +        // Paper end
 +
diff --git a/patches/server/Improve-boat-collision-performance.patch b/patches/server/Improve-boat-collision-performance.patch
index 7057f3bc42..8454d84a27 100644
--- a/patches/server/Improve-boat-collision-performance.patch
+++ b/patches/server/Improve-boat-collision-performance.patch
@@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          return new IllegalStateException("No jar file system provider found");
      });
 +    public static final double COLLISION_EPSILON = 1.0E-7; // Paper
-     private static Consumer<String> thePauser = (string) -> {
+     private static Consumer<String> thePauser = (message) -> {
      };
  
 diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
diff --git a/patches/server/Improved-Watchdog-Support.patch b/patches/server/Improved-Watchdog-Support.patch
index ac44397338..65351e56dd 100644
--- a/patches/server/Improved-Watchdog-Support.patch
+++ b/patches/server/Improved-Watchdog-Support.patch
@@ -220,15 +220,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  }
                  // Spigot End
 @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
-             this.packRepository.setSelected(datapacks);
+             this.packRepository.setSelected(dataPacks);
              this.worldData.setDataPackConfig(MinecraftServer.getSelectedPacks(this.packRepository));
-             datapackresources.updateGlobals();
+             this.resources.managers.updateRegistryTags(this.registryAccess());
 -            this.getPlayerList().saveAll();
 +            if (Thread.currentThread() != this.serverThread) return; // Paper
-+            //this.getPlayerList().savePlayers(); // Paper - we don't need to do this
++            //this.getPlayerList().saveAll(); // Paper - we don't need to do this
              this.getPlayerList().reloadResources();
-             this.functionManager.replaceLibrary(this.resources.getFunctionLibrary());
-             this.structureManager.onResourceManagerReload(this.resources.getResourceManager());
+             this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary());
+             this.structureManager.onResourceManagerReload(this.resources.resourceManager);
 diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -295,7 +295,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              task.run();
          } catch (Exception var3) {
 +            if (var3.getCause() instanceof ThreadDeath) throw var3; // Paper
-             LOGGER.fatal("Error executing task on {}", this.name(), var3);
+             LOGGER.error(LogUtils.FATAL_MARKER, "Error executing task on {}", this.name(), var3);
          }
  
 diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
diff --git a/patches/server/Lag-compensate-block-breaking.patch b/patches/server/Lag-compensate-block-breaking.patch
index 1d217fdaf8..a4b64c63cb 100644
--- a/patches/server/Lag-compensate-block-breaking.patch
+++ b/patches/server/Lag-compensate-block-breaking.patch
@@ -94,7 +94,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                this.destroyProgressStart = this.gameTicks; this.lastDigTime = System.nanoTime(); // Paper - lag compensate block breaking
                  float f = 1.0F;
  
-                 iblockdata = this.level.getBlockState(pos);
+                 iblockdata1 = this.level.getBlockState(pos);
 @@ -0,0 +0,0 @@ public class ServerPlayerGameMode {
                      int j = (int) (f * 10.0F);
  
@@ -108,8 +108,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -                    int k = this.gameTicks - this.destroyProgressStart;
 +                    int k = this.getTimeDiggingLagCompensate(); // Paper - lag compensate block breaking
  
-                     iblockdata = this.level.getBlockState(pos);
-                     if (!iblockdata.isAir()) {
+                     iblockdata1 = this.level.getBlockState(pos);
+                     if (!iblockdata1.isAir()) {
 @@ -0,0 +0,0 @@ public class ServerPlayerGameMode {
                              this.isDestroyingBlock = false;
                              this.hasDelayedDestroy = true;
diff --git a/patches/server/MC-Dev-fixes.patch b/patches/server/MC-Dev-fixes.patch
index 630d365162..34ad3ef8f2 100644
--- a/patches/server/MC-Dev-fixes.patch
+++ b/patches/server/MC-Dev-fixes.patch
@@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        return (Strategy<K>) Util.IdentityStrategy.INSTANCE; // Paper - decompile fix
      }
  
-     public static <V> CompletableFuture<List<V>> sequence(List<? extends CompletableFuture<? extends V>> futures) {
+     public static <V> CompletableFuture<List<V>> sequence(List<? extends CompletableFuture<V>> futures) {
 diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/core/BlockPos.java
@@ -39,21 +39,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                      }
                  }
              };
-diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/core/MappedRegistry.java
-+++ b/src/main/java/net/minecraft/core/MappedRegistry.java
-@@ -0,0 +0,0 @@ public class MappedRegistry<T> extends WritableRegistry<T> {
-     }
- 
-     static record RegistryEntry<T>(ResourceKey<T> key, int id, T value) {
--        RegistryEntry(ResourceKey<T> key, int rawId, T entry) {
--            this.key = key;
--            this.id = rawId;
--            this.value = entry;
--        }
-     }
- }
 diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/nbt/ListTag.java
@@ -121,7 +106,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  import net.minecraft.network.protocol.status.ServerboundPingRequestPacket;
  import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket;
  import net.minecraft.util.VisibleForDebug;
- import org.apache.logging.log4j.LogManager;
+ import org.slf4j.Logger;
  
  public enum ConnectionProtocol {
 -    HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))),
@@ -142,17 +127,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLoginPacket.java
 +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLoginPacket.java
 @@ -0,0 +0,0 @@ public record ClientboundLoginPacket(int playerId, boolean hardcore, GameType ga
-         }), buf.readWithCodec(RegistryAccess.RegistryHolder.NETWORK_CODEC), buf.readWithCodec(DimensionType.CODEC).get(), ResourceKey.create(Registry.DIMENSION_REGISTRY, buf.readResourceLocation()), buf.readLong(), buf.readVarInt(), buf.readVarInt(), buf.readVarInt(), buf.readBoolean(), buf.readBoolean(), buf.readBoolean(), buf.readBoolean());
+         }), buf.readWithCodec(RegistryAccess.NETWORK_CODEC).freeze(), buf.readWithCodec(DimensionType.CODEC), ResourceKey.create(Registry.DIMENSION_REGISTRY, buf.readResourceLocation()), buf.readLong(), buf.readVarInt(), buf.readVarInt(), buf.readVarInt(), buf.readBoolean(), buf.readBoolean(), buf.readBoolean(), buf.readBoolean());
      }
  
--    public ClientboundLoginPacket(int playerEntityId, boolean bl, GameType previousGameMode, @Nullable GameType gameType, Set<ResourceKey<Level>> set, RegistryAccess.RegistryHolder registryHolder, DimensionType dimensionType, ResourceKey<Level> resourceKey, long l, int maxPlayers, int chunkLoadDistance, int i, boolean bl2, boolean bl3, boolean bl4, boolean bl5) {
+-    public ClientboundLoginPacket(int playerEntityId, boolean bl, GameType previousGameMode, @Nullable GameType gameType, Set<ResourceKey<Level>> set, RegistryAccess.Frozen frozen, Holder<DimensionType> holder, ResourceKey<Level> resourceKey, long l, int maxPlayers, int chunkLoadDistance, int i, boolean bl2, boolean bl3, boolean bl4, boolean bl5) {
 -        this.playerId = playerEntityId;
 -        this.hardcore = bl;
 -        this.gameType = previousGameMode;
 -        this.previousGameType = gameType;
 -        this.levels = set;
--        this.registryHolder = registryHolder;
--        this.dimensionType = dimensionType;
+-        this.registryHolder = frozen;
+-        this.dimensionType = holder;
 -        this.dimension = resourceKey;
 -        this.seed = l;
 -        this.maxPlayers = maxPlayers;
@@ -178,8 +163,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -            return stream.map(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error
 +            return stream.<Pack>map(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error // todo: is this needed anymore?
          }, this).thenCompose((immutablelist) -> {
-             return ServerResources.loadResources(immutablelist, this.registryHolder, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this);
-         }).thenAcceptAsync((datapackresources) -> {
+             MultiPackResourceManager resourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, immutablelist);
+ 
 diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/Ticket.java
@@ -236,10 +221,10 @@ diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/biome/Biome.java
 +++ b/src/main/java/net/minecraft/world/level/biome/Biome.java
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import net.minecraft.world.level.material.FluidState;
+ import net.minecraft.world.level.material.Fluids;
  
  public final class Biome {
-     public static final Logger LOGGER = LogManager.getLogger();
 -    public static final Codec<Biome> DIRECT_CODEC;
 -    public static final Codec<Biome> NETWORK_CODEC;
 +    // Paper start - decompile fix: move up verbatim from static block
@@ -256,23 +241,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            return biome.mobSettings;
 +        })).apply(instance, Biome::new);
 +    });
-+    public static final Codec<Biome> NETWORK_CODEC = RecordCodecBuilder.create((instance) -> {
++    public static final Codec<Biome> NETWORK_CODE = RecordCodecBuilder.create((instance) -> {
 +        return instance.group(Biome.ClimateSettings.CODEC.forGetter((biome) -> {
 +            return biome.climateSettings;
 +        }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biome) -> {
 +            return biome.biomeCategory;
 +        }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biome) -> {
 +            return biome.specialEffects;
-+        })).apply(instance, (climateSettings, biomeCategory, biomeSpecialEffects) -> {
-+            return new Biome(climateSettings, biomeCategory, biomeSpecialEffects, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY);
++        })).apply(instance, (weather, category, effects) -> {
++            return new Biome(weather, category, effects, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY);
 +        });
 +    });
 +    // Paper end
-     public static final Codec<Supplier<Biome>> CODEC = RegistryFileCodec.create(Registry.BIOME_REGISTRY, DIRECT_CODEC);
-     public static final Codec<List<Supplier<Biome>>> LIST_CODEC = RegistryFileCodec.homogeneousList(Registry.BIOME_REGISTRY, DIRECT_CODEC);
+     public static final Codec<Holder<Biome>> CODEC = RegistryFileCodec.create(Registry.BIOME_REGISTRY, DIRECT_CODEC);
+     public static final Codec<HolderSet<Biome>> LIST_CODEC = RegistryCodecs.homogeneousList(Registry.BIOME_REGISTRY, DIRECT_CODEC);
      private static final PerlinSimplexNoise TEMPERATURE_NOISE = new PerlinSimplexNoise(new WorldgenRandom(new LegacyRandomSource(1234L)), ImmutableList.of(0));
 @@ -0,0 +0,0 @@ public final class Biome {
-         return resourceLocation == null ? super.toString() : resourceLocation.toString();
+         return biomeEntry.value().getBiomeCategory();
      }
  
 -    static {
@@ -296,8 +281,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -                return biome.biomeCategory;
 -            }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biome) -> {
 -                return biome.specialEffects;
--            })).apply(instance, (climateSettings, biomeCategory, biomeSpecialEffects) -> {
--                return new Biome(climateSettings, biomeCategory, biomeSpecialEffects, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY);
+-            })).apply(instance, (weather, category, effects) -> {
+-                return new Biome(weather, category, effects, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY);
 -            });
 -        });
 -    }
diff --git a/patches/server/MC-Utils.patch b/patches/server/MC-Utils.patch
index 3836446968..e68a76c367 100644
--- a/patches/server/MC-Utils.patch
+++ b/patches/server/MC-Utils.patch
@@ -4478,7 +4478,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                          JvmProfiler.INSTANCE.onPacketSent(k, integer, channelHandlerContext.channel().remoteAddress(), j);
                      }
                  } catch (Throwable var10) {
--                    LOGGER.error(var10);
+-                    LOGGER.error("Error receiving packet {}", integer, var10);
 +                    LOGGER.error("Packet encoding of packet ID {} threw (skippable? {})", integer, packet.isSkippable(), var10); // Paper - Give proper error message
                      if (packet.isSkippable()) {
                          throw new SkipPacketException(var10);
@@ -5082,19 +5082,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          this.setTicketLevel(level);
          this.changedBlocksPerSection = new ShortSet[world.getSectionsCount()];
 +        this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper
-     }
- 
-     // CraftBukkit start
--    public LevelChunk getFullChunk() {
-+    public final LevelChunk getFullChunk() { // Paper - final for inline
-         if (!ChunkHolder.getFullChunkStatus(this.oldTicketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks
-         return this.getFullChunkUnchecked();
-     }
-@@ -0,0 +0,0 @@ public class ChunkHolder {
-     }
-     // CraftBukkit end
- 
++    }
++
 +    // Paper start
++    public LevelChunk getFullChunkUnchecked() {
++        CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL);
++        Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = (Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>) statusFuture.getNow(null);
++        return (either == null) ? null : (LevelChunk) either.left().orElse(null);
+     }
+ 
 +    public ChunkAccess getAvailableChunkNow() {
 +        // TODO can we just getStatusFuture(EMPTY)?
 +        for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getParent(); curr != next; curr = next, next = next.getParent()) {
@@ -5137,6 +5133,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getTickingChunkFuture();
          Either<LevelChunk, ChunkHolder.ChunkLoadingFailure> either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error
  
+@@ -0,0 +0,0 @@ public class ChunkHolder {
+     }
+ 
+     @Nullable
+-    public LevelChunk getFullChunk() {
++    public final LevelChunk getFullChunk() { // Paper - final for inline
+         CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getFullChunkFuture();
+         Either<LevelChunk, ChunkHolder.ChunkLoadingFailure> either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error
+ 
 @@ -0,0 +0,0 @@ public class ChunkHolder {
          return null;
      }
@@ -5413,15 +5418,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                          ((LevelChunk) ichunkaccess).setLoaded(false);
                      }
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
-                     this.lightEngine.updateChunkStatus(ichunkaccess.getPos());
                      this.lightEngine.tryScheduleUpdate();
                      this.progressListener.onStatusChange(ichunkaccess.getPos(), (ChunkStatus) null);
--                }
+                     this.chunkSaveCooldowns.remove(ichunkaccess.getPos().toLong());
 +                } else if (removed) { // Paper start
-+                    for (int index = 0, len = this.regionManagers.size(); index < len; ++index) {
-+                        this.regionManagers.get(index).removeChunk(holder.pos.x, holder.pos.z);
-+                    }
-+                } // Paper end
++                for (int index = 0, len = this.regionManagers.size(); index < len; ++index) {
++                    this.regionManagers.get(index).removeChunk(holder.pos.x, holder.pos.z);
+                 }
++            } // Paper end
  
              }
          };
@@ -5486,22 +5490,21 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/sr
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
 +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-@@ -0,0 +0,0 @@ import net.minecraft.world.level.storage.LevelData;
- import net.minecraft.world.level.storage.LevelStorageSource;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
-+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper
-+import java.util.function.Function; // Paper
+@@ -0,0 +0,0 @@ import net.minecraft.world.level.storage.LevelStorageSource;
  
  public class ServerChunkCache extends ChunkSource {
  
++    public static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper
+     public static final List<ChunkStatus> CHUNK_STATUSES = ChunkStatus.getStatusList();
+     private final DistanceManager distanceManager;
+     final ServerLevel level;
 @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
      @Nullable
      @VisibleForDebug
      private NaturalSpawner.SpawnState lastSpawnState;
 +    // Paper start
 +    final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock();
-+    final Long2ObjectOpenHashMap<LevelChunk> loadedChunkMap = new Long2ObjectOpenHashMap<>(8192, 0.5f);
++    final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<LevelChunk> loadedChunkMap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(8192, 0.5f);
 +
 +    private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4];
 +
@@ -5602,13 +5605,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        this.getChunkFutureAsynchronously(x, z, 33, ChunkHolder::getFullChunkFuture, onLoad);
 +    }
 +
-+    private void getChunkFutureAsynchronously(int x, int z, int ticketLevel, Function<ChunkHolder, CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>>> futureGet, java.util.function.Consumer<LevelChunk> onLoad) {
++    private void getChunkFutureAsynchronously(int x, int z, int ticketLevel, java.util.function.Function<ChunkHolder, CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>>> futureGet, java.util.function.Consumer<LevelChunk> onLoad) {
 +        if (Thread.currentThread() != this.mainThread) {
 +            throw new IllegalStateException();
 +        }
 +        ChunkPos chunkPos = new ChunkPos(x, z);
 +        Long identifier = this.chunkFutureAwaitCounter++;
-+        this.distanceManager.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier);
++        this.distanceManager.addTicket(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier);
 +        this.runDistanceManagerUpdates();
 +
 +        ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(chunkPos.toLong());
@@ -5625,9 +5628,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    if (throwable instanceof ThreadDeath) {
 +                        throw (ThreadDeath)throwable;
 +                    }
-+                    net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", throwable);
++                    net.minecraft.server.MinecraftServer.LOGGER.error("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", throwable);
 +                } else if (either.right().isPresent()) {
-+                    net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "': " + either.right().get().toString());
++                    net.minecraft.server.MinecraftServer.LOGGER.error("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "': " + either.right().get().toString());
 +                }
 +
 +                try {
@@ -5638,13 +5641,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    if (thr instanceof ThreadDeath) {
 +                        throw (ThreadDeath)thr;
 +                    }
-+                    net.minecraft.server.MinecraftServer.LOGGER.fatal("Load callback for future await failed " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", thr);
++                    net.minecraft.server.MinecraftServer.LOGGER.error("Load callback for future await failed " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", thr);
 +                    return;
 +                }
 +            } finally {
 +                // due to odd behaviour with CB unload implementation we need to have these AFTER the load callback.
-+                ServerChunkCache.this.distanceManager.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos);
-+                ServerChunkCache.this.distanceManager.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier);
++                ServerChunkCache.this.distanceManager.addTicket(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos);
++                ServerChunkCache.this.distanceManager.removeTicket(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier);
 +            }
 +        }, this.mainThreadProcessor);
 +    }
@@ -5726,9 +5729,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    if (throwable instanceof ThreadDeath) {
 +                        throw (ThreadDeath)throwable;
 +                    }
-+                    LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", throwable);
++                    LOGGER.error("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", throwable);
 +                } else if (either.right().isPresent()) {
-+                    LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "': " + either.right().get().toString());
++                    LOGGER.error("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "': " + either.right().get().toString());
 +                }
 +
 +                try {
@@ -5739,7 +5742,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    if (thr instanceof ThreadDeath) {
 +                        throw (ThreadDeath)thr;
 +                    }
-+                    LOGGER.fatal("Load callback for future await failed " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", thr);
++                    LOGGER.error("Load callback for future await failed " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "'", thr);
 +                    return;
 +                }
 +            } finally {
@@ -5751,11 +5754,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    public <T> void addTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
-+        this.distanceManager.addTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier);
++        this.distanceManager.addTicket(ticketType, chunkPos, ticketLevel, identifier);
 +    }
 +
 +    public <T> void removeTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
-+        this.distanceManager.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier);
++        this.distanceManager.removeTicket(ticketType, chunkPos, ticketLevel, identifier);
 +    }
 +
 +    void chunkLoadAccept(int chunkX, int chunkZ, ChunkAccess chunk, java.util.function.Consumer<ChunkAccess> consumer) {
@@ -5987,7 +5990,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end
 +
      // Add env and gen to constructor, WorldData -> WorldDataServer
-     public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey<Level> resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
+     public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey<Level> resourcekey, Holder<DimensionType> holder, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
          // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error
 diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@@ -6395,14 +6398,14 @@ diff --git a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java b
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java
 +++ b/src/main/java/net/minecraft/world/level/PathNavigationRegion.java
-@@ -0,0 +0,0 @@ import javax.annotation.Nullable;
- import net.minecraft.core.BlockPos;
+@@ -0,0 +0,0 @@ import net.minecraft.core.Holder;
+ import net.minecraft.core.Registry;
  import net.minecraft.core.SectionPos;
  import net.minecraft.util.profiling.ProfilerFiller;
 +import net.minecraft.server.level.ServerLevel;
  import net.minecraft.world.entity.Entity;
- import net.minecraft.world.level.block.Blocks;
- import net.minecraft.world.level.block.entity.BlockEntity;
+ import net.minecraft.world.level.biome.Biome;
+ import net.minecraft.world.level.biome.Biomes;
 @@ -0,0 +0,0 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter {
      private ChunkAccess getChunk(int chunkX, int chunkZ) {
          int i = chunkX - this.centerX;
@@ -6410,7 +6413,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        if (i >= 0 && i < this.chunks.length && j >= 0 && j < this.chunks[i].length) {
 +        if (i >= 0 && i < this.chunks.length && j >= 0 && j < this.chunks[i].length) { // Paper - if this changes, update getChunkIfLoaded below
              ChunkAccess chunkAccess = this.chunks[i][j];
-             return (ChunkAccess)(chunkAccess != null ? chunkAccess : new EmptyLevelChunk(this.level, new ChunkPos(chunkX, chunkZ)));
+             return (ChunkAccess)(chunkAccess != null ? chunkAccess : new EmptyLevelChunk(this.level, new ChunkPos(chunkX, chunkZ), this.plains.get()));
          } else {
 @@ -0,0 +0,0 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter {
          }
diff --git a/patches/server/Make-legacy-ping-handler-more-reliable.patch b/patches/server/Make-legacy-ping-handler-more-reliable.patch
index ce41bcd2af..8946529dbc 100644
--- a/patches/server/Make-legacy-ping-handler-more-reliable.patch
+++ b/patches/server/Make-legacy-ping-handler-more-reliable.patch
@@ -32,7 +32,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
 +++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
 @@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter {
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
      public static final int FAKE_PROTOCOL_VERSION = 127;
      private final ServerConnectionListener serverConnectionListener;
 +    private ByteBuf buf; // Paper
diff --git a/patches/server/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/patches/server/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch
index 80f0a273de..feb9b1c0d7 100644
--- a/patches/server/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch
+++ b/patches/server/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch
@@ -9,14 +9,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java
 +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
-         this.playerMap = new PlayerMap();
          this.entityMap = new Int2ObjectOpenHashMap();
          this.chunkTypeCache = new Long2ByteOpenHashMap();
+         this.chunkSaveCooldowns = new Long2LongOpenHashMap();
 -        this.unloadQueue = Queues.newConcurrentLinkedQueue();
-+        this.unloadQueue = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size()
          this.structureManager = structureManager;
++        this.unloadQueue = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size()
          Path path = session.getDimensionPath(world.dimension());
  
+         this.storageName = path.getFileName().toString();
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
          // Spigot start
          org.spigotmc.SlackActivityAccountant activityAccountant = this.level.getServer().slackActivityAccountant;
diff --git a/patches/server/Make-water-animal-spawn-height-configurable.patch b/patches/server/Make-water-animal-spawn-height-configurable.patch
index 31654bb0f4..fccab2f85e 100644
--- a/patches/server/Make-water-animal-spawn-height-configurable.patch
+++ b/patches/server/Make-water-animal-spawn-height-configurable.patch
@@ -45,6 +45,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        i = world.getMinecraftWorld().paperConfig.waterAnimalMaxSpawnHeight != null ? world.getMinecraftWorld().paperConfig.waterAnimalMaxSpawnHeight : i;
 +        j = world.getMinecraftWorld().paperConfig.waterAnimalMinSpawnHeight != null ? world.getMinecraftWorld().paperConfig.waterAnimalMinSpawnHeight : j;
 +        // Paper end
-         return world.getFluidState(pos.below()).is(FluidTags.WATER) && world.getBlockState(pos.above()).is(Blocks.WATER) && pos.getY() >= j && pos.getY() <= i;
+         return pos.getY() >= j && pos.getY() <= i && world.getFluidState(pos.below()).is(FluidTags.WATER) && world.getBlockState(pos.above()).is(Blocks.WATER);
      }
  }
diff --git a/patches/server/Move-range-check-for-block-placing-up.patch b/patches/server/Move-range-check-for-block-placing-up.patch
index 0f9adae598..13633feffc 100644
--- a/patches/server/Move-range-check-for-block-placing-up.patch
+++ b/patches/server/Move-range-check-for-block-placing-up.patch
@@ -26,26 +26,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public void handleUseItemOn(ServerboundUseItemOnPacket packet) {
          PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
+         BlockPos blockposition = movingobjectpositionblock.getBlockPos();
+         Vec3 vec3d1 = vec3d.subtract(Vec3.atCenterOf(blockposition));
  
-         this.player.resetLastActionTime();
-         int i = this.player.level.getMaxBuildHeight();
--        // CraftBukkit start
--        double distanceSqr = this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D);
--        if (distanceSqr > 100.0D) {
-+
 +        // Paper start - improve distance check
 +        final Vec3 clickedLocation = movingobjectpositionblock.getLocation();
 +        if (isOutsideOfReach(blockposition.getX() + 0.5D, blockposition.getY() + 0.5D, blockposition.getZ() + 0.5D)
 +            || !Double.isFinite(clickedLocation.x) || !Double.isFinite(clickedLocation.y) || !Double.isFinite(clickedLocation.z)
 +            || isOutsideOfReach(clickedLocation.x, clickedLocation.y, clickedLocation.z)) {
-             return;
-         }
--        // CraftBukkit end
++            return;
++        }
 +        // Paper end
- 
-         if (blockposition.getY() < i) {
--            if (this.awaitingPositionFromClient == null && distanceSqr < 64.0D && worldserver.mayInteract(this.player, blockposition)) { // CraftBukkit - reuse value
-+            if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract(this.player, blockposition)) { // CraftBukkit - reuse value // Paper - revert CB change
-                 this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706
-                 InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock);
++
+         if (this.player.level.getServer() != null && this.player.chunkPosition().getChessboardDistance(new ChunkPos(blockposition)) < this.player.level.spigotConfig.viewDistance) { // Spigot
+             double d0 = 1.0000001D;
  
diff --git a/patches/server/Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/patches/server/Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch
index 7f02bce21e..754d45a1df 100644
--- a/patches/server/Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch
+++ b/patches/server/Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch
@@ -55,20 +55,12 @@ diff --git a/src/main/java/net/minecraft/world/level/block/BushBlock.java b/src/
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/block/BushBlock.java
 +++ b/src/main/java/net/minecraft/world/level/block/BushBlock.java
-@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPos;
- import net.minecraft.core.Direction;
- import net.minecraft.tags.BlockTags;
- import net.minecraft.tags.Tag;
-+import net.minecraft.server.level.ServerLevel;
- import net.minecraft.world.level.BlockGetter;
- import net.minecraft.world.level.LevelAccessor;
- import net.minecraft.world.level.LevelReader;
 @@ -0,0 +0,0 @@ public class BushBlock extends Block {
      public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
          // CraftBukkit start
          if (!state.canSurvive(world, pos)) {
 -            if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) {
-+            if (!(world instanceof ServerLevel && ((ServerLevel) world).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper
++            if (!(world instanceof net.minecraft.server.level.ServerLevel && ((net.minecraft.server.level.ServerLevel) world).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper
                  return Blocks.AIR.defaultBlockState();
              }
          }
diff --git a/patches/server/Oprimise-map-impl-for-tracked-players.patch b/patches/server/Oprimise-map-impl-for-tracked-players.patch
index 067565502a..759217e582 100644
--- a/patches/server/Oprimise-map-impl-for-tracked-players.patch
+++ b/patches/server/Oprimise-map-impl-for-tracked-players.patch
@@ -10,8 +10,8 @@ diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/j
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java
 +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import org.apache.commons.lang3.mutable.MutableObject;
+ import org.slf4j.Logger;
  import org.bukkit.entity.Player;
  // CraftBukkit end
 +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; // Paper
diff --git a/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch b/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch
index 305277fb94..7f10504b90 100644
--- a/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch
+++ b/patches/server/Optimise-BlockSoil-nearby-water-lookup.patch
@@ -42,11 +42,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        }
  
 -            blockposition1 = (BlockPos) iterator.next();
--        } while (!world.getFluidState(blockposition1).is((Tag) FluidTags.WATER));
+-        } while (!world.getFluidState(blockposition1).is(FluidTags.WATER));
 -
 -        return true;
 +        return false;
-+        // Paper end - remove abstract block iteration
      }
  
      @Override
diff --git a/patches/server/Optimise-IEntityAccess-getPlayerByUUID.patch b/patches/server/Optimise-IEntityAccess-getPlayerByUUID.patch
index 23b4014629..09794d2f87 100644
--- a/patches/server/Optimise-IEntityAccess-getPlayerByUUID.patch
+++ b/patches/server/Optimise-IEntityAccess-getPlayerByUUID.patch
@@ -22,5 +22,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end
 +
      // Add env and gen to constructor, WorldData -> WorldDataServer
-     public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey<Level> resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
+     public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey<Level> resourcekey, Holder<DimensionType> holder, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
          // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error
diff --git a/patches/server/Optimise-WorldServer-notify.patch b/patches/server/Optimise-WorldServer-notify.patch
index ebc6c5272a..0390116cdc 100644
--- a/patches/server/Optimise-WorldServer-notify.patch
+++ b/patches/server/Optimise-WorldServer-notify.patch
@@ -226,7 +226,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        } else if (this.path != null && !this.path.isDone() && this.path.getNodeCount() != 0) { // Paper - diff on change - needed for isViableForPathRecalculationChecking()
              Node node = this.path.getEndNode();
              Vec3 vec3 = new Vec3(((double)node.x + this.mob.getX()) / 2.0D, ((double)node.y + this.mob.getY()) / 2.0D, ((double)node.z + this.mob.getZ()) / 2.0D);
-             return pos.closerThan(vec3, (double)(this.path.getNodeCount() - this.path.getNextNodeIndex()));
+             return pos.closerToCenterThan(vec3, (double)(this.path.getNodeCount() - this.path.getNextNodeIndex()));
 diff --git a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
@@ -324,7 +324,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                // Paper end
  
                  if (!this.currentSection.remove(this.entity)) {
-                     PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (moving to {})", this.entity, SectionPos.of(this.currentSectionKey), i);
+                     PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (moving to {})", new Object[]{this.entity, SectionPos.of(this.currentSectionKey), i});
 @@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
                  entitysection.add(this.entity);
                  this.currentSection = entitysection;
diff --git a/patches/server/Optimise-chunk-tick-iteration.patch b/patches/server/Optimise-chunk-tick-iteration.patch
index bc840e669f..ab1fa5c085 100644
--- a/patches/server/Optimise-chunk-tick-iteration.patch
+++ b/patches/server/Optimise-chunk-tick-iteration.patch
@@ -41,13 +41,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              }
  
 @@ -0,0 +0,0 @@ public class ChunkHolder {
-             int k = this.lightEngine.getMaxLightSection();
+                 int k = this.lightEngine.getMaxLightSection();
  
-             if (y >= j && y <= k) {
-+                this.addToBroadcastMap(); // Paper - optimise chunk tick iteration
-                 int l = y - j;
+                 if (y >= j && y <= k) {
++                    this.addToBroadcastMap(); // Paper - optimise chunk tick iteration
+                     int l = y - j;
  
-                 if (lightType == LightLayer.SKY) {
+                     if (lightType == LightLayer.SKY) {
 @@ -0,0 +0,0 @@ public class ChunkHolder {
          }
      }
@@ -85,10 +85,10 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/sr
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
 +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
- import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper
- import java.util.function.Function; // Paper
+@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana
+ import net.minecraft.world.level.storage.DimensionDataStorage;
+ import net.minecraft.world.level.storage.LevelData;
+ import net.minecraft.world.level.storage.LevelStorageSource;
 +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; // Paper
  
  public class ServerChunkCache extends ChunkSource {
@@ -144,8 +144,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                // Paper end - optimise chunk tick iteration
                  ChunkPos chunkcoordintpair = chunk1.getPos();
  
--                if (this.level.isPositionEntityTicking(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
-+                if (this.level.isPositionEntityTicking(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
+-                if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
++                if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
                      chunk1.incrementInhabitedTime(j);
 -                    if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning
 +                    if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning & optimise chunk tick iteration
diff --git a/patches/server/Optimise-collision-checking-in-player-move-packet-ha.patch b/patches/server/Optimise-collision-checking-in-player-move-packet-ha.patch
index 7198d70b80..96a791f311 100644
--- a/patches/server/Optimise-collision-checking-in-player-move-packet-ha.patch
+++ b/patches/server/Optimise-collision-checking-in-player-move-packet-ha.patch
@@ -18,29 +18,31 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
                  d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
                  d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; // Paper - diff on change, used for checking large move vectors above
-                 d8 = d5 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above
+@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
+                 boolean flag1 = entity.verticalCollisionBelow;
+ 
                  entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
 +                boolean didCollide = toX != entity.getX() || toY != entity.getY() || toZ != entity.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
                  double d11 = d7;
  
                  d6 = d3 - entity.getX();
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
-                 boolean flag1 = false;
+                 boolean flag2 = false;
  
                  if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
--                    flag1 = true;
-+                    flag1 = true; // Paper - diff on change, this should be moved wrongly
-                     ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", entity.getName().getString(), this.player.getName().getString(), Math.sqrt(d10));
+-                    flag2 = true;
++                    flag2 = true; // Paper - diff on change, this should be moved wrongly
+                     ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", new Object[]{entity.getName().getString(), this.player.getName().getString(), Math.sqrt(d10)});
                  }
                  Location curPos = this.getCraftPlayer().getLocation(); // Spigot
  
                  entity.absMoveTo(d3, d4, d5, f, f1);
                  this.player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
--                boolean flag2 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D));
--
--                if (flag && (flag1 || !flag2)) {
+-                boolean flag3 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D));
+ 
+-                if (flag && (flag2 || !flag3)) {
 +                // Paper start - optimise out extra getCubes
-+                boolean teleportBack = flag1; // violating this is always a fail
++                boolean teleportBack = flag2; // violating this is always a fail
 +                if (!teleportBack) {
 +                    // note: only call after setLocation, or else getBoundingBox is wrong
 +                    AABB newBox = entity.getBoundingBox();
@@ -105,7 +107,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                              d7 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
                              d8 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
-                             }
+                             boolean flag1 = this.player.verticalCollisionBelow;
  
                              this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9));
 +                            boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
@@ -113,20 +115,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                              // Paper start - prevent position desync
                              if (this.awaitingPositionFromClient != null) {
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
-                             boolean flag1 = false;
+                             boolean flag2 = false;
  
                              if (!this.player.isChangingDimension() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { // Spigot
--                                flag1 = true;
-+                                flag1 = true; // Paper - diff on change, this should be moved wrongly
+-                                flag2 = true;
++                                flag2 = true; // Paper - diff on change, this should be moved wrongly
                                  ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
                              }
  
                              this.player.absMoveTo(d0, d1, d2, f, f1);
--                            if (!this.player.noPhysics && !this.player.isSleeping() && (flag1 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb))) {
+-                            if (!this.player.noPhysics && !this.player.isSleeping() && (flag2 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb))) {
 +                            // Paper start - optimise out extra getCubes
 +                            // Original for reference:
-+                            // boolean teleportBack = flag1 && worldserver.getCubes(this.player, axisalignedbb) || (didCollide && this.a((IWorldReader) worldserver, axisalignedbb));
-+                            boolean teleportBack = flag1; // violating this is always a fail
++                            // boolean teleportBack = flag2 && worldserver.getCubes(this.player, axisalignedbb) || (didCollide && this.a((IWorldReader) worldserver, axisalignedbb));
++                            boolean teleportBack = flag2; // violating this is always a fail
 +                            if (!this.player.noPhysics && !this.player.isSleeping() && !teleportBack) {
 +                                AABB newBox = this.player.getBoundingBox();
 +                                if (didCollide || !axisalignedbb.equals(newBox)) {
diff --git a/patches/server/Optimise-general-POI-access.patch b/patches/server/Optimise-general-POI-access.patch
index 2585c7b9bf..5128cc1938 100644
--- a/patches/server/Optimise-general-POI-access.patch
+++ b/patches/server/Optimise-general-POI-access.patch
@@ -911,9 +911,9 @@ diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
 +++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import org.slf4j.Logger;
  public class PoiSection {
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
      private final Short2ObjectMap<PoiRecord> records = new Short2ObjectOpenHashMap<>();
 -    private final Map<PoiType, Set<PoiRecord>> byType = Maps.newHashMap();
 +    private final Map<PoiType, Set<PoiRecord>> byType = Maps.newHashMap(); public final Map<PoiType, Set<PoiRecord>> getData() { return this.byType; } // Paper - public accessor
diff --git a/patches/server/Optimise-nearby-player-lookups.patch b/patches/server/Optimise-nearby-player-lookups.patch
index 9c9fc76e42..acabff4702 100644
--- a/patches/server/Optimise-nearby-player-lookups.patch
+++ b/patches/server/Optimise-nearby-player-lookups.patch
@@ -191,7 +191,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end - optimise get nearest players for entity AI
  
      // Add env and gen to constructor, WorldData -> WorldDataServer
-     public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey<Level> resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
+     public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey<Level> resourcekey, Holder<DimensionType> holder, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
 @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
      }
  
@@ -230,7 +230,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/Level.java
 +++ b/src/main/java/net/minecraft/world/level/Level.java
 @@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
-         return ret;
+         return this.getChunkIfLoaded(chunkX, chunkZ) != null;
      }
      // Paper end
 +    // Paper start - optimise checkDespawn
@@ -297,8 +297,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +    // Paper end - optimise checkDespawn
  
-     protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, final DimensionType dimensionmanager, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor
-         this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
+     public abstract ResourceKey<LevelStem> getTypeKey();
+ 
 diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
@@ -316,8 +316,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) {
--        return squaredDistance <= 576.0D ? false : (world.getSharedSpawnPos().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || world.isPositionEntityTicking((BlockPos) pos));
-+        return squaredDistance <= 576.0D ? false : (world.getSharedSpawnPos().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || world.isPositionEntityTicking((BlockPos) pos)); // Paper - diff on change, copy into caller
+-        return squaredDistance <= 576.0D ? false : (world.getSharedSpawnPos().closerToCenterThan(new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || world.isNaturalSpawningAllowed((BlockPos) pos));
++        return squaredDistance <= 576.0D ? false : (world.getSharedSpawnPos().closerToCenterThan(new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || world.isNaturalSpawningAllowed((BlockPos) pos)); // Paper - diff on change, copy into caller
      }
  
      private static Boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { // Paper
diff --git a/patches/server/Optimise-non-flush-packet-sending.patch b/patches/server/Optimise-non-flush-packet-sending.patch
index fb74bc9207..4bd07ca88b 100644
--- a/patches/server/Optimise-non-flush-packet-sending.patch
+++ b/patches/server/Optimise-non-flush-packet-sending.patch
@@ -23,9 +23,9 @@ diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/network/Connection.java
 +++ b/src/main/java/net/minecraft/network/Connection.java
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
- import org.apache.logging.log4j.Marker;
- import org.apache.logging.log4j.MarkerManager;
+@@ -0,0 +0,0 @@ import org.slf4j.Logger;
+ import org.slf4j.Marker;
+ import org.slf4j.MarkerFactory;
  
 +
 +import io.netty.util.concurrent.AbstractEventExecutor; // Paper
diff --git a/patches/server/Optimise-random-block-ticking.patch b/patches/server/Optimise-random-block-ticking.patch
index 164c700293..cf131586b9 100644
--- a/patches/server/Optimise-random-block-ticking.patch
+++ b/patches/server/Optimise-random-block-ticking.patch
@@ -99,20 +99,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition);
                  boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper
 @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
-         }
  
          gameprofilerfiller.popPush("iceandsnow");
--        if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow
+         if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow
 -            blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.getBlockRandomPos(j, 0, k, 15));
 -            BlockPos blockposition1 = blockposition.below();
-+         if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking
 +            // Paper start - optimise chunk ticking
 +            this.getRandomBlockPosition(j, 0, k, 15, blockposition);
 +            int normalY = chunk.getHeight(Heightmap.Types.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15) + 1;
 +            int downY = normalY - 1;
 +            blockposition.setY(normalY);
 +            // Paper end
-             Biome biomebase = this.getBiome(blockposition);
+             Biome biomebase = (Biome) this.getBiome(blockposition).value();
  
 -            if (biomebase.shouldFreeze(this, blockposition1)) {
 -                org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.defaultBlockState(), null); // CraftBukkit
@@ -130,10 +128,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  }
  
 -                BlockState iblockdata = this.getBlockState(blockposition1);
-+                blockposition.setY(downY); // Paper
 +                BlockState iblockdata = this.getBlockState(blockposition); // Paper
-+                blockposition.setY(normalY); // Paper
-                 Biome.Precipitation biomebase_precipitation = this.getBiome(blockposition).getPrecipitation();
+                 Biome.Precipitation biomebase_precipitation = biomebase.getPrecipitation();
  
 -                if (biomebase_precipitation == Biome.Precipitation.RAIN && biomebase.coldEnoughToSnow(blockposition1)) {
 +                blockposition.setY(downY); // Paper
@@ -301,7 +297,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/Level.java
 +++ b/src/main/java/net/minecraft/world/level/Level.java
 @@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
-     public abstract TagContainer getTagManager();
+     public abstract RecipeManager getRecipeManager();
  
      public BlockPos getBlockRandomPos(int x, int y, int z, int l) {
 +        // Paper start - allow use of mutable pos
@@ -327,10 +323,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public class LevelChunkSection {
      private short tickingFluidCount;
      public final PalettedContainer<BlockState> states;
-     private final PalettedContainer<Biome> biomes;
+     private final PalettedContainer<Holder<Biome>> biomes;
 +    public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper
  
-     public LevelChunkSection(int chunkPos, PalettedContainer<BlockState> blockStateContainer, PalettedContainer<Biome> biomeContainer) {
+     public LevelChunkSection(int chunkPos, PalettedContainer<BlockState> blockStateContainer, PalettedContainer<Holder<Biome>> biomeContainer) {
          this.bottomBlockY = LevelChunkSection.getBottomBlockY(chunkPos);
 @@ -0,0 +0,0 @@ public class LevelChunkSection {
              --this.nonEmptyBlockCount;
@@ -356,37 +352,63 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      public void recalcBlockCounts() {
-+        // Paper start
+-        class a implements PalettedContainer.CountConsumer<BlockState> {
+-
+-            public int nonEmptyBlockCount;
+-            public int tickingBlockCount;
+-            public int tickingFluidCount;
+-
+-            a() {}
+-
+-            public void accept(BlockState iblockdata, int i) {
+-                FluidState fluid = iblockdata.getFluidState();
+-
+-                if (!iblockdata.isAir()) {
+-                    this.nonEmptyBlockCount += i;
+-                    if (iblockdata.isRandomlyTicking()) {
+-                        this.tickingBlockCount += i;
+-                    }
++        // Paper start - unfuck this
 +        this.tickingList.clear();
-+        // Paper end
-         this.nonEmptyBlockCount = 0;
-         this.tickingBlockCount = 0;
-         this.tickingFluidCount = 0;
--        this.states.count((iblockdata, i) -> {
-+        this.states.forEachLocation((iblockdata, i) -> { // Paper
-             FluidState fluid = iblockdata.getFluidState();
- 
-             if (!iblockdata.isAir()) {
--                this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i);
-+                this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); // Paper
-                 if (iblockdata.isRandomlyTicking()) {
--                    this.tickingBlockCount = (short) (this.tickingBlockCount + i);
-+                    // Paper start
++        this.nonEmptyBlockCount = 0;
++        this.tickingBlockCount = 0;
++        this.tickingFluidCount = 0;
++        this.states.forEachLocation((BlockState iblockdata, int i) -> {
++            FluidState fluid = iblockdata.getFluidState();
++
++            if (!iblockdata.isAir()) {
++                this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1);
++                if (iblockdata.isRandomlyTicking()) {
 +                    this.tickingBlockCount = (short)(this.tickingBlockCount + 1);
 +                    this.tickingList.add(i, iblockdata);
-+                    // Paper end
                  }
-             }
++            }
  
-             if (!fluid.isEmpty()) {
--                this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i);
-+                this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); // Paper
-                 if (fluid.isRandomlyTicking()) {
--                    this.tickingFluidCount = (short) (this.tickingFluidCount + i);
-+                    this.tickingFluidCount = (short) (this.tickingFluidCount + 1); // Paper
+-                if (!fluid.isEmpty()) {
+-                    this.nonEmptyBlockCount += i;
+-                    if (fluid.isRandomlyTicking()) {
+-                        this.tickingFluidCount += i;
+-                    }
++            if (!fluid.isEmpty()) {
++                this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1);
++                if (fluid.isRandomlyTicking()) {
++                    this.tickingFluidCount = (short) (this.tickingFluidCount + 1);
                  }
+-
              }
+-        }
  
+-        a a0 = new a();
+-
+-        this.states.count(a0);
+-        this.nonEmptyBlockCount = (short) a0.nonEmptyBlockCount;
+-        this.tickingBlockCount = (short) a0.tickingBlockCount;
+-        this.tickingFluidCount = (short) a0.tickingFluidCount;
++        });
++        // Paper end
+     }
+ 
+     public PalettedContainer<BlockState> getStates() {
 diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
diff --git a/patches/server/Optimize-Bit-Operations-by-inlining.patch b/patches/server/Optimize-Bit-Operations-by-inlining.patch
index 95c664cc4c..87ba1931d5 100644
--- a/patches/server/Optimize-Bit-Operations-by-inlining.patch
+++ b/patches/server/Optimize-Bit-Operations-by-inlining.patch
@@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/core/BlockPos.java
 @@ -0,0 +0,0 @@ public class BlockPos extends Vec3i {
      }).stable();
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
      public static final BlockPos ZERO = new BlockPos(0, 0, 0);
 -    private static final int PACKED_X_LENGTH = 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000));
 -    private static final int PACKED_Z_LENGTH = PACKED_X_LENGTH;
diff --git a/patches/server/Optimize-Collision-to-not-load-chunks.patch b/patches/server/Optimize-Collision-to-not-load-chunks.patch
index 88b44522cc..a5d252617f 100644
--- a/patches/server/Optimize-Collision-to-not-load-chunks.patch
+++ b/patches/server/Optimize-Collision-to-not-load-chunks.patch
@@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          // CraftBukkit end
  
 +        worldserver1.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper
-         while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) {
+         while (avoidSuffocation && !worldserver1.noCollision((Entity) entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) {
              entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ());
          }
 diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
diff --git a/patches/server/Optimize-MappedRegistry.patch b/patches/server/Optimize-MappedRegistry.patch
index cc2d65e038..2dcfce270c 100644
--- a/patches/server/Optimize-MappedRegistry.patch
+++ b/patches/server/Optimize-MappedRegistry.patch
@@ -11,30 +11,30 @@ diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/jav
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/core/MappedRegistry.java
 +++ b/src/main/java/net/minecraft/core/MappedRegistry.java
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
- 
+@@ -0,0 +0,0 @@ import org.slf4j.Logger;
  public class MappedRegistry<T> extends WritableRegistry<T> {
-     protected static final Logger LOGGER = LogManager.getLogger();
--    private final ObjectList<T> byId = new ObjectArrayList<>(256);
+     private static final Logger LOGGER = LogUtils.getLogger();
+     private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256);
 -    private final Object2IntMap<T> toId = Util.make(new Object2IntOpenCustomHashMap<>(Util.identityStrategy()), (object2IntOpenCustomHashMap) -> {
 -        object2IntOpenCustomHashMap.defaultReturnValue(-1);
 -    });
--    private final BiMap<ResourceLocation, T> storage = HashBiMap.create();
--    private final BiMap<ResourceKey<T>, T> keyStorage = HashBiMap.create();
--    private final Map<T, Lifecycle> lifecycles = Maps.newIdentityHashMap();
-+    private final ObjectList<T> byId = new ObjectArrayList(256);
+-    private final Map<ResourceLocation, Holder.Reference<T>> byLocation = new HashMap<>();
+-    private final Map<ResourceKey<T>, Holder.Reference<T>> byKey = new HashMap<>();
+-    private final Map<T, Holder.Reference<T>> byValue = new IdentityHashMap<>();
+-    private final Map<T, Lifecycle> lifecycles = new IdentityHashMap<>();
 +    private final it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap<T> toId = new it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap<T>(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map
-+    private final BiMap<ResourceLocation, T> storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions
-+    private final BiMap<ResourceKey<T>, T> keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions
-+    private final Map<T, Lifecycle> lifecycles = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions
++    private final Map<ResourceLocation, Holder.Reference<T>> byLocation = new HashMap<>(2048); // Paper - use bigger expected size to reduce collisions
++    private final Map<ResourceKey<T>, Holder.Reference<T>> byKey = new HashMap<>(2048); // Paper - use bigger expected size to reduce collisions
++    private final Map<T, Holder.Reference<T>> byValue = new IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions
++    private final Map<T, Lifecycle> lifecycles = new IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions
      private Lifecycle elementsLifecycle;
-     @Nullable
-     protected Object[] randomCache;
+     private volatile Map<TagKey<T>, HolderSet.Named<T>> tags = new IdentityHashMap<>();
+     private boolean frozen;
 @@ -0,0 +0,0 @@ public class MappedRegistry<T> extends WritableRegistry<T> {
-     public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle) {
-         super(key, lifecycle);
-         this.elementsLifecycle = lifecycle;
+             this.intrusiveHolderCache = new IdentityHashMap<>();
+         }
+ 
 +        this.toId.defaultReturnValue(-1); // Paper
      }
  
-     public static <T> MapCodec<MappedRegistry.RegistryEntry<T>> withNameAndId(ResourceKey<? extends Registry<T>> key, MapCodec<T> entryCodec) {
+     private List<Holder.Reference<T>> holdersInOrder() {
diff --git a/patches/server/Optimize-NetworkManager-Exception-Handling.patch b/patches/server/Optimize-NetworkManager-Exception-Handling.patch
index 8aa72b112a..7decb372d2 100644
--- a/patches/server/Optimize-NetworkManager-Exception-Handling.patch
+++ b/patches/server/Optimize-NetworkManager-Exception-Handling.patch
@@ -45,35 +45,25 @@ diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
 +++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
-@@ -0,0 +0,0 @@
- package net.minecraft.network.protocol;
- 
-+import net.minecraft.network.Connection;
- import net.minecraft.network.PacketListener;
-+import net.minecraft.network.chat.TextComponent;
-+import net.minecraft.network.protocol.game.ClientboundDisconnectPacket;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
- import co.aikar.timings.MinecraftTimings; // Paper
 @@ -0,0 +0,0 @@ public class PacketUtils {
-                     try (Timing ignored = timing.startTiming()) { // Paper - timings
-                     packet.handle(listener);
-                     } // Paper - timings
-+                    // Paper start
-+                    catch (Exception e) {
-+                        Connection networkmanager = listener.getConnection();
+                     try (co.aikar.timings.Timing ignored = timing.startTiming()) { // Paper - timings
+                         packet.handle(listener);
+                     } catch (Exception exception) {
+-                        if (listener.shouldPropagateHandlingExceptions()) {
+-                            throw exception;
++                        net.minecraft.network.Connection networkmanager = listener.getConnection();
 +                        if (networkmanager.getPlayer() != null) {
-+                            LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), networkmanager.getRemoteAddress(), e);
++                            LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), networkmanager.getRemoteAddress(), exception);
 +                        } else {
-+                            LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getRemoteAddress(), e);
-+                        }
-+                        TextComponent error = new TextComponent("Packet processing error");
-+                        networkmanager.send(new ClientboundDisconnectPacket(error), (future) -> {
++                            LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getRemoteAddress(), exception);
+                         }
+-
+-                        PacketUtils.LOGGER.error("Failed to handle packet {}, suppressing error", packet, exception);
++                        net.minecraft.network.chat.TextComponent error = new net.minecraft.network.chat.TextComponent("Packet processing error");
++                        networkmanager.send(new net.minecraft.network.protocol.game.ClientboundDisconnectPacket(error), (future) -> {
 +                            networkmanager.disconnect(error);
 +                        });
 +                        networkmanager.setReadOnly();
-+                    }
-+                    // Paper end
+                     }
                  } else {
                      PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet);
-                 }
diff --git a/patches/server/Optimize-ServerLevels-chunk-level-checking-methods.patch b/patches/server/Optimize-ServerLevels-chunk-level-checking-methods.patch
index e2c0a730cb..c00e5642b2 100644
--- a/patches/server/Optimize-ServerLevels-chunk-level-checking-methods.patch
+++ b/patches/server/Optimize-ServerLevels-chunk-level-checking-methods.patch
@@ -23,13 +23,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      public boolean isPositionEntityTicking(BlockPos pos) {
--        return this.entityManager.isPositionTicking(pos);
-+        return this.entityManager.isPositionTicking(ChunkPos.asLong(pos)); // Paper
+-        return this.entityManager.canPositionTick(pos) && this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(ChunkPos.asLong(pos));
++        return this.entityManager.canPositionTick(ChunkPos.asLong(pos)) && this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(ChunkPos.asLong(pos)); // Paper
      }
  
-     public boolean isPositionEntityTicking(ChunkPos pos) {
--        return this.entityManager.isPositionTicking(pos);
-+        return this.entityManager.isPositionTicking(pos.toLong()); // Paper
+     public boolean isNaturalSpawningAllowed(BlockPos pos) {
+-        return this.entityManager.canPositionTick(pos);
++        return this.entityManager.canPositionTick(ChunkPos.asLong(pos)); // Paper
+     }
+ 
+     public boolean isNaturalSpawningAllowed(ChunkPos pos) {
+-        return this.entityManager.canPositionTick(pos);
++        return this.entityManager.canPositionTick(pos.toLong()); // Paper
      }
  
      private final class EntityCallbacks implements LevelCallback<Entity> {
@@ -55,10 +60,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          return this.entityGetter;
      }
 +    // Paper start
-+    public final boolean isPositionTicking(long position) {
++    public final boolean canPositionTick(long position) {
 +        return this.chunkVisibility.get(position).isTicking();
 +    }
 +    // Paper end
  
-     public boolean isPositionTicking(BlockPos pos) {
+     public boolean canPositionTick(BlockPos pos) {
          return ((Visibility) this.chunkVisibility.get(ChunkPos.asLong(pos))).isTicking();
diff --git a/patches/server/Optimize-Util-sequence.patch b/patches/server/Optimize-Util-sequence.patch
deleted file mode 100644
index 9bb08162b3..0000000000
--- a/patches/server/Optimize-Util-sequence.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: IzzelAliz <csh2001331@126.com>
-Date: Tue, 14 Dec 2021 12:43:03 +0800
-Subject: [PATCH] Optimize Util#sequence
-
-Original method allocates O(n^2) memory on n-size list.
-
-diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/Util.java
-+++ b/src/main/java/net/minecraft/Util.java
-@@ -0,0 +0,0 @@ public class Util {
-         return (Strategy<K>) Util.IdentityStrategy.INSTANCE; // Paper - decompile fix
-     }
- 
-+    private static final CompletableFuture<?>[] EMPTY_FUTURE = new CompletableFuture[0]; // Paper
-     public static <V> CompletableFuture<List<V>> sequence(List<? extends CompletableFuture<? extends V>> futures) {
--        return futures.stream().reduce(CompletableFuture.completedFuture(Lists.newArrayList()), (completableFuture, completableFuture2) -> {
--            return completableFuture2.thenCombine(completableFuture, (object, list) -> {
--                List<V> list2 = Lists.newArrayListWithCapacity(list.size() + 1);
--                list2.addAll(list);
--                list2.add(object);
--                return list2;
--            });
--        }, (completableFuture, completableFuture2) -> {
--            return completableFuture.thenCombine(completableFuture2, (list, list2) -> {
--                List<V> list3 = Lists.newArrayListWithCapacity(list.size() + list2.size());
--                list3.addAll(list);
--                list3.addAll(list2);
--                return list3;
-+        // Paper start - optimize
-+        return CompletableFuture.allOf(futures.toArray(EMPTY_FUTURE))
-+            .thenApply(v -> {
-+                List<V> list = Lists.newArrayListWithCapacity(futures.size());
-+                for (CompletableFuture<? extends V> future : futures) {
-+                    list.add(future.join());
-+                }
-+                return list;
-             });
--        });
-+        // Paper end
-     }
- 
-     public static <V> CompletableFuture<List<V>> sequenceFailFast(List<? extends CompletableFuture<? extends V>> futures) {
diff --git a/patches/server/Optimize-anyPlayerCloseEnoughForSpawning-to-use-dist.patch b/patches/server/Optimize-anyPlayerCloseEnoughForSpawning-to-use-dist.patch
index 8df66c48cd..9a9a7ca2b7 100644
--- a/patches/server/Optimize-anyPlayerCloseEnoughForSpawning-to-use-dist.patch
+++ b/patches/server/Optimize-anyPlayerCloseEnoughForSpawning-to-use-dist.patch
@@ -40,7 +40,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        this.onChunkAdd(); // Paper - optimise anyPlayerCloseEnoughForSpawning
      }
  
-     // CraftBukkit start
+     // Paper start
 diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -348,8 +348,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  LevelChunk chunk1 = chunkproviderserver_a.chunk;
                  ChunkPos chunkcoordintpair = chunk1.getPos();
  
--                if (this.level.isPositionEntityTicking(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) {
-+                if (this.level.isPositionEntityTicking(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
+-                if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) {
++                if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
                      chunk1.incrementInhabitedTime(j);
 -                    if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot
 +                    if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning
diff --git a/patches/server/Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch b/patches/server/Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch
index fb31aad9a8..8955dc9959 100644
--- a/patches/server/Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch
+++ b/patches/server/Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch
@@ -58,7 +58,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
 +++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
 @@ -0,0 +0,0 @@ public class EmptyLevelChunk extends LevelChunk {
-         super(world, pos);
+         this.biome = holder;
      }
  
 +    // Paper start
diff --git a/patches/server/Option-to-have-default-CustomSpawners-in-custom-worl.patch b/patches/server/Option-to-have-default-CustomSpawners-in-custom-worl.patch
index 60036cb62d..a4fd7ab9ba 100644
--- a/patches/server/Option-to-have-default-CustomSpawners-in-custom-worl.patch
+++ b/patches/server/Option-to-have-default-CustomSpawners-in-custom-worl.patch
@@ -31,15 +31,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  this.commandStorage = new CommandStorage(worldpersistentdata);
              } else {
                  ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11);
--                world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, dimensionmanager, worldloadlistener, chunkgenerator, flag, j, ImmutableList.of(), true, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider);
+-                world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, holder, worldloadlistener, chunkgenerator, flag, j, ImmutableList.of(), true, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider);
 +                // Paper start - option to use the dimension_type to check if spawners should be added. I imagine mojang will add some datapack-y way of managing this in the future.
 +                final List<CustomSpawner> spawners;
-+                if (com.destroystokyo.paper.PaperConfig.useDimensionTypeForCustomSpawners && this.registryHolder.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY).getResourceKey(dimensionmanager).orElseThrow() == DimensionType.OVERWORLD_LOCATION) {
++                if (com.destroystokyo.paper.PaperConfig.useDimensionTypeForCustomSpawners && this.registryHolder.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY).getResourceKey(holder.value()).orElseThrow() == DimensionType.OVERWORLD_LOCATION) {
 +                    spawners = list;
 +                } else {
 +                    spawners = Collections.emptyList();
 +                }
-+                world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, dimensionmanager, worldloadlistener, chunkgenerator, flag, j, spawners, true, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider);
++                world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, holder, worldloadlistener, chunkgenerator, flag, j, spawners, true, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider);
 +                // Paper end
              }
  
diff --git a/patches/server/Paper-config-files.patch b/patches/server/Paper-config-files.patch
index d6abc3866b..469c72ccb9 100644
--- a/patches/server/Paper-config-files.patch
+++ b/patches/server/Paper-config-files.patch
@@ -707,7 +707,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      private org.spigotmc.TickLimiter entityLimiter;
 @@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
  
-     protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, final DimensionType dimensionmanager, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) {
+     protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) {
          this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
 +        this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper
          this.generator = gen;
diff --git a/patches/server/Per-Player-View-Distance-API-placeholders.patch b/patches/server/Per-Player-View-Distance-API-placeholders.patch
index 8652b8ebf3..f706439622 100644
--- a/patches/server/Per-Player-View-Distance-API-placeholders.patch
+++ b/patches/server/Per-Player-View-Distance-API-placeholders.patch
@@ -10,15 +10,13 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/ma
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
 +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-@@ -0,0 +0,0 @@ import org.bukkit.inventory.MainHand;
- 
- public class ServerPlayer extends Player {
- 
-+    public final int getViewDistance() { return this.getLevel().getChunkSource().chunkMap.viewDistance - 1; } // Paper - placeholder
+@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
+         return (CraftPlayer) super.getBukkitEntity();
+     }
+     // CraftBukkit end
 +
-     private static final Logger LOGGER = LogManager.getLogger();
-     private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
-     private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
++    public final int getViewDistance() { return this.getLevel().getChunkSource().chunkMap.viewDistance - 1; } // Paper - placeholder
+ }
 diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
diff --git a/patches/server/Player.setPlayerProfile-API.patch b/patches/server/Player.setPlayerProfile-API.patch
index 1c504b4340..551e95e669 100644
--- a/patches/server/Player.setPlayerProfile-API.patch
+++ b/patches/server/Player.setPlayerProfile-API.patch
@@ -12,19 +12,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
                          final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server;
  
-                             // Paper start
--                            PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName);
-+                            PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile);
-                             AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile);
+                         // Paper start
+-                        com.destroystokyo.paper.profile.PlayerProfile profile = org.bukkit.Bukkit.createProfile(uniqueId, playerName);
++                        com.destroystokyo.paper.profile.PlayerProfile profile = com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile);
+                         AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile);
                          server.getPluginManager().callEvent(asyncEvent);
-                             profile = asyncEvent.getPlayerProfile();
--                            profile.complete();
--                            gameProfile = CraftPlayerProfile.asAuthlibCopy(profile);
-+                            profile.complete(true);
-+                            ServerLoginPacketListenerImpl.this.gameProfile = CraftPlayerProfile.asAuthlib(profile);
-                             playerName = gameProfile.getName();
-                             uniqueId = gameProfile.getId();
-                             // Paper end
+                         profile = asyncEvent.getPlayerProfile();
+-                        profile.complete();
++                        profile.complete(true); // Paper - setPlayerProfileAPI
+                         gameProfile = com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile);
+                         playerName = gameProfile.getName();
+                         uniqueId = gameProfile.getId();
 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
diff --git a/patches/server/PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server/PortalCreateEvent-needs-to-know-its-entity.patch
index cf874ce9c9..b9442b9409 100644
--- a/patches/server/PortalCreateEvent-needs-to-know-its-entity.patch
+++ b/patches/server/PortalCreateEvent-needs-to-know-its-entity.patch
@@ -107,8 +107,8 @@ diff --git a/src/main/java/net/minecraft/world/level/portal/PortalShape.java b/s
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/portal/PortalShape.java
 +++ b/src/main/java/net/minecraft/world/level/portal/PortalShape.java
-@@ -0,0 +0,0 @@ import net.minecraft.tags.BlockTags;
- import net.minecraft.tags.Tag;
+@@ -0,0 +0,0 @@ import net.minecraft.server.level.ServerLevel;
+ import net.minecraft.tags.BlockTags;
  import net.minecraft.util.Mth;
  import net.minecraft.world.entity.EntityDimensions;
 +import net.minecraft.world.item.context.UseOnContext;
diff --git a/patches/server/PreCreatureSpawnEvent.patch b/patches/server/PreCreatureSpawnEvent.patch
index e957c69912..cd64f7bffd 100644
--- a/patches/server/PreCreatureSpawnEvent.patch
+++ b/patches/server/PreCreatureSpawnEvent.patch
@@ -117,7 +117,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
                                          if (entityinsentient == null) {
 @@ -0,0 +0,0 @@ public final class NaturalSpawner {
-         return squaredDistance <= 576.0D ? false : (world.getSharedSpawnPos().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || world.isPositionEntityTicking((BlockPos) pos));
+         return squaredDistance <= 576.0D ? false : (world.getSharedSpawnPos().closerToCenterThan(new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || world.isNaturalSpawningAllowed((BlockPos) pos));
      }
  
 -    private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) {
diff --git a/patches/server/Prevent-softlocked-end-exit-portal-generation.patch b/patches/server/Prevent-softlocked-end-exit-portal-generation.patch
index 2cd9ed4a0b..d3ab79c1ca 100644
--- a/patches/server/Prevent-softlocked-end-exit-portal-generation.patch
+++ b/patches/server/Prevent-softlocked-end-exit-portal-generation.patch
@@ -17,7 +17,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            this.portalLocation = this.portalLocation.atY(this.level.getMinBuildHeight() + 1);
 +        }
 +        // Paper end
-+
-         endPodiumFeature.configured(FeatureConfiguration.NONE).place(this.level, this.level.getChunkSource().getGenerator(), new Random(), this.portalLocation);
+         endPodiumFeature.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), new Random(), this.portalLocation);
      }
  
diff --git a/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch
index d2ff17dfe7..333f3f4150 100644
--- a/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch
+++ b/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch
@@ -15,6 +15,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -                BlockState blockState = world.getBlockState(globalPos.pos());
 +                BlockState blockState = world.getBlockStateIfLoaded(globalPos.pos()); // Paper
 +                if (blockState == null) { return false; } // Paper
-                 return globalPos.pos().closerThan(entity.position(), 2.0D) && blockState.is(BlockTags.BEDS) && !blockState.getValue(BedBlock.OCCUPIED);
+                 return globalPos.pos().closerToCenterThan(entity.position(), 2.0D) && blockState.is(BlockTags.BEDS) && !blockState.getValue(BedBlock.OCCUPIED);
              }
          }
diff --git a/patches/server/Remove-some-streams-from-structures.patch b/patches/server/Remove-some-streams-from-structures.patch
index e4c305d737..885a6c5122 100644
--- a/patches/server/Remove-some-streams-from-structures.patch
+++ b/patches/server/Remove-some-streams-from-structures.patch
@@ -9,29 +9,33 @@ diff --git a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java b/
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java
 +++ b/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java
-@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.feature.structures.StructureTemplatePo
+@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.feature.NoiseEffect;
  import net.minecraft.world.level.levelgen.structure.BoundingBox;
  import net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece;
  import net.minecraft.world.level.levelgen.structure.StructurePiece;
 +import net.minecraft.world.level.levelgen.structure.StructureStart;
+ import net.minecraft.world.level.levelgen.structure.pools.JigsawJunction;
+ import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool;
  
- public class Beardifier implements NoiseChunk.NoiseFiller {
-     public static final int BEARD_KERNEL_RADIUS = 12;
-@@ -0,0 +0,0 @@ public class Beardifier implements NoiseChunk.NoiseFiller {
+@@ -0,0 +0,0 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker {
+         int j = chunkPos.getMinBlockZ();
+         this.junctions = new ObjectArrayList<>(32);
          this.rigids = new ObjectArrayList<>(10);
- 
-         for(StructureFeature<?> structureFeature : StructureFeature.NOISE_AFFECTING_FEATURES) {
--            structureAccessor.startsForFeature(SectionPos.bottomOf(chunk), structureFeature).forEach((start) -> {
-+            for (StructureStart<?> start : structureAccessor.startsForFeature(SectionPos.bottomOf(chunk), structureFeature)) { // Paper - remove streams
-                 for(StructurePiece structurePiece : start.getPieces()) {
-                     if (structurePiece.isCloseToChunk(chunkPos, 12)) {
-                         if (structurePiece instanceof PoolElementStructurePiece) {
-@@ -0,0 +0,0 @@ public class Beardifier implements NoiseChunk.NoiseFiller {
-                     }
+-        structureAccessor.startsForFeature(SectionPos.bottomOf(chunk), (configuredStructureFeature) -> {
++        // Paper start - replace for each
++        for (StructureStart start : structureAccessor.startsForFeature(SectionPos.bottomOf(chunk), (configuredStructureFeature) -> {
+             return configuredStructureFeature.adaptNoise;
+-        }).forEach((start) -> {
++        })) { // Paper end
+             for(StructurePiece structurePiece : start.getPieces()) {
+                 if (structurePiece.isCloseToChunk(chunkPos, 12)) {
+                     if (structurePiece instanceof PoolElementStructurePiece) {
+@@ -0,0 +0,0 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker {
                  }
+             }
  
--            });
-+            } // Paper
-         }
- 
+-        });
++        } // Paper
          this.pieceIterator = this.rigids.iterator();
+         this.junctionIterator = this.junctions.iterator();
+     }
diff --git a/patches/server/Replace-player-chunk-loader-system.patch b/patches/server/Replace-player-chunk-loader-system.patch
index 632940f030..a0da4693e5 100644
--- a/patches/server/Replace-player-chunk-loader-system.patch
+++ b/patches/server/Replace-player-chunk-loader-system.patch
@@ -1338,11 +1338,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      public void sectionLightChanged(LightLayer lightType, int y) {
--        LevelChunk chunk = this.getTickingChunk();
-+        LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance
+-        LevelChunk chunk = this.getFullChunk();
++        ChunkAccess chunk = this.getAvailableChunkNow(); // Paper - no-tick view distance
  
          if (chunk != null) {
              chunk.setUnsaved(true);
+-            LevelChunk chunk1 = this.getTickingChunk();
++            LevelChunk chunk1 = this.getSendingChunk(); // Paper - no-tick view distance
+ 
+             if (chunk1 != null) {
+                 int j = this.lightEngine.getMinLightSection();
 @@ -0,0 +0,0 @@ public class ChunkHolder {
      }
  
@@ -1672,23 +1677,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          boolean flag = i != 0;
  
 @@ -0,0 +0,0 @@ public abstract class DistanceManager {
-         long j = pos.toLong();
+         long j = chunkcoordintpair.toLong();
  
-         this.addTicket(j, ticket);
+         boolean added = this.addTicket(j, ticket); // CraftBukkit
 -        this.tickingTicketsTracker.addTicket(j, ticket);
 +        //this.tickingTicketsTracker.addTicket(j, ticket); // Paper - no longer used
+         return added; // CraftBukkit
      }
  
-     public <T> void removeRegionTicket(TicketType<T> type, ChunkPos pos, int radius, T argument) {
 @@ -0,0 +0,0 @@ public abstract class DistanceManager {
-         long j = pos.toLong();
+         long j = chunkcoordintpair.toLong();
  
-         this.removeTicket(j, ticket);
+         boolean removed = this.removeTicket(j, ticket); // CraftBukkit
 -        this.tickingTicketsTracker.removeTicket(j, ticket);
 +        //this.tickingTicketsTracker.removeTicket(j, ticket); // Paper - no longer used
+         return removed; // CraftBukkit
      }
  
-     private SortedArraySet<Ticket<?>> getTickets(long position) {
 @@ -0,0 +0,0 @@ public abstract class DistanceManager {
  
          if (forced) {
@@ -1778,8 +1783,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -    }
 +    // Paper - replace player chunk loader
  
-     // CraftBukkit start
-     public <T> void removeAllTicketsFor(TicketType<T> ticketType, int ticketLevel, T ticketIdentifier) {
+     public void removeTicketsOnClosing() {
+         ImmutableSet<TicketType<?>> immutableset = ImmutableSet.of(TicketType.UNKNOWN, TicketType.POST_TELEPORT, TicketType.LIGHT);
 @@ -0,0 +0,0 @@ public abstract class DistanceManager {
          }
      }
@@ -1821,26 +1826,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      public void save(boolean flush) {
 @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
-         this.level.timings.doChunkMap.stopTiming(); // Spigot
          this.level.getProfiler().popPush("chunks");
-         this.level.timings.chunks.startTiming(); // Paper - timings
-+        this.chunkMap.playerChunkManager.tick(); // Paper - this is mostly is to account for view distance changes
-         this.tickChunks();
-         this.level.timings.chunks.stopTiming(); // Paper - timings
-         this.level.timings.doChunkUnload.startTiming(); // Spigot
+         if (tickChunks) {
+             this.level.timings.chunks.startTiming(); // Paper - timings
++            this.chunkMap.playerChunkManager.tick(); // Paper - this is mostly is to account for view distance changes
+             this.tickChunks();
+             this.level.timings.chunks.stopTiming(); // Paper - timings
+         }
 @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
                  // Paper end - optimise chunk tick iteration
                  ChunkPos chunkcoordintpair = chunk1.getPos();
  
--                if (this.level.isPositionEntityTicking(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
-+                if ((true || this.level.isPositionEntityTicking(chunkcoordintpair)) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning // Paper - replace player chunk loader system
+-                if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
++                if ((true || this.level.isNaturalSpawningAllowed(chunkcoordintpair)) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning // Paper - replace player chunk loader system
                      chunk1.incrementInhabitedTime(j);
                      if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning & optimise chunk tick iteration
                          NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1);
                      }
  
 -                    if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) {
-+                    if ((true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong()))) { // Paper - replace player chunk loader system
++                    if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - replace player chunk loader system
                          this.level.tickChunk(chunk1, k);
                          if ((chunksTicked++ & 1) == 0) net.minecraft.server.MinecraftServer.getServer().executeMidTickTasks(); // Paper
                      }
@@ -1890,15 +1895,13 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/ma
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
 +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-@@ -0,0 +0,0 @@ import org.bukkit.inventory.MainHand;
- 
- public class ServerPlayer extends Player {
+@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
+     }
+     // CraftBukkit end
  
 -    public final int getViewDistance() { return this.getLevel().getChunkSource().chunkMap.viewDistance - 1; } // Paper - placeholder
 +    public final int getViewDistance() { throw new UnsupportedOperationException("Use PlayerChunkLoader"); } // Paper - placeholder
- 
-     private static final Logger LOGGER = LogManager.getLogger();
-     public long lastSave = MinecraftServer.currentTick; // Paper
+ }
 diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -1907,15 +1910,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO);
  
          // Spigot - view distance
--        playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionType(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, worldserver1.spigotConfig.simulationDistance, flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat()));
-+        playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionType(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), this.getMaxPlayers(), worldserver1.getChunkSource().chunkMap.playerChunkManager.getTargetSendDistance(), worldserver1.getChunkSource().chunkMap.playerChunkManager.getTargetTickViewDistance(), flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat())); // Paper - replace old player chunk management
+-        playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionTypeRegistration(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, worldserver1.spigotConfig.simulationDistance, flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat()));
++        playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionTypeRegistration(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), this.getMaxPlayers(), worldserver1.getChunkSource().chunkMap.playerChunkManager.getTargetSendDistance(), worldserver1.getChunkSource().chunkMap.playerChunkManager.getTargetTickViewDistance(), flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat())); // Paper - replace old player chunk management
          player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
          playerconnection.send(new ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.BRAND, (new FriendlyByteBuf(Unpooled.buffer())).writeUtf(this.getServer().getServerModName())));
          playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
 @@ -0,0 +0,0 @@ public abstract class PlayerList {
          // CraftBukkit start
          LevelData worlddata = worldserver1.getLevelData();
-         entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionType(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), flag));
+         entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionTypeRegistration(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), flag));
 -        entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.spigotConfig.viewDistance)); // Spigot
 -        entityplayer1.connection.send(new ClientboundSetSimulationDistancePacket(worldserver1.spigotConfig.simulationDistance)); // Spigot
 +        entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.getChunkSource().chunkMap.playerChunkManager.getTargetSendDistance())); // Spigot // Paper - replace old player chunk management
diff --git a/patches/server/Replace-ticket-level-propagator.patch b/patches/server/Replace-ticket-level-propagator.patch
index af61ad3274..74b7b898dd 100644
--- a/patches/server/Replace-ticket-level-propagator.patch
+++ b/patches/server/Replace-ticket-level-propagator.patch
@@ -18,14 +18,14 @@ diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java
 +++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
-@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.LevelChunk;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.ChunkStatus;
+ import net.minecraft.world.level.chunk.LevelChunk;
+ import org.slf4j.Logger;
  
 +import it.unimi.dsi.fastutil.longs.Long2IntLinkedOpenHashMap; // Paper
  public abstract class DistanceManager {
  
-     static final Logger LOGGER = LogManager.getLogger();
+     static final Logger LOGGER = LogUtils.getLogger();
 @@ -0,0 +0,0 @@ public abstract class DistanceManager {
      private static final int BLOCK_TICKING_LEVEL_THRESHOLD = 33;
      final Long2ObjectMap<ObjectSet<ServerPlayer>> playersPerChunk = new Long2ObjectOpenHashMap();
diff --git a/patches/server/Rewrite-entity-bounding-box-lookup-calls.patch b/patches/server/Rewrite-entity-bounding-box-lookup-calls.patch
index 4fe5cce4c7..2721b60605 100644
--- a/patches/server/Rewrite-entity-bounding-box-lookup-calls.patch
+++ b/patches/server/Rewrite-entity-bounding-box-lookup-calls.patch
@@ -1054,55 +1054,6 @@ diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/Level.java
 +++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
- 
-     public abstract ResourceKey<LevelStem> getTypeKey();
- 
-+    // Paper start
-+    protected final io.papermc.paper.world.EntitySliceManager entitySliceManager;
-+
-+    public org.bukkit.entity.Entity[] getChunkEntities(int chunkX, int chunkZ) {
-+        io.papermc.paper.world.ChunkEntitySlices slices = this.entitySliceManager.getChunk(chunkX, chunkZ);
-+        if (slices == null) {
-+            return new org.bukkit.entity.Entity[0];
-+        }
-+        return slices.getChunkEntities();
-+    }
-+
-+    @Override
-+    public List<Entity> getHardCollidingEntities(Entity except, AABB box, Predicate<? super Entity> predicate) {
-+        List<Entity> ret = new java.util.ArrayList<>();
-+        this.entitySliceManager.getEntities(except, box, ret, predicate);
-+        return ret;
-+    }
-+
-+    @Override
-+    public void getEntities(Entity except, AABB box, Predicate<? super Entity> predicate, List<Entity> into) {
-+        this.entitySliceManager.getEntities(except, box, into, predicate);
-+    }
-+
-+    @Override
-+    public void getHardCollidingEntities(Entity except, AABB box, Predicate<? super Entity> predicate, List<Entity> into) {
-+        this.entitySliceManager.getHardCollidingEntities(except, box, into, predicate);
-+    }
-+
-+    @Override
-+    public <T> void getEntitiesByClass(Class<? extends T> clazz, Entity except, final AABB box, List<? super T> into,
-+                                       Predicate<? super T> predicate) {
-+        this.entitySliceManager.getEntities((Class)clazz, except, box, (List)into, (Predicate)predicate);
-+    }
-+
-+    @Override
-+    public <T extends Entity> List<T> getEntitiesOfClass(Class<T> entityClass, AABB box, Predicate<? super T> predicate) {
-+        List<T> ret = new java.util.ArrayList<>();
-+        this.entitySliceManager.getEntities(entityClass, null, box, ret, predicate);
-+        return ret;
-+    }
-+    // Paper end
-+
-     protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, final DimensionType dimensionmanager, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor
-         this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
-         this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper
 @@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
          this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime);
          this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime);
@@ -1182,6 +1133,53 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          return list;
      }
  
+@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+     public long nextSubTickCount() {
+         return (long) (this.subTickCount++);
+     }
++
++    // Paper start
++    protected final io.papermc.paper.world.EntitySliceManager entitySliceManager;
++
++    public org.bukkit.entity.Entity[] getChunkEntities(int chunkX, int chunkZ) {
++        io.papermc.paper.world.ChunkEntitySlices slices = this.entitySliceManager.getChunk(chunkX, chunkZ);
++        if (slices == null) {
++            return new org.bukkit.entity.Entity[0];
++        }
++        return slices.getChunkEntities();
++    }
++
++    @Override
++    public List<Entity> getHardCollidingEntities(Entity except, AABB box, Predicate<? super Entity> predicate) {
++        List<Entity> ret = new java.util.ArrayList<>();
++        this.entitySliceManager.getEntities(except, box, ret, predicate);
++        return ret;
++    }
++
++    @Override
++    public void getEntities(Entity except, AABB box, Predicate<? super Entity> predicate, List<Entity> into) {
++        this.entitySliceManager.getEntities(except, box, into, predicate);
++    }
++
++    @Override
++    public void getHardCollidingEntities(Entity except, AABB box, Predicate<? super Entity> predicate, List<Entity> into) {
++        this.entitySliceManager.getHardCollidingEntities(except, box, into, predicate);
++    }
++
++    @Override
++    public <T> void getEntitiesByClass(Class<? extends T> clazz, Entity except, final AABB box, List<? super T> into,
++                                       Predicate<? super T> predicate) {
++        this.entitySliceManager.getEntities((Class)clazz, except, box, (List)into, (Predicate)predicate);
++    }
++
++    @Override
++    public <T extends Entity> List<T> getEntitiesOfClass(Class<T> entityClass, AABB box, Predicate<? super T> predicate) {
++        List<T> ret = new java.util.ArrayList<>();
++        this.entitySliceManager.getEntities(entityClass, null, box, ret, predicate);
++        return ret;
++    }
++    // Paper end
+ }
 diff --git a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
@@ -1224,7 +1222,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  if (!this.currentSection.remove(this.entity)) {
 @@ -0,0 +0,0 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
              if (!this.currentSection.remove(this.entity)) {
-                 PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (destroying due to {})", this.entity, SectionPos.of(this.currentSectionKey), reason);
+                 PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (destroying due to {})", new Object[]{this.entity, SectionPos.of(this.currentSectionKey), reason});
              }
 +            PersistentEntitySectionManager.this.entitySliceManager.removeEntity((Entity)this.entity); // Paper
  
diff --git a/patches/server/Rewrite-the-light-engine.patch b/patches/server/Rewrite-the-light-engine.patch
index 4eb490d34a..9e2d205b0f 100644
--- a/patches/server/Rewrite-the-light-engine.patch
+++ b/patches/server/Rewrite-the-light-engine.patch
@@ -4112,6 +4112,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +import ca.spottedleaf.starlight.common.light.SWMRNibbleArray;
 +import ca.spottedleaf.starlight.common.light.StarLightEngine;
++import com.mojang.logging.LogUtils;
 +import net.minecraft.nbt.CompoundTag;
 +import net.minecraft.nbt.ListTag;
 +import net.minecraft.server.level.ServerLevel;
@@ -4119,12 +4120,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import net.minecraft.world.level.Level;
 +import net.minecraft.world.level.chunk.ChunkAccess;
 +import net.minecraft.world.level.chunk.ChunkStatus;
-+import org.apache.logging.log4j.LogManager;
-+import org.apache.logging.log4j.Logger;
++import org.slf4j.Logger;
 +
 +public final class SaveUtil {
 +
-+    private static final Logger LOGGER = LogManager.getLogger();
++    private static final Logger LOGGER = LogUtils.getLogger();
 +
 +    private static final int STARLIGHT_LIGHT_VERSION = 6;
 +
@@ -4448,9 +4448,9 @@ diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.j
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
 +++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
-@@ -0,0 +0,0 @@ import net.minecraft.world.level.lighting.LevelLightEngine;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.LightChunkGetter;
+ import net.minecraft.world.level.lighting.LevelLightEngine;
+ import org.slf4j.Logger;
  
 +// Paper start
 +import ca.spottedleaf.starlight.common.light.StarLightEngine;
@@ -4464,7 +4464,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +// Paper end
 +
  public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCloseable {
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
      private final ProcessorMailbox<Runnable> taskMailbox;
 @@ -0,0 +0,0 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
      private volatile int taskPerBatch = 5;
@@ -4606,7 +4606,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            }
 +        }, world.getChunkSource().chunkMap.mainThreadExecutor).whenComplete((final Void ignore, final Throwable thr) -> {
 +            if (thr != null) {
-+                LOGGER.fatal("Failed to remove ticket level for post chunk task " + new ChunkPos(chunkX, chunkZ), thr);
++                LOGGER.error("Failed to remove ticket level for post chunk task " + new ChunkPos(chunkX, chunkZ), thr);
 +            }
 +        });
 +    }
@@ -4729,7 +4729,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                this.tryScheduleUpdate();
 +            }).whenComplete((final ChunkAccess c, final Throwable throwable) -> {
 +                if (throwable != null) {
-+                    LOGGER.fatal("Failed to light chunk " + chunkPos, throwable);
++                    LOGGER.error("Failed to light chunk " + chunkPos, throwable);
 +                }
 +            });
 +        }
@@ -4869,7 +4869,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
 +++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
 @@ -0,0 +0,0 @@ public class EmptyLevelChunk extends LevelChunk {
-         super(world, pos);
+         this.biome = holder;
      }
  
 +    @Override
diff --git a/patches/server/Setup-Gradle-project.patch b/patches/server/Setup-Gradle-project.patch
index 731d2f5297..2e3c74dc5c 100644
--- a/patches/server/Setup-Gradle-project.patch
+++ b/patches/server/Setup-Gradle-project.patch
@@ -47,7 +47,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +dependencies {
 +    implementation(project(":paper-api"))
 +    implementation("jline:jline:2.12.1")
-+    implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") {
++    implementation("org.apache.logging.log4j:log4j-iostreams:2.17.0") {
 +        exclude(group = "org.apache.logging.log4j", module = "log4j-api")
 +    }
 +    implementation("org.ow2.asm:asm:9.2")
@@ -185,7 +185,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -    <groupId>org.spigotmc</groupId>
 -    <artifactId>spigot</artifactId>
 -    <packaging>jar</packaging>
--    <version>1.18.1-R0.1-SNAPSHOT</version>
+-    <version>1.18.2-R0.1-SNAPSHOT</version>
 -    <name>Spigot</name>
 -    <url>https://www.spigotmc.org/</url>
 -
@@ -201,7 +201,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 -        <api.version>unknown</api.version>
 -        <bt.name>git</bt.name>
--        <minecraft_version>1_18_R1</minecraft_version>
+-        <minecraft_version>1_18_R2</minecraft_version>
 -        <maven.compiler.source>16</maven.compiler.source>
 -        <maven.compiler.target>16</maven.compiler.target>
 -    </properties>
@@ -236,7 +236,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        <dependency>
 -            <groupId>org.apache.logging.log4j</groupId>
 -            <artifactId>log4j-iostreams</artifactId>
--            <version>2.14.1</version>
+-            <version>2.17.0</version>
 -            <scope>compile</scope>
 -        </dependency>
 -        <dependency>
@@ -249,13 +249,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        <dependency>
 -            <groupId>com.github.oshi</groupId>
 -            <artifactId>oshi-core</artifactId>
--            <version>5.8.2</version>
+-            <version>5.8.5</version>
 -            <scope>compile</scope>
 -        </dependency>
 -        <dependency>
 -            <groupId>com.mojang</groupId>
 -            <artifactId>authlib</artifactId>
--            <version>3.2.38</version>
+-            <version>3.3.39</version>
 -            <scope>compile</scope>
 -        </dependency>
 -        <dependency>
@@ -267,7 +267,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        <dependency>
 -            <groupId>com.mojang</groupId>
 -            <artifactId>datafixerupper</artifactId>
--            <version>4.0.26</version>
+-            <version>4.1.27</version>
 -            <scope>compile</scope>
 -        </dependency>
 -        <dependency>
@@ -277,6 +277,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -            <scope>compile</scope>
 -        </dependency>
 -        <dependency>
+-            <groupId>com.mojang</groupId>
+-            <artifactId>logging</artifactId>
+-            <version>1.0.0</version>
+-            <scope>compile</scope>
+-        </dependency>
+-        <dependency>
 -            <groupId>commons-io</groupId>
 -            <artifactId>commons-io</artifactId>
 -            <version>2.11.0</version>
@@ -309,13 +315,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        <dependency>
 -            <groupId>org.apache.logging.log4j</groupId>
 -            <artifactId>log4j-core</artifactId>
--            <version>2.14.1</version>
+-            <version>2.17.0</version>
 -            <scope>compile</scope>
 -        </dependency>
 -        <dependency>
 -            <groupId>org.apache.logging.log4j</groupId>
 -            <artifactId>log4j-slf4j18-impl</artifactId>
--            <version>2.14.1</version>
+-            <version>2.17.0</version>
 -            <scope>compile</scope>
 -        </dependency>
 -        <dependency>
diff --git a/patches/server/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/patches/server/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch
index c201ad146d..f4ef151f0b 100644
--- a/patches/server/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch
+++ b/patches/server/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch
@@ -49,7 +49,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/craftbukkit/Main.java
 +++ b/src/main/java/org/bukkit/craftbukkit/Main.java
 @@ -0,0 +0,0 @@ public class Main {
-                     deadline.add(Calendar.DAY_OF_YEAR, -28);
+                     deadline.add(Calendar.DAY_OF_YEAR, -3);
                      if (buildDate.before(deadline.getTime())) {
                          System.err.println("*** Error, this build is outdated ***");
 -                        System.err.println("*** Please download a new build as per instructions from https://www.spigotmc.org/go/outdated-spigot ***");
diff --git a/patches/server/Significantly-improve-performance-of-the-end-generat.patch b/patches/server/Significantly-improve-performance-of-the-end-generat.patch
index 40d0e81bba..c12a353daf 100644
--- a/patches/server/Significantly-improve-performance-of-the-end-generat.patch
+++ b/patches/server/Significantly-improve-performance-of-the-end-generat.patch
@@ -16,9 +16,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java
 +++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java
 @@ -0,0 +0,0 @@ public class TheEndBiomeSource extends BiomeSource {
-     private final Biome midlands;
-     private final Biome islands;
-     private final Biome barrens;
+     private final Holder<Biome> midlands;
+     private final Holder<Biome> islands;
+     private final Holder<Biome> barrens;
 +    // Paper start
 +    private static final class NoiseCache {
 +        public long[] keys = new long[8192];
@@ -31,7 +31,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end
  
      public TheEndBiomeSource(Registry<Biome> biomeRegistry, long seed) {
-         this(biomeRegistry, seed, biomeRegistry.getOrThrow(Biomes.THE_END), biomeRegistry.getOrThrow(Biomes.END_HIGHLANDS), biomeRegistry.getOrThrow(Biomes.END_MIDLANDS), biomeRegistry.getOrThrow(Biomes.SMALL_END_ISLANDS), biomeRegistry.getOrThrow(Biomes.END_BARRENS));
+         this(seed, biomeRegistry.getOrCreateHolder(Biomes.THE_END), biomeRegistry.getOrCreateHolder(Biomes.END_HIGHLANDS), biomeRegistry.getOrCreateHolder(Biomes.END_MIDLANDS), biomeRegistry.getOrCreateHolder(Biomes.SMALL_END_ISLANDS), biomeRegistry.getOrCreateHolder(Biomes.END_BARRENS));
 @@ -0,0 +0,0 @@ public class TheEndBiomeSource extends BiomeSource {
          float f = 100.0F - Mth.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; // Paper - cast ints to long to avoid integer overflow
          f = Mth.clamp(f, -100.0F, 80.0F);
diff --git a/patches/server/Spawn-player-in-correct-world-on-login.patch b/patches/server/Spawn-player-in-correct-world-on-login.patch
index 29a184cf53..71327176fd 100644
--- a/patches/server/Spawn-player-in-correct-world-on-login.patch
+++ b/patches/server/Spawn-player-in-correct-world-on-login.patch
@@ -25,6 +25,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        } else if (nbttagcompound != null) {
 +            // Vanilla migration support
 +            // Paper end
-             DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension")));
+             DataResult<ResourceKey<Level>> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension"))); // CraftBukkit - decompile error
              Logger logger = PlayerList.LOGGER;
  
diff --git a/patches/server/Support-old-UUID-format-for-NBT.patch b/patches/server/Support-old-UUID-format-for-NBT.patch
index f1d6ad77e3..507b8c5153 100644
--- a/patches/server/Support-old-UUID-format-for-NBT.patch
+++ b/patches/server/Support-old-UUID-format-for-NBT.patch
@@ -49,8 +49,8 @@ diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/m
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/nbt/NbtUtils.java
 +++ b/src/main/java/net/minecraft/nbt/NbtUtils.java
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import net.minecraft.world.level.material.FluidState;
+ import org.slf4j.Logger;
  
  public final class NbtUtils {
 -    private static final Comparator<ListTag> YXZ_LISTTAG_INT_COMPARATOR = Comparator.comparingInt((nbt) -> {
diff --git a/patches/server/Synchronize-PalettedContainer-instead-of-ReentrantLo.patch b/patches/server/Synchronize-PalettedContainer-instead-of-ReentrantLo.patch
index 0c0f43db0c..533eece542 100644
--- a/patches/server/Synchronize-PalettedContainer-instead-of-ReentrantLo.patch
+++ b/patches/server/Synchronize-PalettedContainer-instead-of-ReentrantLo.patch
@@ -31,7 +31,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      // Paper start - Anti-Xray - Add preset values
      @Deprecated public static <T> Codec<PalettedContainer<T>> codec(IdMap<T> idList, Codec<T> entryCodec, PalettedContainer.Strategy provider, T object) { return PalettedContainer.codec(idList, entryCodec, provider, object, null); } // Notice for updates: Please make sure this function isn't used anywhere
-     public static <T> Codec<PalettedContainer<T>> codec(IdMap<T> idList, Codec<T> entryCodec, PalettedContainer.Strategy provider, T object, T[] presetValues) {
+     public static <T> Codec<PalettedContainer<T>> codec(IdMap<T> idList, Codec<T> entryCodec, PalettedContainer.Strategy provider, T object, T @org.jetbrains.annotations.Nullable [] presetValues) {
 -        return RecordCodecBuilder.create((instance) -> {
 +        return RecordCodecBuilder.<DiscData<T>>create((instance) -> { // Paper - decompile fixes
              return instance.group(entryCodec.mapResult(ExtraCodecs.orElsePartial(object)).listOf().fieldOf("palette").forGetter(PalettedContainer.DiscData::paletteEntries), Codec.LONG_STREAM.optionalFieldOf("data").forGetter(PalettedContainer.DiscData::storage)).apply(instance, PalettedContainer.DiscData::new);
diff --git a/patches/server/Timings-v2.patch b/patches/server/Timings-v2.patch
index 29d08f4193..9de3f191e0 100644
--- a/patches/server/Timings-v2.patch
+++ b/patches/server/Timings-v2.patch
@@ -748,29 +748,16 @@ diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
 +++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
-@@ -0,0 +0,0 @@ package net.minecraft.network.protocol;
- import net.minecraft.network.PacketListener;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
-+import co.aikar.timings.MinecraftTimings; // Paper
-+import co.aikar.timings.Timing; // Paper
- 
- // CraftBukkit start
- import net.minecraft.server.MinecraftServer;
 @@ -0,0 +0,0 @@ public class PacketUtils {
- 
-     public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, BlockableEventLoop<?> engine) throws RunningOnDifferentThreadException {
-         if (!engine.isSameThread()) {
-+            Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings
-             engine.execute(() -> {
+             engine.executeIfPossible(() -> {
                  if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerGamePacketListenerImpl && ((ServerGamePacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590
                  if (listener.getConnection().isConnected()) {
-+                    try (Timing ignored = timing.startTiming()) { // Paper - timings
-                     packet.handle(listener);
-+                    } // Paper - timings
-                 } else {
-                     PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet);
-                 }
+-                    try {
++                    co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings
++                    try (co.aikar.timings.Timing ignored = timing.startTiming()) { // Paper - timings
+                         packet.handle(listener);
+                     } catch (Exception exception) {
+                         if (listener.shouldPropagateHandlingExceptions()) {
 diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -963,8 +950,8 @@ diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
 +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
- import org.apache.logging.log4j.Level;
+@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Level;
+ import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.io.IoBuilder;
  import org.bukkit.command.CommandSender;
 -import org.bukkit.craftbukkit.SpigotTimings; // Spigot
@@ -1157,15 +1144,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      @Override
 @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
-         this.runDistanceManagerUpdates();
          this.level.timings.doChunkMap.stopTiming(); // Spigot
          this.level.getProfiler().popPush("chunks");
-+        this.level.timings.chunks.startTiming(); // Paper - timings
-         this.tickChunks();
-+        this.level.timings.chunks.stopTiming(); // Paper - timings
+         if (tickChunks) {
++            this.level.timings.chunks.startTiming(); // Paper - timings
+             this.tickChunks();
++            this.level.timings.chunks.stopTiming(); // Paper - timings
+         }
+ 
          this.level.timings.doChunkUnload.startTiming(); // Spigot
-         this.level.getProfiler().popPush("unload");
-         this.chunkMap.tick(shouldKeepTicking);
 @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
              boolean flag1 = level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
  
@@ -1228,9 +1215,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import co.aikar.timings.Timings; // Paper
  import com.google.common.collect.Lists;
  import com.mojang.datafixers.DataFixer;
- import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+ import com.mojang.datafixers.util.Pair;
+@@ -0,0 +0,0 @@ import net.minecraft.world.ticks.LevelTicks;
+ import org.slf4j.Logger;
  import org.bukkit.Bukkit;
  import org.bukkit.WeatherType;
 -import org.bukkit.craftbukkit.SpigotTimings; // Spigot
@@ -1259,7 +1246,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        this.timings.raids.stopTiming(); // Paper - timings
          gameprofilerfiller.popPush("chunkSource");
 +        this.timings.chunkProviderTick.startTiming(); // Paper - timings
-         this.getChunkSource().tick(shouldKeepTicking);
+         this.getChunkSource().tick(shouldKeepTicking, true);
 +        this.timings.chunkProviderTick.stopTiming(); // Paper - timings
          gameprofilerfiller.popPush("blockEvents");
          timings.doSounds.startTiming(); // Spigot
@@ -1463,9 +1450,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +    public EntityType(EntityType.EntityFactory<T> factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet<Block> canSpawnInside, EntityDimensions dimensions, int maxTrackDistance, int trackTickInterval, String id) {
 +        // Paper end
+         this.builtInRegistryHolder = Registry.ENTITY_TYPE.createIntrusiveHolder(this);
          this.factory = factory;
          this.category = spawnGroup;
-         this.canSpawnFarFromPlayer = spawnableFarFromPlayer;
 @@ -0,0 +0,0 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T> {
          this.dimensions = dimensions;
          this.clientTrackingRange = maxTrackDistance;
diff --git a/patches/server/Turtle-API.patch b/patches/server/Turtle-API.patch
index 22d62b1094..3e5955f723 100644
--- a/patches/server/Turtle-API.patch
+++ b/patches/server/Turtle-API.patch
@@ -46,8 +46,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
          @Override
          public boolean canUse() {
--            return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(reducedTickDelay(700)) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) this.turtle.position(), 64.0D)));
-+            return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(reducedTickDelay(700)) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) this.turtle.position(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity()).callEvent(); // Paper
+-            return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(reducedTickDelay(700)) != 0 ? false : !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0D)));
++            return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(reducedTickDelay(700)) != 0 ? false : !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity()).callEvent(); // Paper
          }
  
          @Override
diff --git a/patches/server/Update-Log4j.patch b/patches/server/Update-Log4j.patch
index 262176b2a6..f71efe9377 100644
--- a/patches/server/Update-Log4j.patch
+++ b/patches/server/Update-Log4j.patch
@@ -17,8 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    implementation("org.apache.logging.log4j:log4j-core:2.17.1") // Paper - implementation
 +    annotationProcessor("org.apache.logging.log4j:log4j-core:2.17.1") // Paper - Needed to generate meta for our Log4j plugins
      // Paper end
--    implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper
-+    implementation("org.apache.logging.log4j:log4j-iostreams:2.17.1") // Paper
+     implementation("org.apache.logging.log4j:log4j-iostreams:2.17.1") // Paper
 +    implementation("org.apache.logging.log4j:log4j-slf4j18-impl:2.17.1") // Paper
      implementation("org.ow2.asm:asm:9.2")
      implementation("org.ow2.asm:asm-commons:9.2") // Paper - ASM event executor generation
diff --git a/patches/server/Use-ConcurrentHashMap-in-JsonList.patch b/patches/server/Use-ConcurrentHashMap-in-JsonList.patch
index 33c5c83701..a9f4bce7e5 100644
--- a/patches/server/Use-ConcurrentHashMap-in-JsonList.patch
+++ b/patches/server/Use-ConcurrentHashMap-in-JsonList.patch
@@ -49,7 +49,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  import java.util.Collection;
  import java.util.Iterator;
 @@ -0,0 +0,0 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> {
-     protected static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
      private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create();
      private final File file;
 -    private final Map<String, V> map = Maps.newHashMap();
diff --git a/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch
index 3c25da3a05..93c5d25a06 100644
--- a/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch
+++ b/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch
@@ -38,7 +38,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     */
 +    runtimeOnly("org.apache.logging.log4j:log4j-core:2.14.1")
 +    // Paper end
-     implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper
+     implementation("org.apache.logging.log4j:log4j-iostreams:2.17.1") // Paper
      implementation("org.ow2.asm:asm:9.2")
      implementation("org.ow2.asm:asm-commons:9.2") // Paper - ASM event executor generation
 diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java
@@ -115,23 +115,15 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/MinecraftServer.java
 +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
-@@ -0,0 +0,0 @@ import com.mojang.authlib.GameProfile;
- import com.mojang.authlib.GameProfileRepository;
- import com.mojang.authlib.minecraft.MinecraftSessionService;
- import com.mojang.datafixers.DataFixer;
-+import io.papermc.paper.adventure.PaperAdventure; // Paper
- import it.unimi.dsi.fastutil.longs.LongIterator;
- import java.awt.image.BufferedImage;
- import java.io.BufferedWriter;
-@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
+@@ -0,0 +0,0 @@ import org.slf4j.Logger;
  // CraftBukkit start
  import com.mojang.serialization.DynamicOps;
  import com.mojang.serialization.Lifecycle;
 -import jline.console.ConsoleReader;
 +// import jline.console.ConsoleReader; // Paper
  import joptsimple.OptionSet;
- import net.minecraft.resources.RegistryReadOps;
  import net.minecraft.server.bossevents.CustomBossEvents;
+ import net.minecraft.server.dedicated.DedicatedServer;
 @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
      public OptionSet options;
      public org.bukkit.command.ConsoleCommandSender console;
@@ -143,8 +135,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public int autosavePeriod;
 @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
          this.datapackconfiguration = datapackconfiguration;
-         this.registryreadops = RegistryReadOps.createAndLoad(NbtOps.INSTANCE, datapackresources.getResourceManager(), iregistrycustom_dimension);
-         this.vanillaCommandDispatcher = datapackresources.commands; // CraftBukkit
+         this.registryreadops = registryreadops;
+         this.vanillaCommandDispatcher = worldstem.dataPackResources().commands; // CraftBukkit
 +        // Paper start - Handled by TerminalConsoleAppender
          // Try to see if we're actually running in a terminal, disable jline if not
 +        /*
@@ -174,7 +166,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      @Override
      public void sendMessage(Component message, UUID sender) {
 -        MinecraftServer.LOGGER.info(message.getString());
-+        MinecraftServer.LOGGER.info(PaperAdventure.LEGACY_SECTION_UXRC.serialize(PaperAdventure.asAdventure(message))); // Paper - Log message with colors
++        MinecraftServer.LOGGER.info(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(io.papermc.paper.adventure.PaperAdventure.asAdventure(message))); // Paper - Log message with colors
      }
  
      public KeyPair getKeyPair() {
@@ -235,7 +227,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/server/players/PlayerList.java
 @@ -0,0 +0,0 @@ public abstract class PlayerList {
  
-     public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) {
+     public PlayerList(MinecraftServer server, RegistryAccess.Frozen registryManager, PlayerDataStorage saveHandler, int maxPlayers) {
          this.cserver = server.server = new CraftServer((DedicatedServer) server, this);
 -        server.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance();
 -        server.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(server.server));
diff --git a/patches/server/Use-a-Shared-Random-for-Entities.patch b/patches/server/Use-a-Shared-Random-for-Entities.patch
index 351a6d9819..cfb6679600 100644
--- a/patches/server/Use-a-Shared-Random-for-Entities.patch
+++ b/patches/server/Use-a-Shared-Random-for-Entities.patch
@@ -39,7 +39,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        this.random = SHARED_RANDOM; // Paper
          this.remainingFireTicks = -this.getFireImmuneTicks();
          this.fluidHeight = new Object2DoubleArrayMap(2);
-         this.firstTick = true;
+         this.fluidOnEyes = new HashSet();
 diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/entity/animal/Squid.java
diff --git a/patches/server/Use-correct-LevelStem-registry-when-loading-default-.patch b/patches/server/Use-correct-LevelStem-registry-when-loading-default-.patch
index 3f48147f87..72ef87c491 100644
--- a/patches/server/Use-correct-LevelStem-registry-when-loading-default-.patch
+++ b/patches/server/Use-correct-LevelStem-registry-when-loading-default-.patch
@@ -13,15 +13,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              long i = generatorsettings.seed();
              long j = BiomeManager.obfuscateSeed(i);
              List<CustomSpawner> list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(iworlddataserver));
--            LevelStem worlddimension = (LevelStem) registrymaterials.get(dimensionKey);
+-            LevelStem worlddimension = (LevelStem) iregistry.get(dimensionKey);
 +            // Paper start - Use correct LevelStem registry
 +            final LevelStem worlddimension;
 +            if (dimensionKey == LevelStem.END || dimensionKey == LevelStem.NETHER) {
 +                worlddimension = generatorsettings.dimensions().get(dimensionKey);
 +            } else {
-+                worlddimension = registrymaterials.get(dimensionKey);
++                worlddimension = iregistry.get(dimensionKey);
 +            }
 +            // Paper end
-             DimensionType dimensionmanager;
+             Holder<DimensionType> holder;
              ChunkGenerator chunkgenerator;
  
diff --git a/patches/server/Use-getChunkIfLoadedImmediately-in-places.patch b/patches/server/Use-getChunkIfLoadedImmediately-in-places.patch
index d907911d89..a7a87ddd12 100644
--- a/patches/server/Use-getChunkIfLoadedImmediately-in-places.patch
+++ b/patches/server/Use-getChunkIfLoadedImmediately-in-places.patch
@@ -50,7 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
      public abstract ResourceKey<LevelStem> getTypeKey();
  
-     protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, final DimensionType dimensionmanager, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor
+     protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor
 @@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
  
          for (int l1 = j; l1 <= l; ++l1) {
diff --git a/patches/server/Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/patches/server/Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch
index d9d7ad5b52..5a674d34c1 100644
--- a/patches/server/Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch
+++ b/patches/server/Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch
@@ -10,11 +10,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/item/MapItem.java
 +++ b/src/main/java/net/minecraft/world/item/MapItem.java
 @@ -0,0 +0,0 @@ public class MapItem extends ComplexItem {
+                 boolean[] aboolean = new boolean[16384];
+                 int l = j / i - 64;
+                 int i1 = k / i - 64;
+-                BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
  
-                 for (l = 0; l < 128 * i; ++l) {
-                     for (i1 = 0; i1 < 128 * i; ++i1) {
--                        Biome.BiomeCategory biomebase_geography = world.getBiome(new BlockPos((j / i - 64) * i + i1, 0, (k / i - 64) * i + l)).getBiomeCategory();
-+                        Biome.BiomeCategory biomebase_geography = world.getUncachedNoiseBiome((j / i - 64) * i + i1, 0, (k / i - 64) * i + l).getBiomeCategory(); // Paper
+                 int j1;
+                 int k1;
  
-                         aboolean[l * 128 * i + i1] = biomebase_geography == Biome.BiomeCategory.OCEAN || biomebase_geography == Biome.BiomeCategory.RIVER || biomebase_geography == Biome.BiomeCategory.SWAMP;
+                 for (j1 = 0; j1 < 128; ++j1) {
+                     for (k1 = 0; k1 < 128; ++k1) {
+-                        Biome.BiomeCategory biomebase_geography = Biome.getBiomeCategory(world.getBiome(blockposition_mutableblockposition.set((l + k1) * i, 0, (i1 + j1) * i)));
++                        Biome.BiomeCategory biomebase_geography = Biome.getBiomeCategory(world.getUncachedNoiseBiome((l + k1) * i, 0, (i1 + j1) * i)); // Paper
+ 
+                         aboolean[j1 * 128 + k1] = biomebase_geography == Biome.BiomeCategory.OCEAN || biomebase_geography == Biome.BiomeCategory.RIVER || biomebase_geography == Biome.BiomeCategory.SWAMP;
                      }
diff --git a/patches/server/Validate-usernames.patch b/patches/server/Validate-usernames.patch
index ddf18ae8bc..f961150baf 100644
--- a/patches/server/Validate-usernames.patch
+++ b/patches/server/Validate-usernames.patch
@@ -61,6 +61,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public void handleHello(ServerboundHelloPacket packet) {
          Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet", new Object[0]);
          this.gameProfile = packet.getGameProfile();
+         Validate.validState(ServerLoginPacketListenerImpl.isValidUsername(this.gameProfile.getName()), "Invalid characters in username", new Object[0]);
 +        // Paper start - validate usernames
 +        if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() && com.destroystokyo.paper.PaperConfig.performUsernameValidation) {
 +            if (!this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation && !validateUsername(this.gameProfile.getName())) {
diff --git a/patches/server/Vanilla-command-permission-fixes.patch b/patches/server/Vanilla-command-permission-fixes.patch
index e224be53da..f719d7de15 100644
--- a/patches/server/Vanilla-command-permission-fixes.patch
+++ b/patches/server/Vanilla-command-permission-fixes.patch
@@ -45,7 +45,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        }
 +        // Paper end
          this.dispatcher.findAmbiguities((commandnode, commandnode1, commandnode2, collection) -> {
-             // CommandDispatcher.LOGGER.warn("Ambiguity between arguments {} and {} with inputs: {}", this.dispatcher.getPath(commandnode1), this.dispatcher.getPath(commandnode2), collection); // CraftBukkit
+             // CommandDispatcher.LOGGER.warn("Ambiguity between arguments {} and {} with inputs: {}", new Object[]{this.dispatcher.getPath(commandnode1), this.dispatcher.getPath(commandnode2), collection}); // CraftBukkit
          });
 diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
diff --git a/patches/server/Vanished-players-don-t-have-rights.patch b/patches/server/Vanished-players-don-t-have-rights.patch
index d9af9ff999..e183611916 100644
--- a/patches/server/Vanished-players-don-t-have-rights.patch
+++ b/patches/server/Vanished-players-don-t-have-rights.patch
@@ -50,8 +50,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import net.minecraft.world.phys.shapes.Shapes;
 +import net.minecraft.world.phys.shapes.VoxelShape;
  import net.minecraft.world.scores.Scoreboard;
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+ 
+ // CraftBukkit start
 @@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
          this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime);
      }
diff --git a/patches/server/fix-cancelling-block-falling-causing-client-desync.patch b/patches/server/fix-cancelling-block-falling-causing-client-desync.patch
index 945d909520..37382d4a5f 100644
--- a/patches/server/fix-cancelling-block-falling-causing-client-desync.patch
+++ b/patches/server/fix-cancelling-block-falling-causing-client-desync.patch
@@ -10,22 +10,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
 @@ -0,0 +0,0 @@ public class FallingBlockEntity extends Entity {
  
-             if (this.time++ == 0) {
-                 blockposition = this.blockPosition();
--                if (this.level.getBlockState(blockposition).is(block) && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) {
--                    this.level.removeBlock(blockposition, false);
-+                // Paper start - fix cancelling block falling causing client desync
-+                if (this.level.getBlockState(blockposition).is(block)) {
-+                    if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) {
-+                        if (this.level.getBlockState(blockposition).is(block)) { //if listener didn't update the block
-+                            ((ServerLevel) level).getChunkSource().blockChanged(blockposition);
-+                        }
-+                        this.discard();
-+                        return;
-+                    } else {
-+                        this.level.removeBlock(blockposition, false);
-+                    }
-+                    // Paper end - fix cancelling block falling causing client desync
-                 } else if (!this.level.isClientSide) {
-                     this.discard();
-                     return;
+                                 // CraftBukkit start
+                                 if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, this.blockState).isCancelled()) {
+-                                    this.discard(); // SPIGOT-6586 called before the event in previous versions
++                                    this.discard(); // SPIGOT-6586 called before the event in previous versions //TODO test if desync happens on cancel
+                                     return;
+                                 }
+                                 // CraftBukkit end
diff --git a/patches/server/forced-whitelist-use-configurable-kick-message.patch b/patches/server/forced-whitelist-use-configurable-kick-message.patch
index 91d4ec7e0f..7c19575581 100644
--- a/patches/server/forced-whitelist-use-configurable-kick-message.patch
+++ b/patches/server/forced-whitelist-use-configurable-kick-message.patch
@@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/MinecraftServer.java
 +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
-@@ -0,0 +0,0 @@ import net.minecraft.nbt.NbtOps;
+@@ -0,0 +0,0 @@ import net.minecraft.gametest.framework.GameTestTicker;
  import net.minecraft.nbt.Tag;
  import net.minecraft.network.chat.Component;
  import net.minecraft.network.chat.TextComponent;
diff --git a/patches/server/implement-optional-per-player-mob-spawns.patch b/patches/server/implement-optional-per-player-mob-spawns.patch
index 73c0688f3b..70c2ad8ce6 100644
--- a/patches/server/implement-optional-per-player-mob-spawns.patch
+++ b/patches/server/implement-optional-per-player-mob-spawns.patch
@@ -273,7 +273,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java
 +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
-     private final Long2ByteMap chunkTypeCache;
+     private final Long2LongMap chunkSaveCooldowns;
      private final Queue<Runnable> unloadQueue;
      int viewDistance;
 +    public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobDistanceMap; // Paper
diff --git a/patches/server/incremental-chunk-and-player-saving.patch b/patches/server/incremental-chunk-and-player-saving.patch
index aa3efad176..f9f2566f18 100644
--- a/patches/server/incremental-chunk-and-player-saving.patch
+++ b/patches/server/incremental-chunk-and-player-saving.patch
@@ -175,7 +175,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper
  import org.apache.commons.lang3.mutable.MutableBoolean;
  import org.apache.commons.lang3.mutable.MutableObject;
- import org.apache.logging.log4j.LogManager;
+ import org.slf4j.Logger;
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
  
      }
@@ -346,10 +346,10 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/ma
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
 +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
-     public final int getViewDistance() { return this.getLevel().getChunkSource().chunkMap.viewDistance - 1; } // Paper - placeholder
+@@ -0,0 +0,0 @@ import org.bukkit.inventory.MainHand;
+ public class ServerPlayer extends Player {
  
-     private static final Logger LOGGER = LogManager.getLogger();
+     private static final Logger LOGGER = LogUtils.getLogger();
 +    public long lastSave = MinecraftServer.currentTick; // Paper
      private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
      private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
diff --git a/patches/server/remove-null-possibility-for-getServer-singleton.patch b/patches/server/remove-null-possibility-for-getServer-singleton.patch
index 58417f320e..79b5d569b9 100644
--- a/patches/server/remove-null-possibility-for-getServer-singleton.patch
+++ b/patches/server/remove-null-possibility-for-getServer-singleton.patch
@@ -14,12 +14,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTask> implements CommandSource, AutoCloseable {
  
 +    private static MinecraftServer SERVER; // Paper
-     public static final Logger LOGGER = LogManager.getLogger();
+     public static final Logger LOGGER = LogUtils.getLogger();
      public static final String VANILLA_BRAND = "vanilla";
      private static final float AVERAGE_TICK_TIME_SMOOTHING = 0.8F;
 @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
  
-     public MinecraftServer(OptionSet options, DataPackConfig datapackconfiguration, Thread thread, RegistryAccess.RegistryHolder iregistrycustom_dimension, LevelStorageSource.LevelStorageAccess convertable_conversionsession, WorldData savedata, PackRepository resourcepackrepository, Proxy proxy, DataFixer datafixer, ServerResources datapackresources, @Nullable MinecraftSessionService minecraftsessionservice, @Nullable GameProfileRepository gameprofilerepository, @Nullable GameProfileCache usercache, ChunkProgressListenerFactory worldloadlistenerfactory) {
+     public MinecraftServer(OptionSet options, DataPackConfig datapackconfiguration, DynamicOps<Tag> registryreadops, Thread thread, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PackRepository resourcepackrepository, WorldStem worldstem, Proxy proxy, DataFixer datafixer, @Nullable MinecraftSessionService minecraftsessionservice, @Nullable GameProfileRepository gameprofilerepository, @Nullable GameProfileCache usercache, ChunkProgressListenerFactory worldloadlistenerfactory) {
          super("Server");
 +        SERVER = this; // Paper - better singleton
          this.metricsRecorder = InactiveMetricsRecorder.INSTANCE;
diff --git a/work/BuildData b/work/BuildData
index 059e48d0b4..641cb0c939 160000
--- a/work/BuildData
+++ b/work/BuildData
@@ -1 +1 @@
-Subproject commit 059e48d0b4666138c4a8330ee38310d74824a848
+Subproject commit 641cb0c939c7c2a3c4b42f2fd7bca7c8b34254ae
diff --git a/work/Bukkit b/work/Bukkit
index 6fac07ebfb..d8a3c3b556 160000
--- a/work/Bukkit
+++ b/work/Bukkit
@@ -1 +1 @@
-Subproject commit 6fac07ebfb9c836546d4fe10772a32cfb8357149
+Subproject commit d8a3c3b55674a931391e2905cad4d54acfd15d11
diff --git a/work/CraftBukkit b/work/CraftBukkit
index 1e87776acb..05a38da190 160000
--- a/work/CraftBukkit
+++ b/work/CraftBukkit
@@ -1 +1 @@
-Subproject commit 1e87776acbb1f1c63fd9a5917b44eb2e7f1283a2
+Subproject commit 05a38da190704cb8df90401c45fc39d087cdc031
diff --git a/work/Spigot b/work/Spigot
index 699290cdcc..fb0dd5f518 160000
--- a/work/Spigot
+++ b/work/Spigot
@@ -1 +1 @@
-Subproject commit 699290cdcc3d7721a3031b395d8693a9a11d8f6d
+Subproject commit fb0dd5f518e866748a20ee2c753edc3c6b9392d2