diff --git a/Spigot-Server-Patches/Add-API-methods-to-control-if-armour-stands-can-move.patch b/Spigot-Server-Patches/Add-API-methods-to-control-if-armour-stands-can-move.patch
index 85dec620fa..32820d3025 100644
--- a/Spigot-Server-Patches/Add-API-methods-to-control-if-armour-stands-can-move.patch
+++ b/Spigot-Server-Patches/Add-API-methods-to-control-if-armour-stands-can-move.patch
@@ -18,7 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          super(entitytypes, world);
 @@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving {
  
-         return this.getEntityType().k().a(f);
+         return this.getEntityType().l().a(f);
      }
 +
 +    // Paper start
diff --git a/Spigot-Server-Patches/Add-EntityZapEvent.patch b/Spigot-Server-Patches/Add-EntityZapEvent.patch
index b984edefad..ba5de3cfb8 100644
--- a/Spigot-Server-Patches/Add-EntityZapEvent.patch
+++ b/Spigot-Server-Patches/Add-EntityZapEvent.patch
@@ -8,36 +8,35 @@ diff --git a/src/main/java/net/minecraft/server/EntityPig.java b/src/main/java/n
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/EntityPig.java
 +++ b/src/main/java/net/minecraft/server/EntityPig.java
-@@ -0,0 +0,0 @@ public class EntityPig extends EntityAnimal {
-             entitypigzombie.setCustomNameVisible(this.getCustomNameVisible());
-         }
+@@ -0,0 +0,0 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable {
+             }
  
-+        // Paper start
-+        if (CraftEventFactory.callEntityZapEvent(this, entitylightning, entitypigzombie).isCancelled()) {
-+            return;
-+        }
-+        // Paper end
-+
-         // CraftBukkit start
-         if (CraftEventFactory.callPigZapEvent(this, entitylightning, entitypigzombie).isCancelled()) {
-             return;
+             entitypigzombie.setPersistent();
++            // Paper start
++            if (CraftEventFactory.callEntityZapEvent(this, entitylightning, entitypigzombie).isCancelled()) {
++                return;
++            }
++            // Paper end
+             // CraftBukkit start
+             if (CraftEventFactory.callPigZapEvent(this, entitylightning, entitypigzombie).isCancelled()) {
+                 return;
 diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/EntityVillager.java
 +++ b/src/main/java/net/minecraft/server/EntityVillager.java
 @@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
-     public void onLightningStrike(EntityLightning entitylightning) {
-         EntityWitch entitywitch = (EntityWitch) EntityTypes.WITCH.a(this.world);
+             EntityVillager.LOGGER.info("Villager {} was struck by lightning {}.", this, entitylightning);
+             EntityWitch entitywitch = (EntityWitch) EntityTypes.WITCH.a(this.world);
  
-+        // Paper start
-+        if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, entitylightning, entitywitch).isCancelled()) {
-+            return;
-+        }
-+        // Paper end
++            // Paper start
++            if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, entitylightning, entitywitch).isCancelled()) {
++                return;
++            }
++            // Paper end
 +
-         entitywitch.setPositionRotation(this.locX(), this.locY(), this.locZ(), this.yaw, this.pitch);
-         entitywitch.prepare(this.world, this.world.getDamageScaler(new BlockPosition(entitywitch)), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (NBTTagCompound) null);
-         entitywitch.setNoAI(this.isNoAI());
+             entitywitch.setPositionRotation(this.locX(), this.locY(), this.locZ(), this.yaw, this.pitch);
+             entitywitch.prepare(this.world, this.world.getDamageScaler(entitywitch.getChunkCoordinates()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (NBTTagCompound) null);
+             entitywitch.setNoAI(this.isNoAI());
 diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
diff --git a/Spigot-Server-Patches/Add-ProjectileCollideEvent.patch b/Spigot-Server-Patches/Add-ProjectileCollideEvent.patch
index 857068456a..bec046d55f 100644
--- a/Spigot-Server-Patches/Add-ProjectileCollideEvent.patch
+++ b/Spigot-Server-Patches/Add-ProjectileCollideEvent.patch
@@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/EntityArrow.java
 +++ b/src/main/java/net/minecraft/server/EntityArrow.java
-@@ -0,0 +0,0 @@ public abstract class EntityArrow extends Entity implements IProjectile {
+@@ -0,0 +0,0 @@ public abstract class EntityArrow extends IProjectile {
                      }
                  }
  
@@ -30,9 +30,9 @@ diff --git a/src/main/java/net/minecraft/server/EntityFireball.java b/src/main/j
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/EntityFireball.java
 +++ b/src/main/java/net/minecraft/server/EntityFireball.java
-@@ -0,0 +0,0 @@ public abstract class EntityFireball extends Entity {
-             ++this.g;
-             MovingObjectPosition movingobjectposition = ProjectileHelper.a(this, true, this.g >= 25, this.shooter, RayTrace.BlockCollisionOption.COLLIDER);
+@@ -0,0 +0,0 @@ public abstract class EntityFireball extends IProjectile {
+ 
+             MovingObjectPosition movingobjectposition = ProjectileHelper.a(this, this::a, RayTrace.BlockCollisionOption.COLLIDER);
  
 -            if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) {
 +            // Paper start - Call ProjectileCollideEvent
@@ -48,50 +48,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  this.a(movingobjectposition);
  
                  // CraftBukkit start - Fire ProjectileHitEvent
-diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/server/EntityFishingHook.java
-+++ b/src/main/java/net/minecraft/server/EntityFishingHook.java
-@@ -0,0 +0,0 @@ public class EntityFishingHook extends Entity {
-             return !entity.isSpectator() && (entity.isInteractable() || entity instanceof EntityItem) && (entity != this.owner || this.g >= 5);
-         }, RayTrace.BlockCollisionOption.COLLIDER, true);
- 
--        if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) {
-+        // Paper start - Call ProjectileCollideEvent
-+        if (movingobjectposition instanceof MovingObjectPositionEntity) {
-+            com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition);
-+            if (event.isCancelled()) {
-+                movingobjectposition = null;
-+            }
-+        }
-+        // Paper end
-+
-+        if (movingobjectposition != null && movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { // Paper - add null check in case cancelled
-             org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); // CraftBukkit - Call event
-             if (movingobjectposition.getType() == MovingObjectPosition.EnumMovingObjectType.ENTITY) {
-                 this.hooked = ((MovingObjectPositionEntity) movingobjectposition).getEntity();
 diff --git a/src/main/java/net/minecraft/server/EntityProjectile.java b/src/main/java/net/minecraft/server/EntityProjectile.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/EntityProjectile.java
 +++ b/src/main/java/net/minecraft/server/EntityProjectile.java
-@@ -0,0 +0,0 @@ public abstract class EntityProjectile extends Entity implements IProjectile {
-             this.ap = null;
+@@ -0,0 +0,0 @@ public abstract class EntityProjectile extends IProjectile {
          }
  
--        if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) {
-+        // Paper start - Call ProjectileCollideEvent
-+        if (movingobjectposition instanceof MovingObjectPositionEntity) {
-+            com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition);
-+            if (event.isCancelled()) {
-+                movingobjectposition = null;
+         if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS && !flag) {
++            // Paper start - Call ProjectileCollideEvent
++            if (movingobjectposition instanceof MovingObjectPositionEntity) {
++                com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition);
++                if (event.isCancelled()) {
++                    movingobjectposition = null;
++                }
 +            }
-+        }
-+        // Paper end
-+
-+        if (movingobjectposition != null && movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { // Paper - add null check in case cancelled
-             if (movingobjectposition.getType() == MovingObjectPosition.EnumMovingObjectType.BLOCK && this.world.getType(((MovingObjectPositionBlock) movingobjectposition).getBlockPosition()).getBlock() == Blocks.NETHER_PORTAL) {
-                 this.c(((MovingObjectPositionBlock) movingobjectposition).getBlockPosition());
-             } else {
++            if (movingobjectposition != null) {
++            // Paper end
+             this.a(movingobjectposition);
+             // CraftBukkit start
+             if (this.dead) {
+                 org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition);
+             }
+             // CraftBukkit end
++            } // Paper
+         }
+ 
+         Vec3D vec3d = this.getMot();
 diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
diff --git a/Spigot-Server-Patches/Auto-fix-bad-Y-levels-on-player-login.patch b/Spigot-Server-Patches/Auto-fix-bad-Y-levels-on-player-login.patch
index 2b54be8e97..6242dbaed0 100644
--- a/Spigot-Server-Patches/Auto-fix-bad-Y-levels-on-player-login.patch
+++ b/Spigot-Server-Patches/Auto-fix-bad-Y-levels-on-player-login.patch
@@ -11,9 +11,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/server/EntityPlayer.java
 @@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
      @Override
-     public void a(NBTTagCompound nbttagcompound) {
-         super.a(nbttagcompound);
+     public void loadData(NBTTagCompound nbttagcompound) {
+         super.loadData(nbttagcompound);
 +        if (this.locY() > 300) this.setPositionRaw(locX(), 257, locZ()); // Paper - bring down to a saner Y level if out of world
          if (nbttagcompound.hasKeyOfType("playerGameType", 99)) {
              if (this.getMinecraftServer().getForceGamemode()) {
-                 this.playerInteractManager.setGameMode(this.getMinecraftServer().getGamemode());
+                 this.playerInteractManager.a(this.getMinecraftServer().getGamemode(), EnumGamemode.NOT_SET);
diff --git a/Spigot-Server-Patches/Bound-Treasure-Maps-to-World-Border.patch b/Spigot-Server-Patches/Bound-Treasure-Maps-to-World-Border.patch
index dced1406dd..a9aa588cf4 100644
--- a/Spigot-Server-Patches/Bound-Treasure-Maps-to-World-Border.patch
+++ b/Spigot-Server-Patches/Bound-Treasure-Maps-to-World-Border.patch
@@ -15,19 +15,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/StructureGenerator.java
 +++ b/src/main/java/net/minecraft/server/StructureGenerator.java
 @@ -0,0 +0,0 @@ public abstract class StructureGenerator<C extends WorldGenFeatureConfiguration>
+                             int i2 = l + k * k1;
+                             int j2 = i1 + k * l1;
+                             ChunkCoordIntPair chunkcoordintpair = this.a(structuresettingsfeature, j, seededrandom, i2, j2);
++                            if (!iworldreader.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper
+                             IChunkAccess ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS);
+                             StructureStart<?> structurestart = structuremanager.a(SectionPosition.a(ichunkaccess.getPos(), 0), this, ichunkaccess);
  
-                             if (flag1 || flag2) {
-                                 ChunkCoordIntPair chunkcoordintpair = this.a(chunkgenerator, seededrandom, j, k, i1, j1);
-+                                if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper
-                                 StructureStart structurestart = world.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS).a(this.b());
- 
-                                 if (structurestart != null && structurestart.e()) {
 diff --git a/src/main/java/net/minecraft/server/WorldBorder.java b/src/main/java/net/minecraft/server/WorldBorder.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/WorldBorder.java
 +++ b/src/main/java/net/minecraft/server/WorldBorder.java
 @@ -0,0 +0,0 @@ public class WorldBorder {
-         return (double) (blockposition.getX() + 1) > this.c() && (double) blockposition.getX() < this.e() && (double) (blockposition.getZ() + 1) > this.d() && (double) blockposition.getZ() < this.f();
+         return (double) (blockposition.getX() + 1) > this.e() && (double) blockposition.getX() < this.g() && (double) (blockposition.getZ() + 1) > this.f() && (double) blockposition.getZ() < this.h();
      }
  
 +    // Paper start
@@ -43,5 +43,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end
 +
      public boolean isInBounds(ChunkCoordIntPair chunkcoordintpair) {
-         return (double) chunkcoordintpair.f() > this.c() && (double) chunkcoordintpair.d() < this.e() && (double) chunkcoordintpair.g() > this.d() && (double) chunkcoordintpair.e() < this.f();
+         return (double) chunkcoordintpair.f() > this.e() && (double) chunkcoordintpair.d() < this.g() && (double) chunkcoordintpair.g() > this.f() && (double) chunkcoordintpair.e() < this.h();
      }
diff --git a/Spigot-Server-Patches/Cache-user-authenticator-threads.patch b/Spigot-Server-Patches/Cache-user-authenticator-threads.patch
index 6b308ee461..e5c349a4f2 100644
--- a/Spigot-Server-Patches/Cache-user-authenticator-threads.patch
+++ b/Spigot-Server-Patches/Cache-user-authenticator-threads.patch
@@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ import com.google.common.collect.Lists;
  import com.mojang.authlib.GameProfile;
  import com.mojang.datafixers.util.Either;
- import io.netty.util.concurrent.Future;
+ import com.mojang.serialization.DataResult;
 +import java.util.ArrayDeque; // Paper
  import java.util.Collection;
 +import java.util.Deque; // Paper
@@ -63,6 +63,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            this.removeQueue.addAll(entityplayer.removeQueue);
 +        }
 +        // Paper end
-         this.cm = entityplayer.cm;
-         this.cr = entityplayer.cr;
+         this.ck = entityplayer.ck;
+         this.cp = entityplayer.cp;
          this.setShoulderEntityLeft(entityplayer.getShoulderEntityLeft());
diff --git a/Spigot-Server-Patches/Chunk-registration-fixes.patch b/Spigot-Server-Patches/Chunk-registration-fixes.patch
index 261a9b880c..d5d3f53714 100644
--- a/Spigot-Server-Patches/Chunk-registration-fixes.patch
+++ b/Spigot-Server-Patches/Chunk-registration-fixes.patch
@@ -11,12 +11,12 @@ diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/WorldServer.java
 +++ b/src/main/java/net/minecraft/server/WorldServer.java
-@@ -0,0 +0,0 @@ public class WorldServer extends World {
-     public void chunkCheck(Entity entity) {
-         this.getMethodProfiler().enter("chunkCheck");
-         int i = MathHelper.floor(entity.locX() / 16.0D);
--        int j = MathHelper.floor(entity.locY() / 16.0D);
-+        int j =  Math.min(15, Math.max(0, MathHelper.floor(entity.locY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior;
-         int k = MathHelper.floor(entity.locZ() / 16.0D);
+@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
+         if (entity.ck()) {
+             this.getMethodProfiler().enter("chunkCheck");
+             int i = MathHelper.floor(entity.locX() / 16.0D);
+-            int j = MathHelper.floor(entity.locY() / 16.0D);
++            int j =  Math.min(15, Math.max(0, MathHelper.floor(entity.locY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior
+             int k = MathHelper.floor(entity.locZ() / 16.0D);
  
-         if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) {
+             if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) {
diff --git a/Spigot-Server-Patches/Configurable-Cartographer-Treasure-Maps.patch b/Spigot-Server-Patches/Configurable-Cartographer-Treasure-Maps.patch
index 3fb5cf3a4b..2767a075d0 100644
--- a/Spigot-Server-Patches/Configurable-Cartographer-Treasure-Maps.patch
+++ b/Spigot-Server-Patches/Configurable-Cartographer-Treasure-Maps.patch
@@ -34,7 +34,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public class LootItemFunctionExplorationMap extends LootItemFunctionConditional
  
              if (blockposition != null) {
-                 WorldServer worldserver = loottableinfo.c();
+                 WorldServer worldserver = loottableinfo.getWorld();
 +                // Paper start
 +                if (!worldserver.paperConfig.enableTreasureMaps) {
 +                    /*
@@ -44,7 +44,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    return itemstack;
 +                }
 +                // Paper end
-                 BlockPosition blockposition1 = worldserver.a(this.d, blockposition, this.g, this.h);
+                 BlockPosition blockposition1 = worldserver.a(this.e, blockposition, this.h, this.i);
  
                  if (blockposition1 != null) {
 diff --git a/src/main/java/net/minecraft/server/VillagerTrades.java b/src/main/java/net/minecraft/server/VillagerTrades.java
@@ -55,9 +55,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  return null;
              } else {
                  WorldServer worldserver = (WorldServer) entity.world;
--                BlockPosition blockposition = worldserver.a(this.b, new BlockPosition(entity), 100, true);
-+                if (!worldserver.paperConfig.enableTreasureMaps) return null; //Paper
-+                BlockPosition blockposition = worldserver.a(this.b, new BlockPosition(entity), 100, !worldserver.paperConfig.treasureMapsAlreadyDiscovered); //Paper
+-                BlockPosition blockposition = worldserver.a(this.b, entity.getChunkCoordinates(), 100, true);
++                if (!worldserver.paperConfig.enableTreasureMaps) return null; // Paper
++                BlockPosition blockposition = worldserver.a(this.b, entity.getChunkCoordinates(), 100, !worldserver.paperConfig.treasureMapsAlreadyDiscovered); // Paper
  
                  if (blockposition != null) {
                      ItemStack itemstack = ItemWorldMap.createFilledMapView(worldserver, blockposition.getX(), blockposition.getZ(), (byte) 2, true, true);
diff --git a/Spigot-Server-Patches/Configurable-flying-kick-messages.patch b/Spigot-Server-Patches/Configurable-flying-kick-messages.patch
index 56784df079..fdc7aa0f0e 100644
--- a/Spigot-Server-Patches/Configurable-flying-kick-messages.patch
+++ b/Spigot-Server-Patches/Configurable-flying-kick-messages.patch
@@ -25,10 +25,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/PlayerConnection.java
 +++ b/src/main/java/net/minecraft/server/PlayerConnection.java
 @@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn {
-         if (this.B) {
+         if (this.B && !this.player.isSleeping()) {
              if (++this.C > 80) {
                  PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", this.player.getDisplayName().getString());
--                this.disconnect(new ChatMessage("multiplayer.disconnect.flying", new Object[0]));
+-                this.disconnect(new ChatMessage("multiplayer.disconnect.flying"));
 +                this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message
                  return;
              }
@@ -37,7 +37,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              if (this.D && this.player.getRootVehicle().getRidingPassenger() == this.player) {
                  if (++this.E > 80) {
                      PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getDisplayName().getString());
--                    this.disconnect(new ChatMessage("multiplayer.disconnect.flying", new Object[0]));
+-                    this.disconnect(new ChatMessage("multiplayer.disconnect.flying"));
 +                    this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message
                      return;
                  }
diff --git a/Spigot-Server-Patches/Don-t-let-fishinghooks-use-portals.patch b/Spigot-Server-Patches/Don-t-let-fishinghooks-use-portals.patch
index 085200f659..4eef9c894f 100644
--- a/Spigot-Server-Patches/Don-t-let-fishinghooks-use-portals.patch
+++ b/Spigot-Server-Patches/Don-t-let-fishinghooks-use-portals.patch
@@ -12,19 +12,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public boolean ac;
      public boolean impulse;
      public int portalCooldown;
--    protected boolean af;
-+    protected boolean af; public final boolean inPortal() { return this.af; } // Paper - OBFHELPER
-     protected int ag;
-     public DimensionManager dimension;
-     protected BlockPosition ai;
+-    protected boolean inPortal;
++    protected boolean inPortal; public final boolean inPortal() { return this.inPortal; } // Paper - OBFHELPER
+     protected int portalTicks;
+     protected BlockPosition ah;
+     protected Vec3D ai;
 diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/EntityFishingHook.java
 +++ b/src/main/java/net/minecraft/server/EntityFishingHook.java
-@@ -0,0 +0,0 @@ public class EntityFishingHook extends Entity {
+@@ -0,0 +0,0 @@ public class EntityFishingHook extends IProjectile {
  
              this.setMot(this.getMot().a(0.92D));
-             this.Z();
+             this.ac();
 +
 +            // Paper start - These shouldn't be going through portals
 +            if (this.inPortal()) {
diff --git a/Spigot-Server-Patches/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/Spigot-Server-Patches/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch
index 33a7cbe276..6fcf7f9971 100644
--- a/Spigot-Server-Patches/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch
+++ b/Spigot-Server-Patches/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch
@@ -11,7 +11,7 @@ diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/m
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/Block.java
 +++ b/src/main/java/net/minecraft/server/Block.java
-@@ -0,0 +0,0 @@ public class Block implements IMaterial {
+@@ -0,0 +0,0 @@ public class Block extends BlockBase implements IMaterial {
          }
      }
  
@@ -40,6 +40,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                      }
  
                      world.triggerEffect(1042, blockposition, 0);
+diff --git a/src/main/java/net/minecraft/server/EntityAnimal.java b/src/main/java/net/minecraft/server/EntityAnimal.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/server/EntityAnimal.java
++++ b/src/main/java/net/minecraft/server/EntityAnimal.java
+@@ -0,0 +0,0 @@ public abstract class EntityAnimal extends EntityAgeable {
+             if (world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) {
+                 // CraftBukkit start - use event experience
+                 if (experience > 0) {
+-                    world.addEntity(new EntityExperienceOrb(world, this.locX(), this.locY(), this.locZ(), experience));
++                    world.addEntity(new EntityExperienceOrb(world, this.locX(), this.locY(), this.locZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper
+                 }
+                 // CraftBukkit end
+             }
 diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/EntityEnderDragon.java
@@ -137,15 +150,28 @@ diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/mai
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/EntityFishingHook.java
 +++ b/src/main/java/net/minecraft/server/EntityFishingHook.java
-@@ -0,0 +0,0 @@ public class EntityFishingHook extends Entity {
+@@ -0,0 +0,0 @@ public class EntityFishingHook extends IProjectile {
                      this.world.addEntity(entityitem);
                      // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop()
                      if (playerFishEvent.getExpToDrop() > 0) {
--                        this.owner.world.addEntity(new EntityExperienceOrb(this.owner.world, this.owner.locX(), this.owner.locY() + 0.5D, this.owner.locZ() + 0.5D, playerFishEvent.getExpToDrop()));
-+                        this.owner.world.addEntity(new EntityExperienceOrb(this.owner.world, this.owner.locX(), this.owner.locY() + 0.5D, this.owner.locZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.owner, this)); // Paper
+-                        entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop()));
++                        entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getOwner(), this)); // Paper
                      }
                      // CraftBukkit end
-                     if (itemstack1.getItem().a(TagsItem.FISHES)) {
+                     if (itemstack1.getItem().a((Tag) TagsItem.FISHES)) {
+diff --git a/src/main/java/net/minecraft/server/EntityFox.java b/src/main/java/net/minecraft/server/EntityFox.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/server/EntityFox.java
++++ b/src/main/java/net/minecraft/server/EntityFox.java
+@@ -0,0 +0,0 @@ public class EntityFox extends EntityAnimal {
+                 if (this.b.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) {
+                     // CraftBukkit start - use event experience
+                     if (experience > 0) {
+-                        this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience));
++                        this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper
+                     }
+                     // CraftBukkit end
+                 }
 diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/EntityLiving.java
@@ -212,19 +238,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          }
  
      }
-diff --git a/src/main/java/net/minecraft/server/PathfinderGoalBreed.java b/src/main/java/net/minecraft/server/PathfinderGoalBreed.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/server/PathfinderGoalBreed.java
-+++ b/src/main/java/net/minecraft/server/PathfinderGoalBreed.java
-@@ -0,0 +0,0 @@ public class PathfinderGoalBreed extends PathfinderGoal {
-             if (this.b.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) {
-                 // CraftBukkit start - use event experience
-                 if (experience > 0) {
--                    this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience));
-+                    this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper
-                 }
-                 // CraftBukkit end
-             }
 diff --git a/src/main/java/net/minecraft/server/PlayerInteractManager.java b/src/main/java/net/minecraft/server/PlayerInteractManager.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/PlayerInteractManager.java
@@ -256,11 +269,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/TileEntityFurnace.java
 +++ b/src/main/java/net/minecraft/server/TileEntityFurnace.java
 @@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I
-         while (i > 0) {
-             j = EntityExperienceOrb.getOrbValue(i);
-             i -= j;
--            entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, j));
-+            entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper
+             int k = EntityExperienceOrb.getOrbValue(j);
+ 
+             j -= k;
+-            world.addEntity(new EntityExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k));
++            world.addEntity(new EntityExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper
          }
  
      }
@@ -275,7 +288,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -            entity = new EntityExperienceOrb(world, x, y, z, 0);
 +            entity = new EntityExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper
          } else if (LightningStrike.class.isAssignableFrom(clazz)) {
-             entity = new EntityLightning(world, x, y, z, false);
+             entity = EntityTypes.LIGHTNING_BOLT.a(world);
          } else if (Firework.class.isAssignableFrom(clazz)) {
 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
diff --git a/Spigot-Server-Patches/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/Spigot-Server-Patches/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch
index c0ed9d44cf..5df98b2968 100644
--- a/Spigot-Server-Patches/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch
+++ b/Spigot-Server-Patches/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch
@@ -35,9 +35,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/server/EntityFallingBlock.java
 @@ -0,0 +0,0 @@ public class EntityFallingBlock extends Entity {
      @Override
-     protected void a(NBTTagCompound nbttagcompound) {
-         this.block = GameProfileSerializer.d(nbttagcompound.getCompound("BlockState"));
-+
+     protected void loadData(NBTTagCompound nbttagcompound) {
+         this.block = GameProfileSerializer.c(nbttagcompound.getCompound("BlockState"));
 +        // Paper start - Block FallingBlocks with Command Blocks
 +        // Check mappings on update - dc = "repeating_command_block" - dd = "chain_command_block"
 +        final Block b = this.block.getBlock();
@@ -45,7 +44,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            this.block = Blocks.STONE.getBlockData();
 +        }
 +        // Paper end
-+
          this.ticksLived = nbttagcompound.getInt("Time");
          if (nbttagcompound.hasKeyOfType("HurtEntities", 99)) {
              this.hurtEntities = nbttagcompound.getBoolean("HurtEntities");
diff --git a/Spigot-Server-Patches/Firework-API-s.patch b/Spigot-Server-Patches/Firework-API-s.patch
index 1ec335e982..cd5ddd74de 100644
--- a/Spigot-Server-Patches/Firework-API-s.patch
+++ b/Spigot-Server-Patches/Firework-API-s.patch
@@ -8,26 +8,17 @@ diff --git a/src/main/java/net/minecraft/server/EntityFireworks.java b/src/main/
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/EntityFireworks.java
 +++ b/src/main/java/net/minecraft/server/EntityFireworks.java
-@@ -0,0 +0,0 @@ package net.minecraft.server;
- import java.util.Iterator;
- import java.util.List;
- import java.util.OptionalInt;
-+import java.util.UUID;
-+
- import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
- 
- public class EntityFireworks extends Entity implements IProjectile {
-@@ -0,0 +0,0 @@ public class EntityFireworks extends Entity implements IProjectile {
+@@ -0,0 +0,0 @@ public class EntityFireworks extends IProjectile {
      public static final DataWatcherObject<Boolean> SHOT_AT_ANGLE = DataWatcher.a(EntityFireworks.class, DataWatcherRegistry.i);
      private int ticksFlown;
      public int expectedLifespan;
 -    private EntityLiving ridingEntity;
 +    private EntityLiving ridingEntity; public final EntityLiving getBoostedEntity() { return this.ridingEntity; } // Paper - OBFHELPER
-+    public UUID spawningEntity; // Paper
++    public java.util.UUID spawningEntity; // Paper
  
      public EntityFireworks(EntityTypes<? extends EntityFireworks> entitytypes, World world) {
          super(entitytypes, world);
-@@ -0,0 +0,0 @@ public class EntityFireworks extends Entity implements IProjectile {
+@@ -0,0 +0,0 @@ public class EntityFireworks extends IProjectile {
          }
  
          nbttagcompound.setBoolean("ShotAtAngle", (Boolean) this.datawatcher.get(EntityFireworks.SHOT_AT_ANGLE));
@@ -39,7 +30,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      @Override
-@@ -0,0 +0,0 @@ public class EntityFireworks extends Entity implements IProjectile {
+@@ -0,0 +0,0 @@ public class EntityFireworks extends IProjectile {
          if (nbttagcompound.hasKey("ShotAtAngle")) {
              this.datawatcher.set(EntityFireworks.SHOT_AT_ANGLE, nbttagcompound.getBoolean("ShotAtAngle"));
          }
@@ -56,10 +47,10 @@ diff --git a/src/main/java/net/minecraft/server/ItemCrossbow.java b/src/main/jav
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/ItemCrossbow.java
 +++ b/src/main/java/net/minecraft/server/ItemCrossbow.java
-@@ -0,0 +0,0 @@ public class ItemCrossbow extends ItemProjectileWeapon {
+@@ -0,0 +0,0 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable
  
              if (flag1) {
-                 object = new EntityFireworks(world, itemstack1, entityliving.locX(), entityliving.getHeadY() - 0.15000000596046448D, entityliving.locZ(), true);
+                 object = new EntityFireworks(world, itemstack1, entityliving, entityliving.locX(), entityliving.getHeadY() - 0.15000000596046448D, entityliving.locZ(), true);
 +                ((EntityFireworks) object).spawningEntity = entityliving.getUniqueID(); // Paper
              } else {
                  object = a(world, entityliving, itemstack, itemstack1);
@@ -71,7 +62,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public class ItemFireworks extends Item {
              Vec3D vec3d = itemactioncontext.getPos();
              EnumDirection enumdirection = itemactioncontext.getClickedFace();
-             EntityFireworks entityfireworks = new EntityFireworks(world, vec3d.x + (double) enumdirection.getAdjacentX() * 0.15D, vec3d.y + (double) enumdirection.getAdjacentY() * 0.15D, vec3d.z + (double) enumdirection.getAdjacentZ() * 0.15D, itemstack);
+             EntityFireworks entityfireworks = new EntityFireworks(world, itemactioncontext.getEntity(), vec3d.x + (double) enumdirection.getAdjacentX() * 0.15D, vec3d.y + (double) enumdirection.getAdjacentY() * 0.15D, vec3d.z + (double) enumdirection.getAdjacentZ() * 0.15D, itemstack);
 +            entityfireworks.spawningEntity = itemactioncontext.getEntity().getUniqueID(); // Paper
  
              world.addEntity(entityfireworks);
@@ -94,53 +85,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/NBTTagCompound.java
 +++ b/src/main/java/net/minecraft/server/NBTTagCompound.java
 @@ -0,0 +0,0 @@ public class NBTTagCompound implements NBTBase {
-         return new UUID(this.getLong(s + "Most"), this.getLong(s + "Least"));
+         return GameProfileSerializer.a(this.get(s));
      }
  
--    public boolean b(String s) {
-+    public final boolean hasUUID(String s) { return this.b(s); } public boolean b(String s) { // Paper - OBFHELPER
-         return this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99);
-     }
++    public final boolean hasUUID(String s) { return this.b(s); } // Paper - OBFHELPER
+     public boolean b(String s) {
+         NBTBase nbtbase = this.get(s);
  
 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
 +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
-@@ -0,0 +0,0 @@ package org.bukkit.craftbukkit.entity;
- 
- import java.util.Random;
- import net.minecraft.server.EntityFireworks;
-+import net.minecraft.server.EntityLiving;
- import net.minecraft.server.ItemStack;
- import net.minecraft.server.Items;
- import org.bukkit.Material;
-@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.CraftServer;
- import org.bukkit.craftbukkit.inventory.CraftItemStack;
- import org.bukkit.entity.EntityType;
- import org.bukkit.entity.Firework;
-+import org.bukkit.entity.LivingEntity;
- import org.bukkit.inventory.meta.FireworkMeta;
- 
-+import java.util.UUID;
-+
- public class CraftFirework extends CraftEntity implements Firework {
- 
-     private final Random random = new Random();
-@@ -0,0 +0,0 @@ public class CraftFirework extends CraftEntity implements Firework {
+@@ -0,0 +0,0 @@ public class CraftFirework extends CraftProjectile implements Firework {
      public void setShotAtAngle(boolean shotAtAngle) {
          getHandle().getDataWatcher().set(EntityFireworks.SHOT_AT_ANGLE, shotAtAngle);
      }
 +
 +    // Paper start
 +    @Override
-+    public UUID getSpawningEntity() {
++    public java.util.UUID getSpawningEntity() {
 +        return getHandle().spawningEntity;
 +    }
 +
 +    @Override
-+    public LivingEntity getBoostedEntity() {
-+        EntityLiving boostedEntity = getHandle().getBoostedEntity();
-+        return boostedEntity != null ? (LivingEntity) boostedEntity.getBukkitEntity() : null;
++    public org.bukkit.entity.LivingEntity getBoostedEntity() {
++        net.minecraft.server.EntityLiving boostedEntity = getHandle().getBoostedEntity();
++        return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null;
 +    }
 +    // Paper end
  }
diff --git a/Spigot-Server-Patches/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/Spigot-Server-Patches/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch
index 0299dab3ac..33bb103e83 100644
--- a/Spigot-Server-Patches/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch
+++ b/Spigot-Server-Patches/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch
@@ -9,13 +9,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
 +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
 @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
-         this.u = new AtomicInteger();
+     private final PlayerMap playerMap;
+     public final Int2ObjectMap<PlayerChunkMap.EntityTracker> trackedEntities;
+     private final Long2ByteMap z;
+-    private final Queue<Runnable> A;
++    private final Queue<Runnable> A; private final Queue<Runnable> getUnloadQueueTasks() { return this.A; } // Paper - OBFHELPER
+     private int viewDistance;
+ 
+     // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
+@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
          this.playerMap = new PlayerMap();
          this.trackedEntities = new Int2ObjectOpenHashMap();
--        this.z = Queues.newConcurrentLinkedQueue();
-+        this.z = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper
+         this.z = new Long2ByteOpenHashMap();
+-        this.A = Queues.newConcurrentLinkedQueue();
++        this.A = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size()
          this.definedStructureManager = definedstructuremanager;
-         this.w = worldserver.getWorldProvider().getDimensionManager().a(file);
+         this.w = convertable_conversionsession.a(worldserver.getDimensionKey());
          this.world = worldserver;
 @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
          // Spigot start
@@ -30,9 +39,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
          Runnable runnable;
  
--        while ((booleansupplier.getAsBoolean() || this.z.size() > 2000) && (runnable = (Runnable) this.z.poll()) != null) {
-+        int queueTarget = Math.min(this.z.size() - 100, (int) (this.z.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well
-+        while ((booleansupplier.getAsBoolean() || this.z.size() > queueTarget) && (runnable = (Runnable) this.z.poll()) != null) { // Paper - Target this queue as well
+-        while ((booleansupplier.getAsBoolean() || this.A.size() > 2000) && (runnable = (Runnable) this.A.poll()) != null) {
++        int queueTarget = Math.min(this.getUnloadQueueTasks().size() - 100, (int) (this.getUnloadQueueTasks().size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well
++        while ((booleansupplier.getAsBoolean() || this.getUnloadQueueTasks().size() > queueTarget) && (runnable = (Runnable)this.getUnloadQueueTasks().poll()) != null) { // Paper - Target this queue as well
              runnable.run();
          }
  
diff --git a/Spigot-Server-Patches/Optimise-BlockState-s-hashCode-equals.patch b/Spigot-Server-Patches/Optimise-BlockState-s-hashCode-equals.patch
index b632c7e2a3..8c1260258b 100644
--- a/Spigot-Server-Patches/Optimise-BlockState-s-hashCode-equals.patch
+++ b/Spigot-Server-Patches/Optimise-BlockState-s-hashCode-equals.patch
@@ -8,38 +8,6 @@ object identity checks safely.
 
 Use a simpler optimized hashcode
 
-diff --git a/src/main/java/net/minecraft/server/IBlockState.java b/src/main/java/net/minecraft/server/IBlockState.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/server/IBlockState.java
-+++ b/src/main/java/net/minecraft/server/IBlockState.java
-@@ -0,0 +0,0 @@ public abstract class IBlockState<T extends Comparable<T>>
-     }
- 
-     public boolean equals(Object object) {
--        if (this == object) {
--            return true;
--        } else if (!(object instanceof IBlockState)) {
--            return false;
--        } else {
--            IBlockState<?> blockstate = (IBlockState) object;
--
--            return this.a.equals(blockstate.a) && this.b.equals(blockstate.b);
--        }
-+        return this == object; // Paper - only one instance per configuration
-     }
- 
-+    private static final java.util.concurrent.atomic.AtomicInteger hashId = new java.util.concurrent.atomic.AtomicInteger(1); // Paper - only one instance per configuration
-+    private final int hashCode = 92821 * hashId.getAndIncrement(); // Paper - only one instance per configuration
-     public final int hashCode() {
--        if (this.c == null) {
--            this.c = this.c();
--        }
--
--        return this.c;
-+        return this.hashCode; // Paper - only one instance per configuration
-     }
- 
-     public int c() {
 diff --git a/src/main/java/net/minecraft/server/BlockStateBoolean.java b/src/main/java/net/minecraft/server/BlockStateBoolean.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/BlockStateBoolean.java
@@ -82,3 +50,44 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          if (this == object) {
              return true;
          } else if (object instanceof BlockStateInteger && super.equals(object)) {
+diff --git a/src/main/java/net/minecraft/server/IBlockState.java b/src/main/java/net/minecraft/server/IBlockState.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/server/IBlockState.java
++++ b/src/main/java/net/minecraft/server/IBlockState.java
+@@ -0,0 +0,0 @@ public abstract class IBlockState<T extends Comparable<T>> {
+                 return DataResult.error("Unable to read property: " + this + " with value: " + s1);
+             });
+         }, this::a);
+-        this.e = this.d.xmap(this::b, IBlockState.a::b);
++        this.e = this.d.xmap(this::b, (IBlockState.a<T> param) -> { return param.b(); }); // Paper - decompile fix
+         this.a = oclass;
+         this.b = s;
+     }
+@@ -0,0 +0,0 @@ public abstract class IBlockState<T extends Comparable<T>> {
+     }
+ 
+     public boolean equals(Object object) {
+-        if (this == object) {
+-            return true;
+-        } else if (!(object instanceof IBlockState)) {
+-            return false;
+-        } else {
+-            IBlockState<?> iblockstate = (IBlockState) object;
+-
+-            return this.a.equals(iblockstate.a) && this.b.equals(iblockstate.b);
+-        }
++        return this == object; // Paper - only one instance per configuration
+     }
+ 
++    private static final java.util.concurrent.atomic.AtomicInteger hashId = new java.util.concurrent.atomic.AtomicInteger(1); // Paper - only one instance per configuration
++    private final int hashCode = 92821 * hashId.getAndIncrement(); // Paper - only one instance per configuration
+     public final int hashCode() {
+         if (this.c == null) {
+             this.c = this.b();
+         }
+ 
+-        return this.c;
++        return this.hashCode; // Paper - only one instance per configuration
+     }
+ 
+     public int b() {
diff --git a/Spigot-Server-Patches/Optimise-removeQueue.patch b/Spigot-Server-Patches/Optimise-removeQueue.patch
index a00af58257..a475831e28 100644
--- a/Spigot-Server-Patches/Optimise-removeQueue.patch
+++ b/Spigot-Server-Patches/Optimise-removeQueue.patch
@@ -54,7 +54,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
 @@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener {
  
-                     return LoginListener.this.server.Y() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null;
+                     return LoginListener.this.server.U() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null;
                  }
 -            };
 -
diff --git a/Spigot-Server-Patches/Optimize-ItemStack.isEmpty.patch b/Spigot-Server-Patches/Optimize-ItemStack.isEmpty.patch
index f4374a69ce..cb8176d566 100644
--- a/Spigot-Server-Patches/Optimize-ItemStack.isEmpty.patch
+++ b/Spigot-Server-Patches/Optimize-ItemStack.isEmpty.patch
@@ -13,8 +13,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      public boolean isEmpty() {
--        return this == ItemStack.a ? true : (this.getItem() != null && this.getItem() != Items.AIR ? this.count <= 0 : true);
-+        return this == ItemStack.a || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper
+-        return this == ItemStack.b ? true : (this.getItem() != null && this.getItem() != Items.AIR ? this.count <= 0 : true);
++        return this == ItemStack.NULL_ITEM || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper
      }
  
      public ItemStack cloneAndSubtract(int i) {
diff --git a/Spigot-Server-Patches/Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/Spigot-Server-Patches/Remove-FishingHook-reference-on-Craft-Entity-removal.patch
index d99e588e5f..b19c38731a 100644
--- a/Spigot-Server-Patches/Remove-FishingHook-reference-on-Craft-Entity-removal.patch
+++ b/Spigot-Server-Patches/Remove-FishingHook-reference-on-Craft-Entity-removal.patch
@@ -8,7 +8,7 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/sr
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
 +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
-@@ -0,0 +0,0 @@ public class CraftFishHook extends AbstractProjectile implements FishHook {
+@@ -0,0 +0,0 @@ public class CraftFishHook extends CraftProjectile implements FishHook {
          Validate.isTrue(chance >= 0 && chance <= 1, "The bite chance must be between 0 and 1.");
          this.biteChance = chance;
      }