diff --git a/patches/server/Add-API-for-quit-reason.patch b/patches/server/Add-API-for-quit-reason.patch
index da86222089..5e1b6d843b 100644
--- a/patches/server/Add-API-for-quit-reason.patch
+++ b/patches/server/Add-API-for-quit-reason.patch
@@ -30,7 +30,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
 @@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
      public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
-     public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
+     public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent
      public @Nullable String clientBrandName = null; // Paper - Brand support
 +    public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
  
diff --git a/patches/server/Add-PlayerAdvancementCriterionGrantEvent.patch b/patches/server/Add-PlayerAdvancementCriterionGrantEvent.patch
index 35a61ff910..8d47ecde0e 100644
--- a/patches/server/Add-PlayerAdvancementCriterionGrantEvent.patch
+++ b/patches/server/Add-PlayerAdvancementCriterionGrantEvent.patch
@@ -12,12 +12,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          boolean flag1 = advancementprogress.isDone();
  
          if (advancementprogress.grantProgress(criterionName)) {
-+            // Paper start
++            // Paper start - Add PlayerAdvancementCriterionGrantEvent
 +            if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.toBukkit(), criterionName).callEvent()) {
 +                advancementprogress.revokeProgress(criterionName);
 +                return false;
 +            }
-+            // Paper end
++            // Paper end - Add PlayerAdvancementCriterionGrantEvent
              this.unregisterListeners(advancement);
              this.progressChanged.add(advancement);
              flag = true;
diff --git a/patches/server/Add-PlayerArmorChangeEvent.patch b/patches/server/Add-PlayerArmorChangeEvent.patch
index d70a0bdb25..376e162d8d 100644
--- a/patches/server/Add-PlayerArmorChangeEvent.patch
+++ b/patches/server/Add-PlayerArmorChangeEvent.patch
@@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemstack1);
 +                    new PlayerArmorChangeEvent((Player) this.getBukkitEntity(), PlayerArmorChangeEvent.SlotType.valueOf(enumitemslot.name()), oldItem, newItem).callEvent();
 +                }
-+                // Paper end
++                // Paper end - PlayerArmorChangeEvent
                  if (map == null) {
                      map = Maps.newEnumMap(EquipmentSlot.class);
                  }
diff --git a/patches/server/Add-PlayerJumpEvent.patch b/patches/server/Add-PlayerJumpEvent.patch
index 0ecf44effa..d83dd9ac68 100644
--- a/patches/server/Add-PlayerJumpEvent.patch
+++ b/patches/server/Add-PlayerJumpEvent.patch
@@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
                              if (this.player.onGround() && !packet.isOnGround() && flag) {
 -                                this.player.jumpFromGround();
-+                                // Paper start - Add player jump event
++                                // Paper start - Add PlayerJumpEvent
 +                                Player player = this.getCraftPlayer();
 +                                Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location.
 +                                Location to = player.getLocation().clone(); // Start off the To location as the Players current location.
@@ -40,7 +40,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                                    this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet());
 +                                    return;
 +                                }
-+                                // Paper end
++                                // Paper end - Add PlayerJumpEvent
                              }
  
                              boolean flag1 = this.player.verticalCollisionBelow;
diff --git a/patches/server/Add-PlayerKickEvent-causes.patch b/patches/server/Add-PlayerKickEvent-causes.patch
index df77573c22..9d0b7811bf 100644
--- a/patches/server/Add-PlayerKickEvent-causes.patch
+++ b/patches/server/Add-PlayerKickEvent-causes.patch
@@ -110,7 +110,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -                this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE);
 +                this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause
              });
-             // Paper endg
+             // Paper endg - This needs to be handled on the main thread for plugins
          }
 @@ -0,0 +0,0 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
                  }
@@ -258,11 +258,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              }
  
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
-         // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - run this async
+         // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - AsyncTabCompleteEvent; run this async
          // CraftBukkit start
          if (this.chatSpamTickCount.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper - configurable tab spam limits
--            server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]))); // Paper
-+            server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause
+-            server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam"))); // Paper - AsyncTabCompleteEvent
++            server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - AsyncTabCompleteEvent & kick event cause
              return;
          }
          // Paper start
diff --git a/patches/server/Add-critical-damage-API.patch b/patches/server/Add-critical-damage-API.patch
index 0e34b898ce..a4cadcf76e 100644
--- a/patches/server/Add-critical-damage-API.patch
+++ b/patches/server/Add-critical-damage-API.patch
@@ -38,7 +38,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -                    boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity;
 +                    boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; // Paper - Add critical damage API; diff on change
  
-                     flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper
+                     flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper - Toggleable player crits
                      flag2 = flag2 && !this.isSprinting();
 @@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity {
                      }
diff --git a/patches/server/Add-experience-points-API.patch b/patches/server/Add-experience-points-API.patch
index 548916b614..9604fa3dbb 100644
--- a/patches/server/Add-experience-points-API.patch
+++ b/patches/server/Add-experience-points-API.patch
@@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2);
 +        return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2); // Paper - diff on change; calculateTotalExperiencePoints
      }
-     // Paper start - send SoundEffect to everyone who can see fromEntity
+     // Paper start - send while respecting visibility
      private static void sendSoundEffect(Player fromEntity, double x, double y, double z, SoundEvent soundEffect, SoundSource soundCategory, float volume, float pitch) {
 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
diff --git a/patches/server/Allow-specifying-a-custom-authentication-servers-dow.patch b/patches/server/Allow-specifying-a-custom-authentication-servers-dow.patch
index 41de4fbb8e..637cf55035 100644
--- a/patches/server/Allow-specifying-a-custom-authentication-servers-dow.patch
+++ b/patches/server/Allow-specifying-a-custom-authentication-servers-dow.patch
@@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                          ServerLoginPacketListenerImpl.this.startClientVerification(ServerLoginPacketListenerImpl.this.createOfflineProfile(s1)); // Spigot
                      } else {
 -                        ServerLoginPacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.authservers_down"));
-+                        ServerLoginPacketListenerImpl.this.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.authenticationServersDown)); // Paper
++                        ServerLoginPacketListenerImpl.this.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.authenticationServersDown)); // Paper - Configurable kick message
                          ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable");
                      }
                      // CraftBukkit start - catch all exceptions
diff --git a/patches/server/AsyncTabCompleteEvent.patch b/patches/server/AsyncTabCompleteEvent.patch
index 349bbdae77..de3a841b62 100644
--- a/patches/server/AsyncTabCompleteEvent.patch
+++ b/patches/server/AsyncTabCompleteEvent.patch
@@ -23,18 +23,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      }
  
-+    // Paper start
++    // Paper start - AsyncTabCompleteEvent
 +    private static final java.util.concurrent.ExecutorService TAB_COMPLETE_EXECUTOR = java.util.concurrent.Executors.newFixedThreadPool(4,
 +        new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Tab Complete Thread - #%d").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build());
-+    // Paper end
++    // Paper end - AsyncTabCompleteEvent
      @Override
      public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) {
 -        PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
-+        // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - run this async
++        // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - AsyncTabCompleteEvent; run this async
          // CraftBukkit start
          if (this.chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
 -            this.disconnect(Component.translatable("disconnect.spam"));
-+            server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]))); // Paper
++            server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam"))); // Paper - AsyncTabCompleteEvent
              return;
          }
          // Paper start
@@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          }
          // Paper end
          // CraftBukkit end
-+        // Paper start - async tab completion
++        // Paper start - AsyncTabCompleteEvent
 +        TAB_COMPLETE_EXECUTOR.execute(() -> {
          StringReader stringreader = new StringReader(packet.getCommand());
  
@@ -86,7 +86,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join()));
 +            }
          });
-+        // Paper end - async tab completion
++        // Paper end - AsyncTabCompleteEvent
      }
  
      @Override
@@ -99,7 +99,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          }
  
 -        TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers);
-+        TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? io.papermc.paper.util.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), BlockPos.containing(pos)) : null); // Paper
++        TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? io.papermc.paper.util.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), BlockPos.containing(pos)) : null); // Paper - AsyncTabCompleteEvent
          this.getPluginManager().callEvent(tabEvent);
  
          return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions();
diff --git a/patches/server/Block-Enderpearl-Travel-Exploit.patch b/patches/server/Block-Enderpearl-Travel-Exploit.patch
index 6e87855cfb..66ff671e0a 100644
--- a/patches/server/Block-Enderpearl-Travel-Exploit.patch
+++ b/patches/server/Block-Enderpearl-Travel-Exploit.patch
@@ -28,7 +28,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                pearl.cachedOwner = null;
 +                pearl.ownerUUID = null;
 +            }
-+            // Paper end
++            // Paper end - Reset pearls when they stop being ticked
          }
  
          public void onTrackingStart(Entity entity) {
@@ -40,7 +40,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          if (nbt.hasUUID("Owner")) {
              this.ownerUUID = nbt.getUUID("Owner");
              this.cachedOwner = null;
-+            if (this instanceof ThrownEnderpearl && this.level() != null && this.level().paperConfig().fixes.disableUnloadedChunkEnderpearlExploit) { this.ownerUUID = null; } // Paper - Don't store shooter name for pearls to block enderpearl travel exploit
++            if (this instanceof ThrownEnderpearl && this.level() != null && this.level().paperConfig().fixes.disableUnloadedChunkEnderpearlExploit) { this.ownerUUID = null; } // Paper - Reset pearls when they stop being ticked; Don't store shooter name for pearls to block enderpearl travel exploit
          }
  
          this.leftOwner = nbt.getBoolean("LeftOwner");
diff --git a/patches/server/Brand-support.patch b/patches/server/Brand-support.patch
index f277adc28a..569c55c6ac 100644
--- a/patches/server/Brand-support.patch
+++ b/patches/server/Brand-support.patch
@@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
      public boolean isRealPlayer; // Paper
      public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
-     public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
+     public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent
 +    public @Nullable String clientBrandName = null; // Paper - Brand support
  
      // Paper start - replace player chunk loader
diff --git a/patches/server/Break-up-and-make-tab-spam-limits-configurable.patch b/patches/server/Break-up-and-make-tab-spam-limits-configurable.patch
index f0679286d5..31e847c6eb 100644
--- a/patches/server/Break-up-and-make-tab-spam-limits-configurable.patch
+++ b/patches/server/Break-up-and-make-tab-spam-limits-configurable.patch
@@ -43,10 +43,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              --this.chatSpamTickCount;
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
      public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) {
-         // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - run this async
+         // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - AsyncTabCompleteEvent; run this async
          // CraftBukkit start
 -        if (this.chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
 +        if (this.chatSpamTickCount.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper - configurable tab spam limits
-             server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]))); // Paper
+             server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam"))); // Paper - AsyncTabCompleteEvent
              return;
          }
diff --git a/patches/server/Brigadier-Mojang-API.patch b/patches/server/Brigadier-Mojang-API.patch
index 48a4aa8e6a..f525d15bd4 100644
--- a/patches/server/Brigadier-Mojang-API.patch
+++ b/patches/server/Brigadier-Mojang-API.patch
@@ -163,7 +163,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                // Paper end - Brigadier API
              }
          });
-         // Paper end - async tab completion
+         // Paper end - AsyncTabCompleteEvent
 diff --git a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java
diff --git a/patches/server/Configurable-sprint-interruption-on-attack.patch b/patches/server/Configurable-sprint-interruption-on-attack.patch
index 0f7d80c74f..caa8a4210b 100644
--- a/patches/server/Configurable-sprint-interruption-on-attack.patch
+++ b/patches/server/Configurable-sprint-interruption-on-attack.patch
@@ -14,11 +14,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
                              this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D));
 -                            this.setSprinting(false);
-+                            // Paper start - Configuration option to disable automatic sprint interruption
++                            // Paper start - Configurable sprint interruption on attack
 +                            if (!this.level().paperConfig().misc.disableSprintInterruptionOnAttack) {
 +                                this.setSprinting(false);
 +                            }
-+                            // Paper end
++                            // Paper end - Configurable sprint interruption on attack
                          }
  
                          if (flag3) {
diff --git a/patches/server/Disable-Explicit-Network-Manager-Flushing.patch b/patches/server/Disable-Explicit-Network-Manager-Flushing.patch
index f992263de5..ceafd260ad 100644
--- a/patches/server/Disable-Explicit-Network-Manager-Flushing.patch
+++ b/patches/server/Disable-Explicit-Network-Manager-Flushing.patch
@@ -19,7 +19,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      // Paper start - NetworkClient implementation
      public int protocolVersion;
      public java.net.InetSocketAddress virtualHost;
-+    private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush");
++    private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); // Paper - Disable explicit network manager flushing
      // Paper end
  
      // Paper start - add utility methods
@@ -28,7 +28,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
          if (this.channel != null) {
 -            this.channel.flush();
-+            if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version
++            if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - Disable explicit network manager flushing; we don't need to explicit flush here, but allow opt in incase issues are found to a better version
          }
  
          if (this.tickCount++ % 20 == 0) {
diff --git a/patches/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch b/patches/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch
index b865a5b70f..2a8350cde3 100644
--- a/patches/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch
+++ b/patches/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch
@@ -18,6 +18,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            return;
 +        }
 +        // Paper end - Don't suggest if tab-complete is disabled
-         // Paper start - async tab completion
+         // Paper start - AsyncTabCompleteEvent
          TAB_COMPLETE_EXECUTOR.execute(() -> {
          StringReader stringreader = new StringReader(packet.getCommand());
diff --git a/patches/server/Dont-resend-blocks-on-interactions.patch b/patches/server/Dont-resend-blocks-on-interactions.patch
index 6f52d9166b..8058f13b59 100644
--- a/patches/server/Dont-resend-blocks-on-interactions.patch
+++ b/patches/server/Dont-resend-blocks-on-interactions.patch
@@ -123,7 +123,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc)
 -                player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above()));
 +                //player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above())); // Paper - Don't resync blocks
-             // Paper start  - extend Player Interact cancellation // TODO: consider merging this into the extracted method
+             // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method
              } else if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.StructureBlock) {
                  player.connection.send(new net.minecraft.network.protocol.game.ClientboundContainerClosePacket(this.player.containerMenu.containerId));
 diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java
diff --git a/patches/server/EndermanEscapeEvent.patch b/patches/server/EndermanEscapeEvent.patch
index 21976b9f4f..5149283ce7 100644
--- a/patches/server/EndermanEscapeEvent.patch
+++ b/patches/server/EndermanEscapeEvent.patch
@@ -15,11 +15,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          this.setTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true);
      }
  
-+    // Paper start
++    // Paper start - EndermanEscapeEvent
 +    private boolean tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason reason) {
 +        return new com.destroystokyo.paper.event.entity.EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent();
 +    }
-+    // Paper end
++    // Paper end - EndermanEscapeEvent
 +
      @Override
      public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) {
@@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              float f = this.getLightLevelDependentMagicValue();
  
 -            if (f > 0.5F && this.level().canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) {
-+            if (f > 0.5F && this.level().canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper
++            if (f > 0.5F && this.level().canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper - EndermanEscapeEvent
                  this.setTarget((LivingEntity) null);
                  this.teleport();
              }
@@ -37,13 +37,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              } else {
                  flag1 = flag && this.hurtWithCleanWater(source, (ThrownPotion) source.getDirectEntity(), amount);
  
-+                if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start
++                if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - EndermanEscapeEvent
                  for (int i = 0; i < 64; ++i) {
                      if (this.teleport()) {
                          return true;
                      }
                  }
-+                } // Paper end
++                } // Paper - EndermanEscapeEvent
  
                  return flag1;
              }
@@ -52,7 +52,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  if (this.target != null && !this.enderman.isPassenger()) {
                      if (this.enderman.isLookingAtMe((Player) this.target)) {
 -                        if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D) {
-+                        if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D && this.enderman.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.STARE)) { // Paper
++                        if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D && this.enderman.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.STARE)) { // Paper - EndermanEscapeEvent
                              this.enderman.teleport();
                          }
  
diff --git a/patches/server/Execute-chunk-tasks-mid-tick.patch b/patches/server/Execute-chunk-tasks-mid-tick.patch
index e4f1063a50..136f2ce010 100644
--- a/patches/server/Execute-chunk-tasks-mid-tick.patch
+++ b/patches/server/Execute-chunk-tasks-mid-tick.patch
@@ -165,7 +165,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                // Paper end - execute chunk tasks during tick
              }
          }
-         this.blockEntityTickers.removeAll(toRemove);
+         this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075
 @@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
      public <T extends Entity> void guardEntityTick(Consumer<T> tickConsumer, T entity) {
          try {
diff --git a/patches/server/Extend-Player-Interact-cancellation.patch b/patches/server/Extend-Player-Interact-cancellation.patch
index 3a31b159a5..0f65b957cd 100644
--- a/patches/server/Extend-Player-Interact-cancellation.patch
+++ b/patches/server/Extend-Player-Interact-cancellation.patch
@@ -20,7 +20,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
                  // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc)
                  player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above()));
-+            // Paper start  - extend Player Interact cancellation // TODO: consider merging this into the extracted method
++            // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method
 +            } else if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.StructureBlock) {
 +                player.connection.send(new net.minecraft.network.protocol.game.ClientboundContainerClosePacket(this.player.containerMenu.containerId));
 +            } else if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.CommandBlock) {
diff --git a/patches/server/Fill-Profile-Property-Events.patch b/patches/server/Fill-Profile-Property-Events.patch
index c5d92dfcdd..703fd5bbab 100644
--- a/patches/server/Fill-Profile-Property-Events.patch
+++ b/patches/server/Fill-Profile-Property-Events.patch
@@ -54,7 +54,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              if (optional.isPresent() && !booleansupplier.getAsBoolean()) {
                  UUID uuid = ((GameProfile) optional.get()).getId();
 -                ProfileResult profileresult = apiServices.sessionService().fetchProfile(uuid, true);
-+                ProfileResult profileresult = apiServices.sessionService() instanceof com.destroystokyo.paper.profile.PaperMinecraftSessionService paperMinecraftSessionService ? paperMinecraftSessionService.fetchProfile(optional.get(), true) : apiServices.sessionService().fetchProfile(uuid, true); // Paper
++                ProfileResult profileresult = apiServices.sessionService() instanceof com.destroystokyo.paper.profile.PaperMinecraftSessionService paperMinecraftSessionService ? paperMinecraftSessionService.fetchProfile(optional.get(), true) : apiServices.sessionService().fetchProfile(uuid, true); // Paper - FillProfileEvent
  
                  return profileresult != null ? Optional.ofNullable(profileresult.profile()) : optional;
              } else {
diff --git a/patches/server/Fix-MC-117075-TE-Unload-Lag-Spike.patch b/patches/server/Fix-MC-117075-Block-entity-unload-lag-spike.patch
similarity index 82%
rename from patches/server/Fix-MC-117075-TE-Unload-Lag-Spike.patch
rename to patches/server/Fix-MC-117075-Block-entity-unload-lag-spike.patch
index 863c961174..92238a2190 100644
--- a/patches/server/Fix-MC-117075-TE-Unload-Lag-Spike.patch
+++ b/patches/server/Fix-MC-117075-Block-entity-unload-lag-spike.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: mezz <tehgeek@gmail.com>
 Date: Wed, 9 Aug 2017 17:51:22 -0500
-Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike
+Subject: [PATCH] Fix MC-117075: Block entity unload lag spike
 
 
 diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
@@ -12,8 +12,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          boolean flag = this.tickRateManager().runsNormally();
  
          int tilesThisCycle = 0;
-+        var toRemove = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<TickingBlockEntity>(); // Paper - use removeAll
-+        toRemove.add(null);
++        var toRemove = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<TickingBlockEntity>(); // Paper - Fix MC-117075; use removeAll
++        toRemove.add(null); // Paper - Fix MC-117075
          for (tileTickPosition = 0; tileTickPosition < this.blockEntityTickers.size(); tileTickPosition++) { // Paper - Disable tick limiters
              this.tileTickPosition = (this.tileTickPosition < this.blockEntityTickers.size()) ? this.tileTickPosition : 0;
              TickingBlockEntity tickingblockentity = (TickingBlockEntity) this.blockEntityTickers.get(this.tileTickPosition);
@@ -22,13 +22,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  // Spigot start
                  tilesThisCycle--;
 -                this.blockEntityTickers.remove(this.tileTickPosition--);
-+                toRemove.add(tickingblockentity); // Paper - use removeAll
++                toRemove.add(tickingblockentity); // Paper - Fix MC-117075; use removeAll
                  // Spigot end
              } else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) {
                  tickingblockentity.tick();
              }
          }
-+        this.blockEntityTickers.removeAll(toRemove);
++        this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075
  
          this.timings.tileEntityTick.stopTiming(); // Spigot
          this.tickingBlockEntities = false;
diff --git a/patches/server/Implement-extended-PaperServerListPingEvent.patch b/patches/server/Implement-extended-PaperServerListPingEvent.patch
index 18f8425c53..cbea780543 100644
--- a/patches/server/Implement-extended-PaperServerListPingEvent.patch
+++ b/patches/server/Implement-extended-PaperServerListPingEvent.patch
@@ -199,7 +199,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              return new ServerStatus.Players(i, list.size(), List.of());
          } else {
 -            int j = Math.min(list.size(), 12);
-+            int j = Math.min(list.size(), org.spigotmc.SpigotConfig.playerSample); // Paper
++            int j = Math.min(list.size(), org.spigotmc.SpigotConfig.playerSample); // Paper - PaperServerListPingEvent
              ObjectArrayList<GameProfile> objectarraylist = new ObjectArrayList(j);
              int k = Mth.nextInt(this.random, 0, list.size() - j);
  
diff --git a/patches/server/Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch b/patches/server/Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch
index ae1c5e5fdb..c25fff011f 100644
--- a/patches/server/Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch
+++ b/patches/server/Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch
@@ -78,7 +78,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
 @@ -0,0 +0,0 @@ public final class NaturalSpawner {
  
-                                     // Paper start
+                                     // Paper start - PreCreatureSpawnEvent
                                      PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
 +                                    // Paper start - per player mob count backoff
 +                                    if (doSpawning == PreSpawnStatus.ABORT || doSpawning == PreSpawnStatus.CANCELLED) {
diff --git a/patches/server/Optimise-chunk-tick-iteration.patch b/patches/server/Optimise-chunk-tick-iteration.patch
index 65168afa41..b6d1a0289e 100644
--- a/patches/server/Optimise-chunk-tick-iteration.patch
+++ b/patches/server/Optimise-chunk-tick-iteration.patch
@@ -216,7 +216,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
  
 -                Util.shuffle(list, this.level.random);
--                // Paper start - call player naturally spawn event
+-                // Paper start - PlayerNaturallySpawnCreaturesEvent
 -                int chunkRange = level.spigotConfig.mobSpawnRange;
 -                chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange;
 -                chunkRange = Math.min(chunkRange, 8);
@@ -257,7 +257,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in anyPlayerCloseEnoughForSpawning
 +                    player.playerNaturallySpawnedEvent = event;
                  }
--                // Paper end
+-                // Paper end - PlayerNaturallySpawnCreaturesEvent
 +                // Paper end - optimise chunk tick iteration
                  int l = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
                  boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
diff --git a/patches/server/Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server/Optimize-Network-Manager-and-add-advanced-packet-sup.patch
index 8143e9fdf6..3442c50a9d 100644
--- a/patches/server/Optimize-Network-Manager-and-add-advanced-packet-sup.patch
+++ b/patches/server/Optimize-Network-Manager-and-add-advanced-packet-sup.patch
@@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      // Spigot Start
 @@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
      public java.net.InetSocketAddress virtualHost;
-     private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush");
+     private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); // Paper - Disable explicit network manager flushing
      // Paper end
 +    // Paper start - Optimize network
 +    public boolean isPending = true;
diff --git a/patches/server/Optional-per-player-mob-spawns.patch b/patches/server/Optional-per-player-mob-spawns.patch
index 17e26788b3..10612f971c 100644
--- a/patches/server/Optional-per-player-mob-spawns.patch
+++ b/patches/server/Optional-per-player-mob-spawns.patch
@@ -194,14 +194,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
              while (k < 3) {
 @@ -0,0 +0,0 @@ public final class NaturalSpawner {
-                                     // Paper start
+                                     // Paper start - PreCreatureSpawnEvent
                                      PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
                                      if (doSpawning == PreSpawnStatus.ABORT) {
 -                                        return;
 +                                        return j; // Paper - Optional per player mob spawns
                                      }
                                      if (doSpawning == PreSpawnStatus.SUCCESS && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) {
-                                         // Paper end
+                                         // Paper end - PreCreatureSpawnEvent
                                          Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type);
  
                                          if (entityinsentient == null) {
diff --git a/patches/server/PlayerNaturallySpawnCreaturesEvent.patch b/patches/server/PlayerNaturallySpawnCreaturesEvent.patch
index d73a2e25b3..4a900da4b1 100644
--- a/patches/server/PlayerNaturallySpawnCreaturesEvent.patch
+++ b/patches/server/PlayerNaturallySpawnCreaturesEvent.patch
@@ -27,7 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  }
  
                  entityplayer = (ServerPlayer) iterator.next();
-+                // Paper start - add PlayerNaturallySpawnCreaturesEvent
++                // Paper start - PlayerNaturallySpawnCreaturesEvent
 +                com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event;
 +                blockRange = 16384.0D;
 +                if (reducedRange) {
@@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    if (event == null || event.isCancelled()) return false;
 +                    blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4));
 +                }
-+                // Paper end
++                // Paper end - PlayerNaturallySpawnCreaturesEvent
              } while (!this.playerIsCloseEnoughForSpawning(entityplayer, chunkcoordintpair, blockRange)); // Spigot
  
              return true;
@@ -47,7 +47,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
  
                  Util.shuffle(list, this.level.random);
-+                // Paper start - call player naturally spawn event
++                // Paper start - PlayerNaturallySpawnCreaturesEvent
 +                int chunkRange = level.spigotConfig.mobSpawnRange;
 +                chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange;
 +                chunkRange = Math.min(chunkRange, 8);
@@ -55,7 +55,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange);
 +                    entityPlayer.playerNaturallySpawnedEvent.callEvent();
 +                }
-+                // Paper end
++                // Paper end - PlayerNaturallySpawnCreaturesEvent
                  int l = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
                  boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
                  Iterator iterator1 = list.iterator();
@@ -67,7 +67,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      // CraftBukkit end
      public boolean isRealPlayer; // Paper
      public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
-+    public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
++    public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent
  
      // Paper start - replace player chunk loader
      private final java.util.concurrent.atomic.AtomicReference<io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances> viewDistances = new java.util.concurrent.atomic.AtomicReference<>(new io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances(-1, -1, -1));
diff --git a/patches/server/PlayerPickupExperienceEvent.patch b/patches/server/PlayerPickupExperienceEvent.patch
index bba1bc73cf..0d12051913 100644
--- a/patches/server/PlayerPickupExperienceEvent.patch
+++ b/patches/server/PlayerPickupExperienceEvent.patch
@@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public void playerTouch(Player player) {
          if (!this.level().isClientSide) {
 -            if (player.takeXpDelay == 0) {
-+            if (player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper
++            if (player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent
                  player.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(player, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2;
                  player.take(this, 1);
                  int i = this.repairPlayerItems(player, this.value);
diff --git a/patches/server/PreCreatureSpawnEvent.patch b/patches/server/PreCreatureSpawnEvent.patch
index f01034f65c..1a4ddbcb99 100644
--- a/patches/server/PreCreatureSpawnEvent.patch
+++ b/patches/server/PreCreatureSpawnEvent.patch
@@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
              blockposition_mutableblockposition.setWithOffset(blockposition, i1, k, j1);
              if (worldserver.getWorldBorder().isWithinBounds((BlockPos) blockposition_mutableblockposition) && SpawnUtil.moveToPossibleSpawnPosition(worldserver, k, blockposition_mutableblockposition, spawnutil_a)) {
-+                // Paper start
++                // Paper start - PreCreatureSpawnEvent
 +                String key = EntityType.getKey(entitytypes).getPath();
 +                org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key);
 +
@@ -54,7 +54,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    }
 +                    break;
 +                }
-+                // Paper end
++                // Paper end - PreCreatureSpawnEvent
                  T t0 = entitytypes.create(worldserver, (CompoundTag) null, null, blockposition_mutableblockposition, enummobspawn, false, false); // CraftBukkit - decompile error
  
                  if (t0 != null) {
@@ -66,7 +66,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      @Nullable
      public T spawn(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Consumer<T> consumer, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
          // CraftBukkit end
-+        // Paper start - Call PreCreatureSpawnEvent
++        // Paper start - PreCreatureSpawnEvent
 +        org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath());
 +        if (type != null) {
 +            com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event;
@@ -79,7 +79,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                return null;
 +            }
 +        }
-+        // Paper end
++        // Paper end - PreCreatureSpawnEvent
          T t0 = this.create(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1);
  
          if (t0 != null) {
@@ -104,7 +104,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                          } else if (!SpawnPlacements.checkSpawnRules((EntityType) optional.get(), world, MobSpawnType.SPAWNER, blockposition1, world.getRandom())) {
                              continue;
                          }
-+                        // Paper start
++                        // Paper start - PreCreatureSpawnEvent
 +                        EntityType<?> entityType = optional.get();
 +                        String key = EntityType.getKey(entityType).getPath();
 +
@@ -124,7 +124,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                                continue;
 +                            }
 +                        }
-+                        // Paper end
++                        // Paper end - PreCreatureSpawnEvent
  
                          Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> {
                              entity1.moveTo(d0, d1, d2, entity1.getYRot(), entity1.getXRot());
@@ -137,13 +137,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                                      }
  
 -                                    if (NaturalSpawner.isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) {
-+                                    // Paper start
++                                    // Paper start - PreCreatureSpawnEvent
 +                                    PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
 +                                    if (doSpawning == PreSpawnStatus.ABORT) {
 +                                        return;
 +                                    }
 +                                    if (doSpawning == PreSpawnStatus.SUCCESS && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) {
-+                                        // Paper end
++                                        // Paper end - PreCreatureSpawnEvent
                                          Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type);
  
                                          if (entityinsentient == null) {
@@ -152,7 +152,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
 -    private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) {
-+    // Paper start
++    // Paper start - PreCreatureSpawnEvent
 +    private enum PreSpawnStatus {
 +        FAIL,
 +        SUCCESS,
@@ -160,10 +160,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        ABORT
 +    }
 +    private static PreSpawnStatus isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) {
-+        // Paper end
++        // Paper end - PreCreatureSpawnEvent
          EntityType<?> entitytypes = spawnEntry.type;
  
-+        // Paper start
++        // Paper start - PreCreatureSpawnEvent
 +        com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event;
 +        org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(entitytypes).getPath());
 +        if (type != null) {
@@ -178,22 +178,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                return PreSpawnStatus.CANCELLED; // Paper
 +            }
 +        }
-+        // Paper end
++        // Paper end - PreCreatureSpawnEvent
          if (entitytypes.getCategory() == MobCategory.MISC) {
 -            return false;
-+            return PreSpawnStatus.FAIL; // Paper
++            return PreSpawnStatus.FAIL; // Paper - PreCreatureSpawnEvent
          } else if (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) {
 -            return false;
-+            return PreSpawnStatus.FAIL; // Paper
++            return PreSpawnStatus.FAIL; // Paper - PreCreatureSpawnEvent
          } else if (entitytypes.canSummon() && NaturalSpawner.canSpawnMobAt(world, structureAccessor, chunkGenerator, group, spawnEntry, pos)) {
              SpawnPlacements.Type entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes);
  
 -            return !NaturalSpawner.isSpawnPositionOk(entitypositiontypes_surface, world, pos, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, world, MobSpawnType.NATURAL, pos, world.random) ? false : world.noCollision(entitytypes.getAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)));
-+            boolean isValid = !NaturalSpawner.isSpawnPositionOk(entitypositiontypes_surface, world, pos, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, world, MobSpawnType.NATURAL, pos, world.random) ? false : world.noCollision(entitytypes.getAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D))); // Paper
-+            return isValid ? PreSpawnStatus.SUCCESS : PreSpawnStatus.FAIL; // Paper
++            boolean isValid = !NaturalSpawner.isSpawnPositionOk(entitypositiontypes_surface, world, pos, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, world, MobSpawnType.NATURAL, pos, world.random) ? false : world.noCollision(entitytypes.getAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D))); // Paper - PreCreatureSpawnEvent
++            return isValid ? PreSpawnStatus.SUCCESS : PreSpawnStatus.FAIL; // Paper - PreCreatureSpawnEvent
          } else {
 -            return false;
-+            return PreSpawnStatus.FAIL; // Paper
++            return PreSpawnStatus.FAIL; // Paper - PreCreatureSpawnEvent
          }
      }
  
diff --git a/patches/server/Prevent-logins-from-being-processed-when-the-player-.patch b/patches/server/Prevent-logins-from-being-processed-when-the-player-.patch
index 37da157d74..d32197f55c 100644
--- a/patches/server/Prevent-logins-from-being-processed-when-the-player-.patch
+++ b/patches/server/Prevent-logins-from-being-processed-when-the-player-.patch
@@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          if (this.state == ServerLoginPacketListenerImpl.State.VERIFYING) {
 +            if (this.connection.isConnected()) { // Paper - prevent logins to be processed even though disconnect was called
              this.verifyLoginAndFinishConnectionSetup((GameProfile) Objects.requireNonNull(this.authenticatedProfile));
-+            } // Paper
++            } // Paper - prevent logins to be processed even though disconnect was called
          }
  
          if (this.state == ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT && !this.isPlayerAlreadyInWorld((GameProfile) Objects.requireNonNull(this.authenticatedProfile))) {
diff --git a/patches/server/Rewrite-chunk-system.patch b/patches/server/Rewrite-chunk-system.patch
index dacd07c942..e75bc7d922 100644
--- a/patches/server/Rewrite-chunk-system.patch
+++ b/patches/server/Rewrite-chunk-system.patch
@@ -20504,7 +20504,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        // Paper start
 +        String str = packet.getCommand(); int index = -1;
 +        if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) {
-+            server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]))); // Paper
++            server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam"))); // Paper
 +            return;
 +        }
 +        // Paper end
diff --git a/patches/server/Send-attack-SoundEffects-only-to-players-who-can-see.patch b/patches/server/Send-attack-SoundEffects-only-to-players-who-can-see.patch
index 2ff4073c52..88bfa78225 100644
--- a/patches/server/Send-attack-SoundEffects-only-to-players-who-can-see.patch
+++ b/patches/server/Send-attack-SoundEffects-only-to-players-who-can-see.patch
@@ -59,14 +59,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public int getXpNeededForNextLevel() {
          return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2);
      }
-+    // Paper start - send SoundEffect to everyone who can see fromEntity
++    // Paper start - send while respecting visibility
 +    private static void sendSoundEffect(Player fromEntity, double x, double y, double z, SoundEvent soundEffect, SoundSource soundCategory, float volume, float pitch) {
 +        fromEntity.level().playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself
 +        if (fromEntity instanceof ServerPlayer) {
 +            ((ServerPlayer) fromEntity).connection.send(new net.minecraft.network.protocol.game.ClientboundSoundPacket(net.minecraft.core.registries.BuiltInRegistries.SOUND_EVENT.wrapAsHolder(soundEffect), soundCategory, x, y, z, volume, pitch, fromEntity.random.nextLong()));
 +        }
 +    }
-+    // Paper end
++    // Paper end - send while respecting visibility
  
      // CraftBukkit start
      public void causeFoodExhaustion(float exhaustion) {
diff --git a/patches/server/Toggleable-player-crits-helps-mitigate-hacked-client.patch b/patches/server/Toggleable-player-crits.patch
similarity index 89%
rename from patches/server/Toggleable-player-crits-helps-mitigate-hacked-client.patch
rename to patches/server/Toggleable-player-crits.patch
index 0ee6d7397e..73d2d8062c 100644
--- a/patches/server/Toggleable-player-crits-helps-mitigate-hacked-client.patch
+++ b/patches/server/Toggleable-player-crits.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: MiniDigger | Martin <admin@minidigger.dev>
 Date: Sat, 10 Mar 2018 00:50:24 +0100
-Subject: [PATCH] Toggleable player crits, helps mitigate hacked clients.
+Subject: [PATCH] Toggleable player crits
 
 
 diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
                      boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity;
  
-+                    flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper
++                    flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper - Toggleable player crits
                      flag2 = flag2 && !this.isSprinting();
                      if (flag2) {
                          f *= 1.5F;
diff --git a/patches/server/handle-ServerboundKeepAlivePacket-async.patch b/patches/server/handle-ServerboundKeepAlivePacket-async.patch
index a8958816a0..be68a56d12 100644
--- a/patches/server/handle-ServerboundKeepAlivePacket-async.patch
+++ b/patches/server/handle-ServerboundKeepAlivePacket-async.patch
@@ -23,7 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      @Override
      public void handleKeepAlive(ServerboundKeepAlivePacket packet) {
 -        PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // CraftBukkit
-+        //PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // CraftBukkit // Paper - This shouldn't be on the main thread
++        //PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // CraftBukkit // Paper - handle ServerboundKeepAlivePacket async
          if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) {
              int i = (int) (Util.getMillis() - this.keepAliveTime);
  
@@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            server.submit(() -> {
 +                this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE);
 +            });
-+            // Paper endg
++            // Paper endg - This needs to be handled on the main thread for plugins
          }
  
      }
diff --git a/patches/server/revert-serverside-behavior-of-keepalives.patch b/patches/server/revert-serverside-behavior-of-keepalives.patch
index 5a91ac0c42..eaf9f16f4a 100644
--- a/patches/server/revert-serverside-behavior-of-keepalives.patch
+++ b/patches/server/revert-serverside-behavior-of-keepalives.patch
@@ -64,7 +64,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge));
              }
          }
-+        // Paper end
++        // Paper end - give clients a longer time to respond to pings as per pre 1.12.2 timings
  
          this.server.getProfiler().pop();
      }