diff --git a/build-data/reobf-mappings-patch.tiny b/build-data/reobf-mappings-patch.tiny
index 1d192e5e6b..48699a5e43 100644
--- a/build-data/reobf-mappings-patch.tiny
+++ b/build-data/reobf-mappings-patch.tiny
@@ -26,10 +26,3 @@ c	net/minecraft/server/level/ChunkMap	net/minecraft/server/level/PlayerChunkMap
 # Paper changes type
 c	net/minecraft/core/MappedRegistry	net/minecraft/core/RegistryMaterials
 	f	Lit/unimi/dsi/fastutil/objects/Reference2IntOpenHashMap;	toId	e
-
-# upstream makes a bunch of methods public that cause accidental overrides now
-c	net/minecraft/world/entity/Display	net/minecraft/world/entity/Display
-	m	()I	getInterpolationDelay	getInterpolationDelay_
-	m	(I)V	setInterpolationDelay	setInterpolationDelay_
-	m	(I)V	setInterpolationDuration	setInterpolationDuration_
-
diff --git a/patches/api/Add-ItemFactory-getSpawnEgg-API.patch b/patches/api/Add-ItemFactory-getSpawnEgg-API.patch
deleted file mode 100644
index b384ca3b9b..0000000000
--- a/patches/api/Add-ItemFactory-getSpawnEgg-API.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: William Blake Galbreath <blake.galbreath@gmail.com>
-Date: Thu, 14 Oct 2021 12:09:28 -0500
-Subject: [PATCH] Add ItemFactory#getSpawnEgg API
-
-
-diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/inventory/ItemFactory.java
-+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
-@@ -0,0 +0,0 @@ public interface ItemFactory {
-     @NotNull
-     @Deprecated
-     net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @NotNull net.md_5.bungee.api.chat.BaseComponent[] customName);
-+
-+    /**
-+     * Get a spawn egg ItemStack from an EntityType
-+     *
-+     * @param type EntityType
-+     * @return ItemStack spawner egg
-+     */
-+    @Nullable
-+    ItemStack getSpawnEgg(@Nullable org.bukkit.entity.EntityType type);
-     // Paper end
- }
diff --git a/patches/api/Add-ItemStack-Recipe-API-helper-methods.patch b/patches/api/Add-ItemStack-Recipe-API-helper-methods.patch
index 1148f8aeab..d777c95b43 100644
--- a/patches/api/Add-ItemStack-Recipe-API-helper-methods.patch
+++ b/patches/api/Add-ItemStack-Recipe-API-helper-methods.patch
@@ -25,7 +25,7 @@ diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/jav
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java
 +++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
-@@ -0,0 +0,0 @@ public class ShapedRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapedRecipe extends CraftingRecipe {
          return this;
      }
  
@@ -43,7 +43,7 @@ diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
 +++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
-@@ -0,0 +0,0 @@ public class ShapelessRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapelessRecipe extends CraftingRecipe {
          return this;
      }
  
@@ -84,7 +84,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      /**
       * Removes an ingredient from the list.
       *
-@@ -0,0 +0,0 @@ public class ShapelessRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapelessRecipe extends CraftingRecipe {
       */
      @NotNull
      public ShapelessRecipe removeIngredient(@NotNull Material ingredient) {
@@ -93,7 +93,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      /**
-@@ -0,0 +0,0 @@ public class ShapelessRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapelessRecipe extends CraftingRecipe {
       */
      @NotNull
      public ShapelessRecipe removeIngredient(int count, @NotNull Material ingredient) {
diff --git a/patches/api/Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/api/Add-and-implement-PlayerRecipeBookClickEvent.patch
index c370434877..e2f715daca 100644
--- a/patches/api/Add-and-implement-PlayerRecipeBookClickEvent.patch
+++ b/patches/api/Add-and-implement-PlayerRecipeBookClickEvent.patch
@@ -94,3 +94,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        return handlers;
 +    }
 +}
+diff --git a/src/main/java/org/bukkit/event/player/PlayerRecipeBookClickEvent.java b/src/main/java/org/bukkit/event/player/PlayerRecipeBookClickEvent.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/event/player/PlayerRecipeBookClickEvent.java
++++ b/src/main/java/org/bukkit/event/player/PlayerRecipeBookClickEvent.java
+@@ -0,0 +0,0 @@ import org.jetbrains.annotations.NotNull;
+ 
+ /**
+  * Called when a player clicks a recipe in the recipe book.
++ * @deprecated use {@link com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent}
+  */
++@Deprecated(forRemoval = true) // Paper
++@org.bukkit.Warning(false) // Paper
+ public class PlayerRecipeBookClickEvent extends PlayerEvent {
+ 
+     private static final HandlerList handlers = new HandlerList();
diff --git a/patches/api/Add-enchantWithLevels-API.patch b/patches/api/Add-enchantWithLevels-API.patch
index 636b1b8021..b95ed29d8d 100644
--- a/patches/api/Add-enchantWithLevels-API.patch
+++ b/patches/api/Add-enchantWithLevels-API.patch
@@ -9,9 +9,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/inventory/ItemFactory.java
 +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
 @@ -0,0 +0,0 @@ public interface ItemFactory {
-     Material updateMaterial(@NotNull final ItemMeta meta, @NotNull final Material material) throws IllegalArgumentException;
+     Material getSpawnEgg(@NotNull EntityType type);
  
-     // Paper start
+     // Paper start - Adventure
 +    /**
 +     * Randomly enchants a copy of the provided {@link ItemStack} using the given experience levels.
 +     *
diff --git a/patches/api/Add-event-for-player-editing-sign.patch b/patches/api/Add-event-for-player-editing-sign.patch
index e14f79a06b..175f837edc 100644
--- a/patches/api/Add-event-for-player-editing-sign.patch
+++ b/patches/api/Add-event-for-player-editing-sign.patch
@@ -114,3 +114,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        UNKNOWN,
 +    }
 +}
+diff --git a/src/main/java/org/bukkit/event/player/PlayerSignOpenEvent.java b/src/main/java/org/bukkit/event/player/PlayerSignOpenEvent.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/event/player/PlayerSignOpenEvent.java
++++ b/src/main/java/org/bukkit/event/player/PlayerSignOpenEvent.java
+@@ -0,0 +0,0 @@ import org.jetbrains.annotations.NotNull;
+ 
+ /**
+  * This event is fired when a sign is opened by the player.
++ * @deprecated use {@link io.papermc.paper.event.player.PlayerOpenSignEvent}
+  */
+ @ApiStatus.Experimental
++@Deprecated(forRemoval = true) // Paper
++@org.bukkit.Warning(false) // Paper
+ public class PlayerSignOpenEvent extends PlayerEvent implements Cancellable {
+ 
+     private static final HandlerList handlers = new HandlerList();
diff --git a/patches/api/Add-getI18NDisplayName-API.patch b/patches/api/Add-getI18NDisplayName-API.patch
index bd2a30410e..8977cf8527 100644
--- a/patches/api/Add-getI18NDisplayName-API.patch
+++ b/patches/api/Add-getI18NDisplayName-API.patch
@@ -12,13 +12,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/inventory/ItemFactory.java
 +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
 @@ -0,0 +0,0 @@ public interface ItemFactory {
-      */
      @NotNull
      net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack);
+     // Paper end - Adventure
 +
++    // Paper start - add getI18NDisplayName
 +    /**
 +     * Gets the Display name as seen in the Client.
-+     * Currently the server only supports the English language. To override this,
++     * Currently, the server only supports the English language. To override this,
 +     * You must replace the language file embedded in the server jar.
 +     *
 +     * @param item Item to return Display name of
@@ -29,7 +30,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    @Nullable
 +    @Deprecated
 +    String getI18NDisplayName(@Nullable ItemStack item);
-     // Paper end
++    // Paper end - add getI18NDisplayName
  }
 diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
diff --git a/patches/api/Adventure.patch b/patches/api/Adventure.patch
index 5ccde0310d..d5880b6893 100644
--- a/patches/api/Adventure.patch
+++ b/patches/api/Adventure.patch
@@ -2473,6 +2473,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       * @param url The URL from which the client will download the resource
       *     pack. The string must contain only US-ASCII characters and should
       *     be encoded as per RFC 1738.
+@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
+      *     pack correctly.
+      * </ul>
+      *
++     * @deprecated in favour of {@link #setResourcePack(String, byte[], Component, boolean)}
+      * @param url The URL from which the client will download the resource
+      *     pack. The string must contain only US-ASCII characters and should
+      *     be encoded as per RFC 1738.
 @@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
       * @throws IllegalArgumentException Thrown if the hash is not 20 bytes
       *     long.
@@ -2531,14 +2539,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      /**
       * Request that the player's client download and switch resource packs.
       * <p>
-@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
-      *     pack correctly.
-      * </ul>
-      *
-+     * @deprecated in favour of {@link #setResourcePack(String, byte[], Component, boolean)}
-      * @param url The URL from which the client will download the resource
-      *     pack. The string must contain only US-ASCII characters and should
-      *     be encoded as per RFC 1738.
 @@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
       * @throws IllegalArgumentException Thrown if the hash is not 20 bytes
       *     long.
@@ -3992,11 +3992,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/inventory/ItemFactory.java
 +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
 @@ -0,0 +0,0 @@ public interface ItemFactory {
-     @Deprecated
-     @NotNull
-     Material updateMaterial(@NotNull final ItemMeta meta, @NotNull final Material material) throws IllegalArgumentException;
+      */
+     @Nullable
+     Material getSpawnEgg(@NotNull EntityType type);
 +
-+    // Paper start
++    // Paper start - Adventure
 +    /**
 +     * Creates a hover event for the given item.
 +     *
@@ -4014,7 +4014,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     */
 +    @NotNull
 +    net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack);
-+    // Paper end
++    // Paper end - Adventure
  }
 diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@@ -4621,17 +4621,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/scoreboard/Objective.java
 +++ b/src/main/java/org/bukkit/scoreboard/Objective.java
 @@ -0,0 +0,0 @@ public interface Objective {
-      */
      @NotNull
-     String getName() throws IllegalStateException;
-+    // Paper start
+     String getName();
+ 
++    // Paper start - Adventure
 +    /**
-+     * Gets the name displayed to players for this objective
++     * Gets the display name for this objective
 +     *
 +     * @return this objective's display name
 +     * @throws IllegalStateException if this objective has been unregistered
 +     */
-+    net.kyori.adventure.text.@NotNull Component displayName() throws IllegalStateException;
++    net.kyori.adventure.text.@NotNull Component displayName();
 +    /**
 +     * Sets the name displayed to players for this objective.
 +     *
@@ -4641,9 +4641,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @throws IllegalArgumentException if displayName is longer than 128
 +     *     characters.
 +     */
-+    void displayName(net.kyori.adventure.text.@Nullable Component displayName) throws IllegalStateException, IllegalArgumentException;
-+    // Paper end
- 
++    void displayName(net.kyori.adventure.text.@Nullable Component displayName);
++    // Paper end - Adventure
++
      /**
       * Gets the name displayed to players for this objective
       *
@@ -4653,17 +4653,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       */
      @NotNull
 +    @Deprecated // Paper
-     String getDisplayName() throws IllegalStateException;
+     String getDisplayName();
  
      /**
 @@ -0,0 +0,0 @@ public interface Objective {
-      * @throws IllegalArgumentException if displayName is null
-      * @throws IllegalArgumentException if displayName is longer than 128
-      *     characters.
+      *
+      * @param displayName Display name to set
+      * @throws IllegalStateException if this objective has been unregistered
 +     * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)}
       */
 +    @Deprecated // Paper
-     void setDisplayName(@NotNull String displayName) throws IllegalStateException, IllegalArgumentException;
+     void setDisplayName(@NotNull String displayName);
  
      /**
 diff --git a/src/main/java/org/bukkit/scoreboard/Scoreboard.java b/src/main/java/org/bukkit/scoreboard/Scoreboard.java
@@ -4671,31 +4671,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/scoreboard/Scoreboard.java
 +++ b/src/main/java/org/bukkit/scoreboard/Scoreboard.java
 @@ -0,0 +0,0 @@ public interface Scoreboard {
-     @Deprecated
      @NotNull
-     Objective registerNewObjective(@NotNull String name, @NotNull String criteria) throws IllegalArgumentException;
-+    // Paper start
+     Objective registerNewObjective(@NotNull String name, @NotNull String criteria);
+ 
++    // Paper start - Adventure
 +    /**
 +     * Registers an Objective on this Scoreboard
 +     *
 +     * @param name Name of the Objective
 +     * @param criteria Criteria for the Objective
-+     * @param displayName Name displayed to players for the Objective.
++     * @param displayName display name for the Objective.
 +     * @return The registered Objective
-+     * @throws IllegalArgumentException if name is null
 +     * @throws IllegalArgumentException if name is longer than 32767
 +     *     characters.
-+     * @throws IllegalArgumentException if criteria is null
-+     * @throws IllegalArgumentException if displayName is null
-+     * @throws IllegalArgumentException if displayName is longer than 128
-+     *     characters.
 +     * @throws IllegalArgumentException if an objective by that name already
 +     *     exists
 +     * @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component)}
 +     */
 +    @NotNull
 +    @Deprecated
-+    Objective registerNewObjective(@NotNull String name, @NotNull String criteria, net.kyori.adventure.text.@Nullable Component displayName) throws IllegalArgumentException;
++    Objective registerNewObjective(@NotNull String name, @NotNull String criteria, net.kyori.adventure.text.@Nullable Component displayName);
 +    /**
 +     * Registers an Objective on this Scoreboard
 +     *
@@ -4704,14 +4699,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @param displayName Name displayed to players for the Objective.
 +     * @param renderType Manner of rendering the Objective
 +     * @return The registered Objective
-+     * @throws IllegalArgumentException if name is null
 +     * @throws IllegalArgumentException if name is longer than 32767
 +     *     characters.
-+     * @throws IllegalArgumentException if criteria is null
-+     * @throws IllegalArgumentException if displayName is null
-+     * @throws IllegalArgumentException if displayName is longer than 128
-+     *     characters.
-+     * @throws IllegalArgumentException if renderType is null
 +     * @throws IllegalArgumentException if an objective by that name already
 +     *     exists
 +     * @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component, RenderType)}
@@ -4726,13 +4715,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @param criteria Criteria for the Objective
 +     * @param displayName Name displayed to players for the Objective.
 +     * @return The registered Objective
-+     * @throws IllegalArgumentException if name is null
 +     * @throws IllegalArgumentException if name is longer than 32767
 +     *     characters.
-+     * @throws IllegalArgumentException if criteria is null
-+     * @throws IllegalArgumentException if displayName is null
-+     * @throws IllegalArgumentException if displayName is longer than 128
-+     *     characters.
 +     * @throws IllegalArgumentException if an objective by that name already
 +     *     exists
 +     */
@@ -4746,37 +4730,40 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @param displayName Name displayed to players for the Objective.
 +     * @param renderType Manner of rendering the Objective
 +     * @return The registered Objective
-+     * @throws IllegalArgumentException if name is null
 +     * @throws IllegalArgumentException if name is longer than 32767
 +     *     characters.
-+     * @throws IllegalArgumentException if criteria is null
-+     * @throws IllegalArgumentException if displayName is null
-+     * @throws IllegalArgumentException if displayName is longer than 128
-+     *     characters.
-+     * @throws IllegalArgumentException if renderType is null
 +     * @throws IllegalArgumentException if an objective by that name already
 +     *     exists
 +     */
 +    @NotNull
 +    Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, net.kyori.adventure.text.@Nullable Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException;
-+    // Paper end
- 
++    // Paper end - Adventure
++
      /**
       * Registers an Objective on this Scoreboard
+      *
 @@ -0,0 +0,0 @@ public interface Scoreboard {
-      * @deprecated use {@link #registerNewObjective(String, Criteria, String)}
+      *     characters.
+      * @throws IllegalArgumentException if an objective by that name already
+      *     exists
+-     * @deprecated use {@link #registerNewObjective(String, Criteria, String)}
++     * @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component)}
       */
      @NotNull
 +    @Deprecated // Paper
-     Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName) throws IllegalArgumentException;
+     Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName);
  
      /**
 @@ -0,0 +0,0 @@ public interface Scoreboard {
-      * @deprecated use {@link #registerNewObjective(String, Criteria, String, RenderType)}
+      *     characters.
+      * @throws IllegalArgumentException if an objective by that name already
+      *     exists
+-     * @deprecated use {@link #registerNewObjective(String, Criteria, String, RenderType)}
++     * @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component, RenderType)}
       */
      @NotNull
 +    @Deprecated // Paper
-     Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName, @NotNull RenderType renderType) throws IllegalArgumentException;
+     Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @NotNull String displayName, @NotNull RenderType renderType);
  
      /**
 @@ -0,0 +0,0 @@ public interface Scoreboard {
@@ -4787,18 +4774,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       */
      @NotNull
 +    @Deprecated // Paper
-     Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, @NotNull String displayName) throws IllegalArgumentException;
+     Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, @NotNull String displayName);
  
      /**
 @@ -0,0 +0,0 @@ public interface Scoreboard {
-      * @throws IllegalArgumentException if renderType is null
+      *     characters.
       * @throws IllegalArgumentException if an objective by that name already
       *     exists
 +     * @deprecated in favour of {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component, RenderType)}
       */
      @NotNull
 +    @Deprecated // Paper
-     Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, @NotNull String displayName, @NotNull RenderType renderType) throws IllegalArgumentException;
+     Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, @NotNull String displayName, @NotNull RenderType renderType);
  
      /**
 diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java
@@ -4806,17 +4793,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/scoreboard/Team.java
 +++ b/src/main/java/org/bukkit/scoreboard/Team.java
 @@ -0,0 +0,0 @@ public interface Team {
-      */
      @NotNull
-     String getName() throws IllegalStateException;
-+    // Paper start
+     String getName();
+ 
++    // Paper start - Adventure
 +    /**
-+     * Gets the name displayed to entries for this team
++     * Gets the display name for this team
 +     *
 +     * @return Team display name
 +     * @throws IllegalStateException if this team has been unregistered
 +     */
-+    net.kyori.adventure.text.@NotNull Component displayName() throws IllegalStateException;
++    net.kyori.adventure.text.@NotNull Component displayName();
 +
 +    /**
 +     * Sets the name displayed to entries for this team
@@ -4824,7 +4811,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @param displayName New display name
 +     * @throws IllegalStateException if this team has been unregistered
 +     */
-+    void displayName(net.kyori.adventure.text.@Nullable Component displayName) throws IllegalStateException, IllegalArgumentException;
++    void displayName(net.kyori.adventure.text.@Nullable Component displayName);
 +
 +    /**
 +     * Gets the prefix prepended to the display of entries on this team.
@@ -4832,17 +4819,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @return Team prefix
 +     * @throws IllegalStateException if this team has been unregistered
 +     */
-+    net.kyori.adventure.text.@NotNull Component prefix() throws IllegalStateException;
++    net.kyori.adventure.text.@NotNull Component prefix();
 +
 +    /**
 +     * Sets the prefix prepended to the display of entries on this team.
 +     *
 +     * @param prefix New prefix
-+     * @throws IllegalArgumentException if prefix is null
-+     *     characters
 +     * @throws IllegalStateException if this team has been unregistered
 +     */
-+    void prefix(net.kyori.adventure.text.@Nullable Component prefix) throws IllegalStateException, IllegalArgumentException;
++    void prefix(net.kyori.adventure.text.@Nullable Component prefix);
 +
 +    /**
 +     * Gets the suffix appended to the display of entries on this team.
@@ -4850,17 +4835,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @return the team's current suffix
 +     * @throws IllegalStateException if this team has been unregistered
 +     */
-+    net.kyori.adventure.text.@NotNull Component suffix() throws IllegalStateException;
++    net.kyori.adventure.text.@NotNull Component suffix();
 +
 +    /**
 +     * Sets the suffix appended to the display of entries on this team.
 +     *
 +     * @param suffix the new suffix for this team.
-+     * @throws IllegalArgumentException if suffix is null
-+     *     characters
 +     * @throws IllegalStateException if this team has been unregistered
 +     */
-+    void suffix(net.kyori.adventure.text.@Nullable Component suffix) throws IllegalStateException, IllegalArgumentException;
++    void suffix(net.kyori.adventure.text.@Nullable Component suffix);
 +
 +    /**
 +     * Checks if the team has a color specified
@@ -4881,7 +4864,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @throws IllegalStateException if the team doesn't have a color
 +     * @see #hasColor()
 +     */
-+    net.kyori.adventure.text.format.@NotNull TextColor color() throws IllegalStateException;
++    net.kyori.adventure.text.format.@NotNull TextColor color();
 +
 +    /**
 +     * Sets the color of the team.
@@ -4892,8 +4875,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @param color new color, null for no color
 +     */
 +    void color(net.kyori.adventure.text.format.@Nullable NamedTextColor color);
-+    // Paper end
- 
++    // Paper end - Adventure
++
      /**
       * Gets the name displayed to entries for this team
       *
@@ -4903,17 +4886,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       */
      @NotNull
 +    @Deprecated // Paper
-     String getDisplayName() throws IllegalStateException;
+     String getDisplayName();
  
      /**
 @@ -0,0 +0,0 @@ public interface Team {
-      * @throws IllegalArgumentException if displayName is longer than 128
-      *     characters.
+      *
+      * @param displayName New display name
       * @throws IllegalStateException if this team has been unregistered
 +     * @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)}
       */
 +    @Deprecated // Paper
-     void setDisplayName(@NotNull String displayName) throws IllegalStateException, IllegalArgumentException;
+     void setDisplayName(@NotNull String displayName);
  
      /**
 @@ -0,0 +0,0 @@ public interface Team {
@@ -4924,17 +4907,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       */
      @NotNull
 +    @Deprecated // Paper
-     String getPrefix() throws IllegalStateException;
+     String getPrefix();
  
      /**
 @@ -0,0 +0,0 @@ public interface Team {
-      * @throws IllegalArgumentException if prefix is longer than 64
-      *     characters
+      *
+      * @param prefix New prefix
       * @throws IllegalStateException if this team has been unregistered
 +     * @deprecated in favour of {@link #prefix(net.kyori.adventure.text.Component)}
       */
 +    @Deprecated // Paper
-     void setPrefix(@NotNull String prefix) throws IllegalStateException, IllegalArgumentException;
+     void setPrefix(@NotNull String prefix);
  
      /**
 @@ -0,0 +0,0 @@ public interface Team {
@@ -4945,17 +4928,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       */
      @NotNull
 +    @Deprecated // Paper
-     String getSuffix() throws IllegalStateException;
+     String getSuffix();
  
      /**
 @@ -0,0 +0,0 @@ public interface Team {
-      * @throws IllegalArgumentException if suffix is longer than 64
-      *     characters
+      *
+      * @param suffix the new suffix for this team.
       * @throws IllegalStateException if this team has been unregistered
 +     * @deprecated in favour of {@link #suffix(net.kyori.adventure.text.Component)}
       */
 +    @Deprecated // Paper
-     void setSuffix(@NotNull String suffix) throws IllegalStateException, IllegalArgumentException;
+     void setSuffix(@NotNull String suffix);
  
      /**
 @@ -0,0 +0,0 @@ public interface Team {
@@ -4966,7 +4949,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       */
      @NotNull
 +    @Deprecated // Paper
-     ChatColor getColor() throws IllegalStateException;
+     ChatColor getColor();
  
      /**
 @@ -0,0 +0,0 @@ public interface Team {
diff --git a/patches/api/Convert-project-to-Gradle.patch b/patches/api/Convert-project-to-Gradle.patch
index a7f3afed80..b05ecd4459 100644
--- a/patches/api/Convert-project-to-Gradle.patch
+++ b/patches/api/Convert-project-to-Gradle.patch
@@ -241,7 +241,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -            <plugin>
 -                <groupId>net.md-5</groupId>
 -                <artifactId>scriptus</artifactId>
--                <version>0.4.1</version>
+-                <version>0.5.0</version>
 -                <executions>
 -                    <execution>
 -                        <phase>initialize</phase>
@@ -287,7 +287,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -            <plugin>
 -                <groupId>org.apache.maven.plugins</groupId>
 -                <artifactId>maven-shade-plugin</artifactId>
--                <version>3.4.1</version>
+-                <version>3.5.0</version>
 -                <executions>
 -                    <execution>
 -                        <phase>package</phase>
diff --git a/patches/api/Create-HoverEvent-from-ItemStack-Entity.patch b/patches/api/Create-HoverEvent-from-ItemStack-Entity.patch
index 39e6e182e1..5f693a1756 100644
--- a/patches/api/Create-HoverEvent-from-ItemStack-Entity.patch
+++ b/patches/api/Create-HoverEvent-from-ItemStack-Entity.patch
@@ -9,10 +9,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/inventory/ItemFactory.java
 +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
 @@ -0,0 +0,0 @@ public interface ItemFactory {
-      */
      @NotNull
      ItemStack ensureServerConversions(@NotNull ItemStack item);
+     // Paper end - ensure server conversions API
 +
++    // Paper start - bungee hover events
 +    /**
 +     * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that ItemStack for displaying.
 +     *
@@ -71,5 +72,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    @NotNull
 +    @Deprecated
 +    net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(@NotNull org.bukkit.entity.Entity entity, @NotNull net.md_5.bungee.api.chat.BaseComponent[] customName);
-     // Paper end
++    // Paper end - bungee hover events
  }
diff --git a/patches/api/Display-warning-on-deprecated-recipe-API.patch b/patches/api/Display-warning-on-deprecated-recipe-API.patch
index 6242ebd939..baffd44b29 100644
--- a/patches/api/Display-warning-on-deprecated-recipe-API.patch
+++ b/patches/api/Display-warning-on-deprecated-recipe-API.patch
@@ -13,23 +13,23 @@ diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/jav
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java
 +++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
-@@ -0,0 +0,0 @@ public class ShapedRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapedRecipe extends CraftingRecipe {
+     @Deprecated
      public ShapedRecipe(@NotNull ItemStack result) {
-         Preconditions.checkArgument(result.getType() != Material.AIR, "Recipe must have non-AIR result.");
-         this.key = NamespacedKey.randomKey();
-+        new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:<ID>'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace();
-         this.output = new ItemStack(result);
+         super(NamespacedKey.randomKey(), result);
++        new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:<ID>'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); // Paper
      }
  
+     /**
 diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
 +++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
-@@ -0,0 +0,0 @@ public class ShapelessRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapelessRecipe extends CraftingRecipe {
+     @Deprecated
      public ShapelessRecipe(@NotNull ItemStack result) {
-         Preconditions.checkArgument(result.getType() != Material.AIR, "Recipe must have non-AIR result.");
-         this.key = NamespacedKey.randomKey();
-+        new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:<ID>'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace();
-         this.output = new ItemStack(result);
+         super(NamespacedKey.randomKey(), result);
++        new Throwable("Warning: A plugin is creating a recipe using a Deprecated method. This will cause you to receive warnings stating 'Tried to load unrecognized recipe: bukkit:<ID>'. Please ask the author to give their recipe a static key using NamespacedKey.").printStackTrace(); // Paper
      }
  
+     /**
diff --git a/patches/api/Fix-BanList-API.patch b/patches/api/Fix-BanList-API.patch
index dea482e583..65c3ccdd14 100644
--- a/patches/api/Fix-BanList-API.patch
+++ b/patches/api/Fix-BanList-API.patch
@@ -44,7 +44,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       */
      @Nullable
 -    public BanEntry<PlayerProfile> ban(@Nullable String reason, @Nullable Date expires, @Nullable String source);
-+    public <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E ban(@Nullable String reason, @Nullable Date expires, @Nullable String source);
++    public <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E ban(@Nullable String reason, @Nullable Date expires, @Nullable String source); // Paper - fix ban list API
+ 
+     /**
+      * Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will
+@@ -0,0 +0,0 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio
+      *     (updated) previous ban
+      */
+     @Nullable
+-    public BanEntry<PlayerProfile> ban(@Nullable String reason, @Nullable Instant expires, @Nullable String source);
++    public <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E ban(@Nullable String reason, @Nullable Instant expires, @Nullable String source); // Paper - fix ban list API
+ 
+     /**
+      * Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will
+@@ -0,0 +0,0 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio
+      *     (updated) previous ban
+      */
+     @Nullable
+-    public BanEntry<PlayerProfile> ban(@Nullable String reason, @Nullable Duration duration, @Nullable String source);
++    public <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E ban(@Nullable String reason, @Nullable Duration duration, @Nullable String source); // Paper - fix ban list API
  
      /**
       * Checks if this player is whitelisted or not
@@ -78,7 +96,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     */
 +    @Nullable BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(com.destroystokyo.paper.profile.@NotNull PlayerProfile target, @Nullable String reason, @Nullable Date expires, @Nullable String source);
 +
-+    // the 3 methods below are added to maintain compat for the PlayerProfile parameter type
++    // the 5 methods below are added to maintain compat for the bukkit.PlayerProfile parameter type
 +    /**
 +     * @deprecated use {@link #getBanEntry(Object)}
 +     */
@@ -96,6 +114,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     */
 +    @Deprecated
 +    void pardon(@NotNull PlayerProfile target);
++
++    /**
++     * @deprecated use {@link #addBan(Object, String, java.time.Instant, String)}
++     */
++    @Deprecated
++    @Nullable <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E addBan(@NotNull PlayerProfile target, @Nullable String reason, @Nullable java.time.Instant expires, @Nullable String source);
++
++    /**
++     * @deprecated use {@link #addBan(Object, String, java.time.Duration, String)}
++     */
++    @Deprecated
++    @Nullable <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E addBan(@NotNull PlayerProfile target, @Nullable String reason, @Nullable java.time.Duration duration, @Nullable String source);
++
 +    // Paper end
  }
 diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
@@ -107,7 +138,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       */
      @Nullable
 -    public BanEntry<PlayerProfile> ban(@Nullable String reason, @Nullable Date expires, @Nullable String source, boolean kickPlayer);
-+    public <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E ban(@Nullable String reason, @Nullable Date expires, @Nullable String source, boolean kickPlayer); // Paper
++    public <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E ban(@Nullable String reason, @Nullable Date expires, @Nullable String source, boolean kickPlayer); // Paper - fix ban list API
+ 
+     /**
+      * Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will
+@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
+      *     (updated) previous ban
+      */
+     @Nullable
+-    public BanEntry<PlayerProfile> ban(@Nullable String reason, @Nullable Instant expires, @Nullable String source, boolean kickPlayer);
++    public <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E ban(@Nullable String reason, @Nullable Instant expires, @Nullable String source, boolean kickPlayer); // Paper - fix ban list API
+ 
+     /**
+      * Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will
+@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
+      *     (updated) previous ban
+      */
+     @Nullable
+-    public BanEntry<PlayerProfile> ban(@Nullable String reason, @Nullable Duration duration, @Nullable String source, boolean kickPlayer);
++    public <E extends BanEntry<? super com.destroystokyo.paper.profile.PlayerProfile>> E ban(@Nullable String reason, @Nullable Duration duration, @Nullable String source, boolean kickPlayer); // Paper - fix ban list API
  
      /**
       * Adds this user's current IP address to the {@link IpBanList}. If a previous ban exists, this will
diff --git a/patches/api/Fix-Spigot-annotation-mistakes.patch b/patches/api/Fix-Spigot-annotation-mistakes.patch
index ba8d4b046d..2a2ae14873 100644
--- a/patches/api/Fix-Spigot-annotation-mistakes.patch
+++ b/patches/api/Fix-Spigot-annotation-mistakes.patch
@@ -344,19 +344,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    @org.jetbrains.annotations.NotNull // Paper
      public ItemStack getItem();
  
-     /**
-diff --git a/src/main/java/org/bukkit/block/DecoratedPot.java b/src/main/java/org/bukkit/block/DecoratedPot.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/block/DecoratedPot.java
-+++ b/src/main/java/org/bukkit/block/DecoratedPot.java
-@@ -0,0 +0,0 @@ import org.jetbrains.annotations.NotNull;
- /**
-  * Represents a captured state of a decorated pot.
-  */
--@ApiStatus.Experimental
-+//@ApiStatus.Experimental // Paper
- public interface DecoratedPot extends TileState {
- 
      /**
 diff --git a/src/main/java/org/bukkit/entity/Enderman.java b/src/main/java/org/bukkit/entity/Enderman.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@@ -807,7 +794,7 @@ diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/jav
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java
 +++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
-@@ -0,0 +0,0 @@ public class ShapedRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapedRecipe extends CraftingRecipe {
       * @param ingredient The ingredient.
       * @return The changed recipe, so you can chain calls.
       * @throws IllegalArgumentException if the {@code key} does not appear in the shape.
@@ -818,7 +805,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public ShapedRecipe setIngredient(char key, @NotNull MaterialData ingredient) {
          return setIngredient(key, ingredient.getItemType(), ingredient.getData());
      }
-@@ -0,0 +0,0 @@ public class ShapedRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapedRecipe extends CraftingRecipe {
       * Get a copy of the ingredients map.
       *
       * @return The mapping of character to ingredients.
@@ -832,7 +819,7 @@ diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
 +++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
-@@ -0,0 +0,0 @@ public class ShapelessRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapelessRecipe extends CraftingRecipe {
       *
       * @param ingredient The ingredient to add.
       * @return The changed recipe, so you can chain calls.
@@ -843,7 +830,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public ShapelessRecipe addIngredient(@NotNull MaterialData ingredient) {
          return addIngredient(1, ingredient);
      }
-@@ -0,0 +0,0 @@ public class ShapelessRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapelessRecipe extends CraftingRecipe {
       * @param count How many to add (can't be more than 9!)
       * @param ingredient The ingredient to add.
       * @return The changed recipe, so you can chain calls.
@@ -854,7 +841,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public ShapelessRecipe addIngredient(int count, @NotNull MaterialData ingredient) {
          return addIngredient(count, ingredient.getItemType(), ingredient.getData());
      }
-@@ -0,0 +0,0 @@ public class ShapelessRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapelessRecipe extends CraftingRecipe {
       *
       * @param ingredient The ingredient to remove
       * @return The changed recipe.
@@ -865,7 +852,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public ShapelessRecipe removeIngredient(@NotNull MaterialData ingredient) {
          return removeIngredient(ingredient.getItemType(), ingredient.getData());
      }
-@@ -0,0 +0,0 @@ public class ShapelessRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapelessRecipe extends CraftingRecipe {
       * @param count The number of copies to remove.
       * @param ingredient The ingredient to remove.
       * @return The changed recipe.
@@ -876,7 +863,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public ShapelessRecipe removeIngredient(int count, @NotNull MaterialData ingredient) {
          return removeIngredient(count, ingredient.getItemType(), ingredient.getData());
      }
-@@ -0,0 +0,0 @@ public class ShapelessRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapelessRecipe extends CraftingRecipe {
       * Get the list of ingredients used for this recipe.
       *
       * @return The input list
diff --git a/patches/api/Fix-upstream-javadocs.patch b/patches/api/Fix-upstream-javadocs.patch
index ca40c123e5..25815e3ee8 100644
--- a/patches/api/Fix-upstream-javadocs.patch
+++ b/patches/api/Fix-upstream-javadocs.patch
@@ -1066,7 +1066,7 @@ diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/jav
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java
 +++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
-@@ -0,0 +0,0 @@ public class ShapedRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapedRecipe extends CraftingRecipe {
       * @param result The item you want the recipe to create.
       * @see ShapedRecipe#shape(String...)
       * @see ShapedRecipe#setIngredient(char, Material)
@@ -1075,7 +1075,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       * @see ShapedRecipe#setIngredient(char, RecipeChoice)
       * @deprecated Recipes must have keys. Use {@link #ShapedRecipe(NamespacedKey, ItemStack)}
       * instead.
-@@ -0,0 +0,0 @@ public class ShapedRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapedRecipe extends CraftingRecipe {
       * @param result The item you want the recipe to create.
       * @see ShapedRecipe#shape(String...)
       * @see ShapedRecipe#setIngredient(char, Material)
@@ -1088,7 +1088,7 @@ diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
 +++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
-@@ -0,0 +0,0 @@ public class ShapelessRecipe implements Recipe, Keyed {
+@@ -0,0 +0,0 @@ public class ShapelessRecipe extends CraftingRecipe {
       * @param key the unique recipe key
       * @param result The item you want the recipe to create.
       * @see ShapelessRecipe#addIngredient(Material)
@@ -1100,8 +1100,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @see ShapelessRecipe#addIngredient(RecipeChoice)
       */
      public ShapelessRecipe(@NotNull NamespacedKey key, @NotNull ItemStack result) {
-         Preconditions.checkArgument(result.getType() != Material.AIR, "Recipe must have non-AIR result.");
-@@ -0,0 +0,0 @@ public class ShapelessRecipe implements Recipe, Keyed {
+         super(key, result);
+@@ -0,0 +0,0 @@ public class ShapelessRecipe extends CraftingRecipe {
  
      /**
       * Removes multiple instances of an ingredient from the list. If there are
@@ -1110,20 +1110,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       * matches, with a data value of 0.
       *
       * @param count The number of copies to remove.
-diff --git a/src/main/java/org/bukkit/inventory/SmithingRecipe.java b/src/main/java/org/bukkit/inventory/SmithingRecipe.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/inventory/SmithingRecipe.java
-+++ b/src/main/java/org/bukkit/inventory/SmithingRecipe.java
-@@ -0,0 +0,0 @@ public class SmithingRecipe implements Recipe, Keyed {
-      * @param result The item you want the recipe to create.
-      * @param base The base ingredient
-      * @param addition The addition ingredient
-+     * @deprecated use {@link SmithingTrimRecipe} or {@link SmithingTransformRecipe}
-      */
-+    @Deprecated(forRemoval = true) // Paper
-     public SmithingRecipe(@NotNull NamespacedKey key, @NotNull ItemStack result, @NotNull RecipeChoice base, @NotNull RecipeChoice addition) {
-         this.key = key;
-         this.result = result;
 diff --git a/src/main/java/org/bukkit/inventory/StonecuttingRecipe.java b/src/main/java/org/bukkit/inventory/StonecuttingRecipe.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/inventory/StonecuttingRecipe.java
@@ -1179,7 +1165,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -     * @see Criterias#HEALTH
 +     * @see Criteria#HEALTH
       */
-     boolean isModifiable() throws IllegalStateException;
+     boolean isModifiable();
  
 diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@@ -1189,11 +1175,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       * Gets the Set of entries on the team
       *
       * @return entries on the team
--     * @throws IllegalStateException if this entries has been unregistered\
+-     * @throws IllegalStateException if this entries has been unregistered
 +     * @throws IllegalStateException if this team has been unregistered
       */
      @NotNull
-     Set<String> getEntries() throws IllegalStateException;
+     Set<String> getEntries();
 diff --git a/src/main/java/org/bukkit/util/BoundingBox.java b/src/main/java/org/bukkit/util/BoundingBox.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/util/BoundingBox.java
diff --git a/patches/api/Improve-scoreboard-entries.patch b/patches/api/Improve-scoreboard-entries.patch
index 7b7504e9bb..b17bfb0bc8 100644
--- a/patches/api/Improve-scoreboard-entries.patch
+++ b/patches/api/Improve-scoreboard-entries.patch
@@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/scoreboard/Objective.java
 +++ b/src/main/java/org/bukkit/scoreboard/Objective.java
 @@ -0,0 +0,0 @@ public interface Objective {
-      * @throws IllegalArgumentException if player is null
+      * @return Score tracking the Objective and player specified
       * @throws IllegalStateException if this objective has been unregistered
       * @see #getScore(String)
 -     * @deprecated Scoreboards can contain entries that aren't players
@@ -17,14 +17,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -    @Deprecated
 +    // @Deprecated // Paper
      @NotNull
-     Score getScore(@NotNull OfflinePlayer player) throws IllegalArgumentException, IllegalStateException;
+     Score getScore(@NotNull OfflinePlayer player);
  
 @@ -0,0 +0,0 @@ public interface Objective {
       */
      @NotNull
-     Score getScore(@NotNull String entry) throws IllegalArgumentException, IllegalStateException;
+     Score getScore(@NotNull String entry);
 +
-+    // Paper start
++    // Paper start - improve scoreboard entries
 +    /**
 +     * Gets an entity's Score for an Objective on this Scoreboard.
 +     *
@@ -34,51 +34,51 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @throws IllegalStateException if this objective has been unregistered
 +     */
 +    @NotNull Score getScoreFor(@NotNull org.bukkit.entity.Entity entity) throws IllegalArgumentException, IllegalStateException;
-+    // Paper end
++    // Paper end - improve scoreboard entries
  }
 diff --git a/src/main/java/org/bukkit/scoreboard/Scoreboard.java b/src/main/java/org/bukkit/scoreboard/Scoreboard.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/scoreboard/Scoreboard.java
 +++ b/src/main/java/org/bukkit/scoreboard/Scoreboard.java
 @@ -0,0 +0,0 @@ public interface Scoreboard {
+      * @param player the player whose scores are being retrieved
       * @return immutable set of all scores tracked for the player
-      * @throws IllegalArgumentException if player is null
       * @see #getScores(String)
 -     * @deprecated Scoreboards can contain entries that aren't players
       */
 -    @Deprecated
 +    // @Deprecated // Paper
      @NotNull
-     Set<Score> getScores(@NotNull OfflinePlayer player) throws IllegalArgumentException;
+     Set<Score> getScores(@NotNull OfflinePlayer player);
  
 @@ -0,0 +0,0 @@ public interface Scoreboard {
+      *
       * @param player the player to drop all current scores for
-      * @throws IllegalArgumentException if player is null
       * @see #resetScores(String)
 -     * @deprecated Scoreboards can contain entries that aren't players
       */
 -    @Deprecated
 +    // @Deprecated // Paper
-     void resetScores(@NotNull OfflinePlayer player) throws IllegalArgumentException;
+     void resetScores(@NotNull OfflinePlayer player);
  
      /**
 @@ -0,0 +0,0 @@ public interface Scoreboard {
+      * @param player the player to search for
       * @return the player's Team or null if the player is not on a team
-      * @throws IllegalArgumentException if player is null
       * @see #getEntryTeam(String)
 -     * @deprecated Scoreboards can contain entries that aren't players
       */
 -    @Deprecated
 +    // @Deprecated // Paper
      @Nullable
-     Team getPlayerTeam(@NotNull OfflinePlayer player) throws IllegalArgumentException;
+     Team getPlayerTeam(@NotNull OfflinePlayer player);
  
 @@ -0,0 +0,0 @@ public interface Scoreboard {
-      * @throws IllegalArgumentException if slot is null
+      * @param slot the slot to remove objectives
       */
-     void clearSlot(@NotNull DisplaySlot slot) throws IllegalArgumentException;
+     void clearSlot(@NotNull DisplaySlot slot);
 +
-+    // Paper start
++    // Paper start - improve scoreboard entries
 +    /**
 +     * Gets all scores for an entity on this Scoreboard
 +     *
@@ -107,50 +107,50 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @see #getEntryTeam(String)
 +     */
 +    @Nullable Team getEntityTeam(@NotNull org.bukkit.entity.Entity entity) throws IllegalArgumentException;
-+    // Paper end
++    // Paper end - improve scoreboard entries
  }
 diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/scoreboard/Team.java
 +++ b/src/main/java/org/bukkit/scoreboard/Team.java
 @@ -0,0 +0,0 @@ public interface Team {
-      * @throws IllegalArgumentException if player is null
+      * @param player the player to add
       * @throws IllegalStateException if this team has been unregistered
       * @see #addEntry(String)
 -     * @deprecated Teams can contain entries that aren't players
       */
 -    @Deprecated
 +    // @Deprecated // Paper
-     void addPlayer(@NotNull OfflinePlayer player) throws IllegalStateException, IllegalArgumentException;
+     void addPlayer(@NotNull OfflinePlayer player);
  
      /**
 @@ -0,0 +0,0 @@ public interface Team {
-      * @throws IllegalArgumentException if player is null
+      * @return if the player was on this team
       * @throws IllegalStateException if this team has been unregistered
       * @see #removeEntry(String)
 -     * @deprecated Teams can contain entries that aren't players
       */
 -    @Deprecated
 +    // @Deprecated // Paper
-     boolean removePlayer(@NotNull OfflinePlayer player) throws IllegalStateException, IllegalArgumentException;
+     boolean removePlayer(@NotNull OfflinePlayer player);
  
      /**
 @@ -0,0 +0,0 @@ public interface Team {
-      * @throws IllegalArgumentException if player is null
+      * @return true if the player is a member of this team
       * @throws IllegalStateException if this team has been unregistered
       * @see #hasEntry(String)
 -     * @deprecated Teams can contain entries that aren't players
       */
 -    @Deprecated
 +    // @Deprecated // Paper
-     boolean hasPlayer(@NotNull OfflinePlayer player) throws IllegalArgumentException, IllegalStateException;
+     boolean hasPlayer(@NotNull OfflinePlayer player);
      /**
       * Checks to see if the specified entry is a member of this team.
 @@ -0,0 +0,0 @@ public interface Team {
       */
-     void setOption(@NotNull Option option, @NotNull OptionStatus status) throws IllegalStateException;
+     void setOption(@NotNull Option option, @NotNull OptionStatus status);
  
-+    // Paper start
++    // Paper start - improve scoreboard entries
 +    /**
 +     * This puts the specified entity onto this team for the scoreboard.
 +     * <p>
@@ -184,7 +184,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @see #hasEntry(String)
 +     */
 +    boolean hasEntity(@NotNull org.bukkit.entity.Entity entity) throws IllegalStateException, IllegalArgumentException;
-+    // Paper end
++    // Paper end - improve scoreboard entries
 +
      /**
       * Represents an option which may be applied to this team.
diff --git a/patches/api/Multiple-Entries-with-Scoreboards.patch b/patches/api/Multiple-Entries-with-Scoreboards.patch
index 537c082321..4672db75fc 100644
--- a/patches/api/Multiple-Entries-with-Scoreboards.patch
+++ b/patches/api/Multiple-Entries-with-Scoreboards.patch
@@ -10,7 +10,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/org/bukkit/scoreboard/Team.java
 @@ -0,0 +0,0 @@ public interface Team {
       */
-     void addEntry(@NotNull String entry) throws IllegalStateException, IllegalArgumentException;
+     void addEntry(@NotNull String entry);
  
 +    // Paper start
 +    /**
@@ -71,7 +71,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       *
 @@ -0,0 +0,0 @@ public interface Team {
       */
-     boolean removeEntry(@NotNull String entry) throws IllegalStateException, IllegalArgumentException;
+     boolean removeEntry(@NotNull String entry);
  
 +    // Paper start
 +    /**
diff --git a/patches/api/Option-to-prevent-NBT-copy-in-smithing-recipes.patch b/patches/api/Option-to-prevent-NBT-copy-in-smithing-recipes.patch
index ef3fa7ce09..9fd924ec24 100644
--- a/patches/api/Option-to-prevent-NBT-copy-in-smithing-recipes.patch
+++ b/patches/api/Option-to-prevent-NBT-copy-in-smithing-recipes.patch
@@ -18,7 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
       * Create a smithing recipe to produce the specified result ItemStack.
 @@ -0,0 +0,0 @@ public class SmithingRecipe implements Recipe, Keyed {
       */
-     @Deprecated(forRemoval = true) // Paper
+     @Deprecated
      public SmithingRecipe(@NotNull NamespacedKey key, @NotNull ItemStack result, @NotNull RecipeChoice base, @NotNull RecipeChoice addition) {
 +        // Paper start
 +        this(key, result, base, addition, true);
@@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @param copyNbt whether to copy the nbt from the input base item to the output
 +     * @deprecated use {@link SmithingTrimRecipe} or {@link SmithingTransformRecipe}
 +     */
-+    @Deprecated(forRemoval = true) // Paper
++    @Deprecated
 +    public SmithingRecipe(@NotNull NamespacedKey key, @NotNull ItemStack result, @NotNull RecipeChoice base, @NotNull RecipeChoice addition, boolean copyNbt) {
 +        this.copyNbt = copyNbt;
 +        // Paper end
diff --git a/patches/api/ensureServerConversions-API.patch b/patches/api/ensureServerConversions-API.patch
index 191a02053a..a9345d73ab 100644
--- a/patches/api/ensureServerConversions-API.patch
+++ b/patches/api/ensureServerConversions-API.patch
@@ -11,22 +11,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/inventory/ItemFactory.java
 +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
 @@ -0,0 +0,0 @@ public interface ItemFactory {
-     @Nullable
      @Deprecated
      String getI18NDisplayName(@Nullable ItemStack item);
+     // Paper end - add getI18NDisplayName
 +
++    // Paper start - ensure server conversions API
 +    /**
-+     * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks.
++     * Minecraft's updates are converting simple item stacks into more complex NBT oriented Item Stacks.
 +     *
 +     * Use this method to ensure any desired data conversions are processed.
 +     * The input itemstack will not be the same as the returned itemstack.
 +     *
 +     * @param item The item to process conversions on
-+     * @return A potentially Data Converted ItemStack
++     * @return A potentially Data-Converted-ItemStack
 +     */
 +    @NotNull
 +    ItemStack ensureServerConversions(@NotNull ItemStack item);
-     // Paper end
++    // Paper end - ensure server conversions API
  }
 diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
diff --git a/patches/server/Add-ItemFactory-getSpawnEgg-API.patch b/patches/server/Add-ItemFactory-getSpawnEgg-API.patch
index 578c219491..16dd2dd9bd 100644
--- a/patches/server/Add-ItemFactory-getSpawnEgg-API.patch
+++ b/patches/server/Add-ItemFactory-getSpawnEgg-API.patch
@@ -9,12 +9,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
 +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
 @@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory {
-             entity.getUniqueId().toString(),
              new net.md_5.bungee.api.chat.TextComponent(customName));
      }
+     // Paper end - bungee hover events
 +
-+    @Override
-+    public ItemStack getSpawnEgg(org.bukkit.entity.EntityType type) {
++    // Paper start - old getSpawnEgg API
++    // @Override // used to override, upstream added conflicting method, is called via Commodore now
++    @Deprecated
++    public ItemStack getSpawnEgg0(org.bukkit.entity.EntityType type) {
 +        if (type == null) {
 +            return null;
 +        }
@@ -24,5 +26,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        net.minecraft.world.item.SpawnEggItem eggItem = net.minecraft.world.item.SpawnEggItem.byId(nmsType);
 +        return eggItem == null ? null : new net.minecraft.world.item.ItemStack(eggItem).asBukkitMirror();
 +    }
-     // Paper end
++    // Paper end
  }
+diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
++++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
+@@ -0,0 +0,0 @@ public class Commodore
+                             return;
+                         }
+                         // Paper end
++
++                        // Paper start - ItemFactory#getSpawnEgg (paper had original method that returned ItemStack, upstream added identical but returned Material)
++                        if (owner.equals("org/bukkit/inventory/ItemFactory") && name.equals("getSpawnEgg") && desc.equals("(Lorg/bukkit/entity/EntityType;)Lorg/bukkit/inventory/ItemStack;")) {
++                            super.visitInsn(Opcodes.SWAP); // has 1 param, this moves the owner instance to the top for the checkcast
++                            super.visitTypeInsn(Opcodes.CHECKCAST, CB_PACKAGE + "/inventory/CraftItemFactory");
++                            super.visitInsn(Opcodes.SWAP); // moves param back to the the top of stack
++                            super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CB_PACKAGE + "/inventory/CraftItemFactory", "getSpawnEgg0", desc, false);
++                            return;
++                        }
++                        // Paper end - ItemFactory#getSpawnEgg
+                         if ( modern )
+                         {
+                             if ( owner.equals( "org/bukkit/Material" ) )
diff --git a/patches/server/Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/server/Add-and-implement-PlayerRecipeBookClickEvent.patch
index fff7bca5af..07feade5ec 100644
--- a/patches/server/Add-and-implement-PlayerRecipeBookClickEvent.patch
+++ b/patches/server/Add-and-implement-PlayerRecipeBookClickEvent.patch
@@ -12,18 +12,44 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              if (!this.player.containerMenu.stillValid(this.player)) {
                  ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu);
              } else {
--                this.server.getRecipeManager().byKey(packet.getRecipe()).ifPresent((irecipe) -> {
--                    ((RecipeBookMenu) this.player.containerMenu).handlePlacement(packet.isShiftDown(), irecipe, this.player);
--                });
-+                // Paper start - fire event for clicking recipes in the recipe book
-+                com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent event = new com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent(
-+                    player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(packet.getRecipe()), packet.isShiftDown());
-+                if (event.callEvent() && this.player.containerMenu instanceof RecipeBookMenu<?> recipeBookMenu) { // check if inventory changed during event handling
-+                    this.server.getRecipeManager().byKey(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getRecipe())).ifPresent((irecipe) -> {
-+                        recipeBookMenu.handlePlacement(event.isMakeAll(), irecipe, this.player);
-+                    });
++                // Paper start
++                ResourceLocation recipeName = packet.getRecipe();
++                boolean makeAll = packet.isShiftDown();
++                com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent paperEvent = new com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent(
++                    this.player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(recipeName), makeAll
++                );
++                if (!paperEvent.callEvent()) {
++                    return;
++                }
++                recipeName = CraftNamespacedKey.toMinecraft(paperEvent.getRecipe());
++                makeAll = paperEvent.isMakeAll();
++                if (org.bukkit.event.player.PlayerRecipeBookClickEvent.getHandlerList().getRegisteredListeners().length > 0) {
++                // Paper end
+                 // CraftBukkit start - implement PlayerRecipeBookClickEvent
+-                org.bukkit.inventory.Recipe recipe = this.cserver.getRecipe(CraftNamespacedKey.fromMinecraft(packet.getRecipe()));
++                org.bukkit.inventory.Recipe recipe = this.cserver.getRecipe(CraftNamespacedKey.fromMinecraft(recipeName)); // Paper
+                 if (recipe == null) {
+                     return;
+                 }
+-                org.bukkit.event.player.PlayerRecipeBookClickEvent event = CraftEventFactory.callRecipeBookClickEvent(this.player, recipe, packet.isShiftDown());
++                // Paper start
++                org.bukkit.event.player.PlayerRecipeBookClickEvent event = CraftEventFactory.callRecipeBookClickEvent(this.player, recipe, makeAll);
++                recipeName = CraftNamespacedKey.toMinecraft(((org.bukkit.Keyed) event.getRecipe()).getKey());
++                makeAll = event.isShiftClick();
++                }
++                if (!(this.player.containerMenu instanceof RecipeBookMenu<?>)) {
++                    return;
 +                }
 +                // Paper end
+ 
+                 // Cast to keyed should be safe as the recipe will never be a MerchantRecipe.
+-                this.server.getRecipeManager().byKey(CraftNamespacedKey.toMinecraft(((org.bukkit.Keyed) event.getRecipe()).getKey())).ifPresent((irecipe) -> {
+-                    ((RecipeBookMenu) this.player.containerMenu).handlePlacement(event.isShiftClick(), irecipe, this.player);
++                // Paper start
++                final boolean finalMakeAll = makeAll;
++                this.server.getRecipeManager().byKey(recipeName).ifPresent((irecipe) -> {
++                    ((RecipeBookMenu) this.player.containerMenu).handlePlacement(finalMakeAll, irecipe, this.player);
++                    // Paper end
+                 });
+                 // CraftBukkit end
              }
-         }
-     }
diff --git a/patches/server/Add-config-to-disable-ender-dragon-legacy-check.patch b/patches/server/Add-config-to-disable-ender-dragon-legacy-check.patch
index b869e8a0b0..d218388bdc 100644
--- a/patches/server/Add-config-to-disable-ender-dragon-legacy-check.patch
+++ b/patches/server/Add-config-to-disable-ender-dragon-legacy-check.patch
@@ -9,13 +9,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
 +++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
 @@ -0,0 +0,0 @@ public class EndDragonFight {
-     }
- 
-     public EndDragonFight(ServerLevel world, long gatewaysSeed, EndDragonFight.Data data, BlockPos origin) {
+         this.ticksSinceLastPlayerScan = 21;
+         this.skipArenaLoadedCheck = false;
+         this.needsStateScanning = true;
 +        // Paper start
 +        this.needsStateScanning = world.paperConfig().entities.spawning.scanForLegacyEnderDragon;
 +        if (!this.needsStateScanning) this.dragonKilled = true;
 +        // Paper end
          this.level = world;
          this.origin = origin;
-         this.validPlayer = EntitySelector.ENTITY_STILL_ALIVE.and(EntitySelector.withinDistance((double)origin.getX(), (double)(128 + origin.getY()), (double)origin.getZ(), 192.0D));
+         this.validPlayer = EntitySelector.ENTITY_STILL_ALIVE.and(EntitySelector.withinDistance((double) origin.getX(), (double) (128 + origin.getY()), (double) origin.getZ(), 192.0D));
diff --git a/patches/server/Add-event-for-player-editing-sign.patch b/patches/server/Add-event-for-player-editing-sign.patch
index 277112d38d..c10bd45780 100644
--- a/patches/server/Add-event-for-player-editing-sign.patch
+++ b/patches/server/Add-event-for-player-editing-sign.patch
@@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                          try {
                              if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) {
                                  if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) {
--                                    blocksign.openTextEdit(entityhuman, tileentitysign, true);
+-                                    blocksign.openTextEdit(entityhuman, tileentitysign, true, org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE); // Craftbukkit
 +                                    blocksign.openTextEdit(entityhuman, tileentitysign, true, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLACE); // Paper
                                  }
                              }
@@ -22,36 +22,53 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/block/SignBlock.java
 +++ b/src/main/java/net/minecraft/world/level/block/SignBlock.java
 @@ -0,0 +0,0 @@ public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterlo
-                 } else if (bl3) {
+                 } else if (flag2) {
                      return InteractionResult.SUCCESS;
-                 } else if (!this.otherPlayerIsEditingSign(player, signBlockEntity) && player.mayBuild() && this.hasEditableText(player, signBlockEntity, bl2)) {
--                    this.openTextEdit(player, signBlockEntity, bl2);
-+                    this.openTextEdit(player, signBlockEntity, bl2, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.INTERACT); // Paper
+                 } else if (!this.otherPlayerIsEditingSign(player, tileentitysign) && player.mayBuild() && this.hasEditableText(player, tileentitysign, flag1)) {
+-                    this.openTextEdit(player, tileentitysign, flag1, org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT); // CraftBukkit
++                    this.openTextEdit(player, tileentitysign, flag1, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.INTERACT); // Paper
                      return InteractionResult.SUCCESS;
                  } else {
                      return InteractionResult.PASS;
 @@ -0,0 +0,0 @@ public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterlo
-         return woodType;
+         return blockpropertywood;
      }
  
 +    @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper
      public void openTextEdit(Player player, SignBlockEntity blockEntity, boolean front) {
-+        // Paper start
+-        // Craftbukkit start
+-        this.openTextEdit(player, blockEntity, front, org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN);
++        // Paper start - PlayerOpenSignEvent
 +        this.openTextEdit(player, blockEntity, front, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.UNKNOWN);
-+    }
-+    public void openTextEdit(Player player, SignBlockEntity blockEntity, boolean front, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause cause) {
-+        org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) player.getBukkitEntity();
-+        org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(blockEntity.getLevel(), blockEntity.getBlockPos());
+     }
+-
+-    public void openTextEdit(Player entityhuman, SignBlockEntity tileentitysign, boolean flag, org.bukkit.event.player.PlayerSignOpenEvent.Cause cause) {
+-        if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, cause)) {
++    public void openTextEdit(Player entityhuman, SignBlockEntity tileentitysign, boolean flag, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause cause) {
++        org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) entityhuman.getBukkitEntity();
++        org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(tileentitysign.getLevel(), tileentitysign.getBlockPos());
 +        org.bukkit.craftbukkit.block.CraftSign<?> bukkitSign = (org.bukkit.craftbukkit.block.CraftSign<?>) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(bukkitBlock);
 +        io.papermc.paper.event.player.PlayerOpenSignEvent event = new io.papermc.paper.event.player.PlayerOpenSignEvent(
 +            bukkitPlayer,
 +            bukkitSign,
-+            front ? org.bukkit.block.sign.Side.FRONT : org.bukkit.block.sign.Side.BACK,
++            flag ? org.bukkit.block.sign.Side.FRONT : org.bukkit.block.sign.Side.BACK,
 +            cause);
 +        if (!event.callEvent()) return;
-+        // Paper end
-         blockEntity.setAllowedPlayerEditor(player.getUUID());
-         player.openTextEdit(blockEntity, front);
++        if (org.bukkit.event.player.PlayerSignOpenEvent.getHandlerList().getRegisteredListeners().length > 0) {
++            final org.bukkit.event.player.PlayerSignOpenEvent.Cause legacyCause = switch (cause) {
++                case PLACE -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE;
++                case PLUGIN -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLUGIN;
++                case INTERACT -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT;
++                case UNKNOWN -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN;
++            };
++        // Paper end - PlayerOpenSignEvent
++        if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, legacyCause)) { // Paper
+             return;
+         }
+-        // Craftbukkit end
++        } // Paper
+         tileentitysign.setAllowedPlayerEditor(entityhuman.getUUID());
+         entityhuman.openTextEdit(tileentitysign, flag);
      }
 diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@@ -64,7 +81,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        // Paper start
 +        io.papermc.paper.event.player.PlayerOpenSignEvent event = new io.papermc.paper.event.player.PlayerOpenSignEvent((Player) player, sign, side, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLUGIN);
 +        if (!event.callEvent()) return;
-+        // Paper end
++        if (PlayerSignOpenEvent.getHandlerList().getRegisteredListeners().length > 0) {
++            // Paper end
+         if (!CraftEventFactory.callPlayerSignOpenEvent(player, sign, side, PlayerSignOpenEvent.Cause.PLUGIN)) {
+             return;
+         }
++        } // Paper
+ 
          handle.setAllowedPlayerEditor(player.getUniqueId()); // Paper
-         ((org.bukkit.craftbukkit.entity.CraftHumanEntity) player).getHandle().openTextEdit(handle, Side.FRONT == side); // Paper - change move open sign to HumanEntity
-     }
+         ((CraftPlayer) player).getHandle().openTextEdit(handle, Side.FRONT == side);
diff --git a/patches/server/Add-openSign-method-to-HumanEntity.patch b/patches/server/Add-openSign-method-to-HumanEntity.patch
index b0d81ea66a..6b4b8bd0a7 100644
--- a/patches/server/Add-openSign-method-to-HumanEntity.patch
+++ b/patches/server/Add-openSign-method-to-HumanEntity.patch
@@ -9,24 +9,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
 +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
 @@ -0,0 +0,0 @@ public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<
-         super.applyTo(sign);
-     }
+             return;
+         }
  
--    public static void openSign(Sign sign, Player player, Side side) {
-+    public static void openSign(Sign sign, org.bukkit.entity.HumanEntity player, Side side) { // Paper - change move open sign to HumanEntity
-         Preconditions.checkArgument(sign != null, "sign == null");
-         Preconditions.checkArgument(side != null, "side == null");
-         Preconditions.checkArgument(sign.isPlaced(), "Sign must be placed");
-@@ -0,0 +0,0 @@ public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<
- 
-         SignBlockEntity handle = ((CraftSign<?>) sign).getTileEntity();
- 
--        ((CraftPlayer) player).getHandle().openTextEdit(handle, Side.FRONT == side);
 +        handle.setAllowedPlayerEditor(player.getUniqueId()); // Paper
-+        ((org.bukkit.craftbukkit.entity.CraftHumanEntity) player).getHandle().openTextEdit(handle, Side.FRONT == side); // Paper - change move open sign to HumanEntity
+         ((CraftPlayer) player).getHandle().openTextEdit(handle, Side.FRONT == side);
      }
  
-     // Paper start
 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -38,7 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper start - move open sign method to HumanEntity
 +    @Override
 +    public void openSign(final org.bukkit.block.Sign sign, final org.bukkit.block.sign.Side side) {
-+        org.bukkit.craftbukkit.block.CraftSign.openSign(sign, this, side);
++        org.bukkit.craftbukkit.block.CraftSign.openSign(sign, (CraftPlayer) this, side);
 +    }
 +    // Paper end
      @Override
diff --git a/patches/server/Adventure.patch b/patches/server/Adventure.patch
index ab77e51a96..8d7603a2ec 100644
--- a/patches/server/Adventure.patch
+++ b/patches/server/Adventure.patch
@@ -1825,6 +1825,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +    // Paper end
  }
+diff --git a/src/main/java/net/minecraft/network/chat/ChatType.java b/src/main/java/net/minecraft/network/chat/ChatType.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/network/chat/ChatType.java
++++ b/src/main/java/net/minecraft/network/chat/ChatType.java
+@@ -0,0 +0,0 @@ public record ChatType(ChatTypeDecoration chat, ChatTypeDecoration narration) {
+     public static final ResourceKey<ChatType> TEAM_MSG_COMMAND_INCOMING = create("team_msg_command_incoming");
+     public static final ResourceKey<ChatType> TEAM_MSG_COMMAND_OUTGOING = create("team_msg_command_outgoing");
+     public static final ResourceKey<ChatType> EMOTE_COMMAND = create("emote_command");
++    public static final ResourceKey<ChatType> RAW = create("raw"); // Paper
+ 
+     private static ResourceKey<ChatType> create(String id) {
+         return ResourceKey.create(Registries.CHAT_TYPE, new ResourceLocation(id));
+@@ -0,0 +0,0 @@ public record ChatType(ChatTypeDecoration chat, ChatTypeDecoration narration) {
+         messageTypeRegisterable.register(TEAM_MSG_COMMAND_INCOMING, new ChatType(ChatTypeDecoration.teamMessage("chat.type.team.text"), ChatTypeDecoration.withSender("chat.type.text.narrate")));
+         messageTypeRegisterable.register(TEAM_MSG_COMMAND_OUTGOING, new ChatType(ChatTypeDecoration.teamMessage("chat.type.team.sent"), ChatTypeDecoration.withSender("chat.type.text.narrate")));
+         messageTypeRegisterable.register(EMOTE_COMMAND, new ChatType(ChatTypeDecoration.withSender("chat.type.emote"), ChatTypeDecoration.withSender("chat.type.emote")));
++        messageTypeRegisterable.register(RAW, new ChatType(new ChatTypeDecoration("%s", java.util.List.of(ChatTypeDecoration.Parameter.CONTENT), Style.EMPTY), new ChatTypeDecoration("%s", java.util.List.of(ChatTypeDecoration.Parameter.CONTENT), Style.EMPTY))); // Paper
+     }
+ 
+     public static ChatType.Bound bind(ResourceKey<ChatType> typeKey, Entity entity) {
 diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/network/chat/Component.java
@@ -4299,22 +4319,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
 +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
 @@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory {
-     public Material updateMaterial(ItemMeta meta, Material material) throws IllegalArgumentException {
-         return ((CraftMetaItem) meta).updateMaterial(material);
+ 
+         return CraftMagicNumbers.getMaterial(nmsItem);
      }
 +
-+    // Paper start
++    // Paper start - Adventure
 +    @Override
 +    public net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowItem> asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowItem> op) {
 +        final net.minecraft.nbt.CompoundTag tag = CraftItemStack.asNMSCopy(item).getTag();
-+        return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.of(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.asBinaryTagHolder(tag))));
++        return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.showItem(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.asBinaryTagHolder(tag))));
 +    }
 +
 +    @Override
 +    public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) {
 +        return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).getDisplayName());
 +    }
-+    // Paper end
++    // Paper end - Adventure
  }
 diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@@ -4781,28 +4801,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +    // Paper end
      @Override
-     public String getDisplayName() throws IllegalStateException {
+     public String getDisplayName() {
          this.checkState();
 diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
 +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
 @@ -0,0 +0,0 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard {
-     public CraftObjective registerNewObjective(String name, String criteria) throws IllegalArgumentException {
+     public CraftObjective registerNewObjective(String name, String criteria) {
          return this.registerNewObjective(name, criteria, name);
      }
-+    // Paper start
++    // Paper start - Adventure
 +    @Override
 +    public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName) {
-+        return registerNewObjective(name, CraftCriteria.getFromBukkit(criteria), displayName, RenderType.INTEGER);
++        return this.registerNewObjective(name, CraftCriteria.getFromBukkit(criteria), displayName, RenderType.INTEGER);
 +    }
 +    @Override
 +    public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName, RenderType renderType) {
-+        return registerNewObjective(name, CraftCriteria.getFromBukkit(criteria), displayName, renderType);
++        return this.registerNewObjective(name, CraftCriteria.getFromBukkit(criteria), displayName, renderType);
 +    }
 +    @Override
 +    public CraftObjective registerNewObjective(String name, Criteria criteria, net.kyori.adventure.text.Component displayName) throws IllegalArgumentException {
-+        return registerNewObjective(name, criteria, displayName, RenderType.INTEGER);
++        return this.registerNewObjective(name, criteria, displayName, RenderType.INTEGER);
 +    }
 +    @Override
 +    public CraftObjective registerNewObjective(String name, Criteria criteria, net.kyori.adventure.text.Component displayName, RenderType renderType) throws IllegalArgumentException {
@@ -4814,28 +4834,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        Preconditions.checkArgument(renderType != null, "RenderType cannot be null");
 +        Preconditions.checkArgument(name.length() <= Short.MAX_VALUE, "The name '%s' is longer than the limit of 32767 characters (%s)", name, name.length());
 +        Preconditions.checkArgument(this.board.getObjective(name) == null, "An objective of name '%s' already exists", name);
-+        net.minecraft.world.scores.Objective objective = board.addObjective(name, ((CraftCriteria) criteria).criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
++        net.minecraft.world.scores.Objective objective = this.board.addObjective(name, ((CraftCriteria) criteria).criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
 +        return new CraftObjective(this, objective);
 +    }
-+    // Paper end
++    // Paper end - Adventure
  
      @Override
-     public CraftObjective registerNewObjective(String name, String criteria, String displayName) throws IllegalArgumentException {
+     public CraftObjective registerNewObjective(String name, String criteria, String displayName) {
 @@ -0,0 +0,0 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard {
  
      @Override
-     public CraftObjective registerNewObjective(String name, Criteria criteria, String displayName, RenderType renderType) throws IllegalArgumentException {
+     public CraftObjective registerNewObjective(String name, Criteria criteria, String displayName, RenderType renderType) {
 -        Preconditions.checkArgument(name != null, "Objective name cannot be null");
 -        Preconditions.checkArgument(criteria != null, "Criteria cannot be null");
 -        Preconditions.checkArgument(displayName != null, "Display name cannot be null");
 -        Preconditions.checkArgument(renderType != null, "RenderType cannot be null");
 -        Preconditions.checkArgument(name.length() <= Short.MAX_VALUE, "The name '%s' is longer than the limit of 32767 characters (%s)", name, name.length());
--        Preconditions.checkArgument(displayName.length() <= 128, "The display name '%s' is longer than the limit of 128 characters (%s)", displayName, displayName.length());
 -        Preconditions.checkArgument(this.board.getObjective(name) == null, "An objective of name '%s' already exists", name);
 -
 -        net.minecraft.world.scores.Objective objective = this.board.addObjective(name, ((CraftCriteria) criteria).criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
 -        return new CraftObjective(this, objective);
-+        return registerNewObjective(name, criteria, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(displayName), renderType); // Paper
++        return this.registerNewObjective(name, criteria, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(displayName), renderType); // Paper - Adventure
      }
  
      @Override
@@ -4906,7 +4925,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end
  
      @Override
-     public String getDisplayName() throws IllegalStateException {
+     public String getDisplayName() {
 diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java
diff --git a/patches/server/Build-system-changes.patch b/patches/server/Build-system-changes.patch
index 3a8579debc..10da19a991 100644
--- a/patches/server/Build-system-changes.patch
+++ b/patches/server/Build-system-changes.patch
@@ -90,7 +90,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    Date buildDate = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse(Main.class.getPackage().getImplementationVendor()); // Paper
  
                      Calendar deadline = Calendar.getInstance();
-                     deadline.add(Calendar.DAY_OF_YEAR, -7);
+                     deadline.add(Calendar.DAY_OF_YEAR, -21);
 diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
diff --git a/patches/server/Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server/Create-HoverEvent-from-ItemStack-Entity.patch
index 7a2c7c4b03..340b54bb11 100644
--- a/patches/server/Create-HoverEvent-from-ItemStack-Entity.patch
+++ b/patches/server/Create-HoverEvent-from-ItemStack-Entity.patch
@@ -9,10 +9,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
 +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
 @@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory {
- 
          return nms != null ? net.minecraft.locale.Language.getInstance().getOrDefault(nms.getItem().getDescriptionId(nms)) : null;
      }
+     // Paper end - add getI18NDisplayName
 +
++    // Paper start - bungee hover events
 +    @Override
 +    public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(ItemStack itemStack) {
 +        net.md_5.bungee.api.chat.ItemTag itemTag = net.md_5.bungee.api.chat.ItemTag.ofNbt(CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString());
@@ -47,5 +48,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            entity.getUniqueId().toString(),
 +            new net.md_5.bungee.api.chat.TextComponent(customName));
 +    }
-     // Paper end
++    // Paper end - bungee hover events
  }
diff --git a/patches/server/Fix-BanList-API.patch b/patches/server/Fix-BanList-API.patch
index 1be52a9834..97c6e934fa 100644
--- a/patches/server/Fix-BanList-API.patch
+++ b/patches/server/Fix-BanList-API.patch
@@ -13,10 +13,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      @Override
 -    public BanEntry<PlayerProfile> ban(String reason, Date expires, String source) {
-+    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source) { // Paper
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source) { // Paper - fix ban list API
          return ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source);
      }
  
+     @Override
+-    public BanEntry<PlayerProfile> ban(String reason, Instant expires, String source) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Instant expires, String source) { // Paper - fix ban list API
+         return ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source);
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> ban(String reason, Duration duration, String source) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Duration duration, String source) { // Paper - fix ban list API
+         return ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, duration, source);
+     }
+ 
 diff --git a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java
@@ -64,7 +76,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -        return this.getBanEntry(((CraftPlayerProfile) target).buildGameProfile());
 +        return this.getBanEntry(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile()); // Paper
 +    }
-+    // Paper start
++    // Paper start - fix ban list API
 +    @Override
 +    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(final com.destroystokyo.paper.profile.PlayerProfile target) {
 +        Preconditions.checkArgument(target != null, "target cannot be null");
@@ -78,10 +90,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        Preconditions.checkArgument(target.getId() != null, "The PlayerProfile UUID cannot be null");
 +
 +        return this.addBan(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile(), reason, expires, source);
-     }
- 
-     @Override
--    public BanEntry<PlayerProfile> addBan(String target, String reason, Date expires, String source) {
++    }
++
++    @Override
 +    public boolean isBanned(final com.destroystokyo.paper.profile.PlayerProfile target) {
 +        return this.isBanned((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
 +    }
@@ -89,11 +100,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    @Override
 +    public void pardon(final com.destroystokyo.paper.profile.PlayerProfile target) {
 +        this.pardon((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> addBan(String target, String reason, Date expires, String source) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(final com.destroystokyo.paper.profile.PlayerProfile target, final String reason, final Instant expires, final String source) {
++        Date date = expires != null ? Date.from(expires) : null;
++        return this.addBan(target, reason, date, source);
 +    }
-+    // Paper end
 +
 +    @Override
-+    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(String target, String reason, Date expires, String source) { // Paper
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(final com.destroystokyo.paper.profile.PlayerProfile target, final String reason, final Duration duration, final String source) {
++        Instant instant = duration != null ? Instant.now().plus(duration) : null;
++        return this.addBan(target, reason, instant, source);
++    }
++    // Paper end - fix ban list API
++
++    @Override
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(String target, String reason, Date expires, String source) { // Paper - fix ban list API
          Preconditions.checkArgument(target != null, "Ban target cannot be null");
  
          return this.addBan(CraftProfileBanList.getProfileByName(target), reason, expires, source);
@@ -101,7 +125,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      @Override
 -    public BanEntry<PlayerProfile> addBan(PlayerProfile target, String reason, Date expires, String source) {
-+    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(PlayerProfile target, String reason, Date expires, String source) { // Paper
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(PlayerProfile target, String reason, Date expires, String source) { // Paper - fix ban list API
          Preconditions.checkArgument(target != null, "PlayerProfile cannot be null");
          Preconditions.checkArgument(target.getUniqueId() != null, "The PlayerProfile UUID cannot be null");
  
@@ -110,6 +134,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      @Override
+-    public BanEntry<PlayerProfile> addBan(PlayerProfile target, String reason, Instant expires, String source) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(PlayerProfile target, String reason, Instant expires, String source) { // Paper - fix ban list API
+         Date date = expires != null ? Date.from(expires) : null;
+         return this.addBan(target, reason, date, source);
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> addBan(PlayerProfile target, String reason, Duration duration, String source) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(PlayerProfile target, String reason, Duration duration, String source) { // Paper - fix ban list API
+         Instant instant = duration != null ? Instant.now().plus(duration) : null;
+         return this.addBan(target, reason, instant, source);
+     }
 @@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
      }
  
@@ -180,18 +216,45 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      @Override
 -    public BanEntry<PlayerProfile> ban(String reason, Date expires, String source) {
-+    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source) { // Paper
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source) { // Paper - fix ban list API
          return this.ban(reason, expires, source, true);
      }
  
+     @Override
+-    public BanEntry<PlayerProfile> ban(String reason, Instant expires, String source) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Instant expires, String source) { // Paper - fix ban list API
+         return this.ban(reason, expires != null ? Date.from(expires) : null, source);
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> ban(String reason, Duration duration, String source) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Duration duration, String source) { // Paper - fix ban list API
+         return this.ban(reason, duration != null ? Instant.now().plus(duration) : null, source);
+     }
+ 
      @Override
 -    public BanEntry<PlayerProfile> ban(String reason, Date expires, String source, boolean kickPlayer) {
 -        BanEntry<PlayerProfile> banEntry = ((ProfileBanList) server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source);
-+    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source, boolean kickPlayer) { // Paper
-+        BanEntry<com.destroystokyo.paper.profile.PlayerProfile> banEntry = ((ProfileBanList) server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source); // Paper
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source, boolean kickPlayer) { // Paper - fix ban list API
++        BanEntry<com.destroystokyo.paper.profile.PlayerProfile> banEntry = ((ProfileBanList) server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source); // Paper - fix ban list API
          if (kickPlayer) {
              this.kickPlayer(reason);
          }
+@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> ban(String reason, Instant instant, String source, boolean kickPlayer) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Instant instant, String source, boolean kickPlayer) { // Paper - fix ban list API
+         return this.ban(reason, instant != null ? Date.from(instant) : null, source, kickPlayer);
+     }
+ 
+     @Override
+-    public BanEntry<PlayerProfile> ban(String reason, Duration duration, String source, boolean kickPlayer) {
++    public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Duration duration, String source, boolean kickPlayer) { // Paper - fix ban list API
+         return this.ban(reason, duration != null ? Instant.now().plus(duration) : null, source, kickPlayer);
+     }
+ 
 diff --git a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
diff --git a/patches/server/Fix-and-optimise-world-force-upgrading.patch b/patches/server/Fix-and-optimise-world-force-upgrading.patch
index 971a551c06..c4067d52d3 100644
--- a/patches/server/Fix-and-optimise-world-force-upgrading.patch
+++ b/patches/server/Fix-and-optimise-world-force-upgrading.patch
@@ -285,7 +285,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -            if (this.options.has("forceUpgrade")) {
 -                net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), this.options.has("eraseCache"), () -> {
 -                    return true;
--                }, iregistry);
+-                }, dimensions);
 -            }
 +            // Paper - move down
  
diff --git a/patches/server/Fix-cancelled-powdered-snow-bucket-placement.patch b/patches/server/Fix-cancelled-powdered-snow-bucket-placement.patch
index 4f792cc631..3203161a87 100644
--- a/patches/server/Fix-cancelled-powdered-snow-bucket-placement.patch
+++ b/patches/server/Fix-cancelled-powdered-snow-bucket-placement.patch
@@ -27,11 +27,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              int oldCount = this.getCount();
              ServerLevel world = (ServerLevel) context.getLevel();
  
--            if (!(this.getItem() instanceof BucketItem || this.getItem() instanceof SolidBucketItem)) { // if not bucket
-+            if (!(this.getItem() instanceof BucketItem/* || this.getItem() instanceof SolidBucketItem*/)) { // if not bucket // Paper - capture block states for snow buckets
+-            if (!(item instanceof BucketItem || item instanceof SolidBucketItem)) { // if not bucket
++            if (!(item instanceof BucketItem/* || item instanceof SolidBucketItem*/)) { // if not bucket // Paper - capture block states for snow buckets
                  world.captureBlockStates = true;
                  // special case bonemeal
-                 if (this.getItem() == Items.BONE_MEAL) {
+                 if (item == Items.BONE_MEAL) {
 @@ -0,0 +0,0 @@ public final class ItemStack {
                  world.capturedBlockStates.clear();
                  if (blocks.size() > 1) {
diff --git a/patches/server/Fix-interact-event-not-being-called-sometimes.patch b/patches/server/Fix-interact-event-not-being-called-sometimes.patch
index ff0a0e4451..11b2ddd28b 100644
--- a/patches/server/Fix-interact-event-not-being-called-sometimes.patch
+++ b/patches/server/Fix-interact-event-not-being-called-sometimes.patch
@@ -24,12 +24,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                              }
                          }
 @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
- 
          double d3 = player.gameMode.getGameModeForPlayer() == GameType.CREATIVE ? 5.0D : 4.5D;
          // SPIGOT-5607: Only call interact event if no block or entity is being clicked. Use bukkit ray trace method, because it handles blocks and entities at the same time
--        org.bukkit.util.RayTraceResult result = this.player.level().getWorld().rayTrace(origin, origin.getDirection(), d3, org.bukkit.FluidCollisionMode.NEVER, false, 0.1, entity -> entity != this.player.getBukkitEntity() && this.player.getBukkitEntity().canSee(entity));
-+        org.bukkit.util.RayTraceResult result = this.player.level().getWorld().rayTrace(origin, origin.getDirection(), d3, org.bukkit.FluidCollisionMode.NEVER, false, 0.0, entity -> entity != this.player.getBukkitEntity() && this.player.getBukkitEntity().canSee(entity)); // Paper - change raySize from 0.1 to 0.0
- 
+         // SPIGOT-7429: Make sure to call PlayerInteractEvent for spectators and non-pickable entities
+-        org.bukkit.util.RayTraceResult result = this.player.level().getWorld().rayTrace(origin, origin.getDirection(), d3, org.bukkit.FluidCollisionMode.NEVER, false, 0.1, entity -> {
++        org.bukkit.util.RayTraceResult result = this.player.level().getWorld().rayTrace(origin, origin.getDirection(), d3, org.bukkit.FluidCollisionMode.NEVER, false, 0.0, entity -> { // Paper - change raySize from 0.1 to 0.0
+             Entity handle = ((CraftEntity) entity).getHandle();
+             return entity != this.player.getBukkitEntity() && this.player.getBukkitEntity().canSee(entity) && !handle.isSpectator() && handle.isPickable() && !handle.isPassengerOfSameVehicle(player);
+         });
          if (result == null) {
              CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
 -        }
diff --git a/patches/server/Fix-text-display-error-on-spawn.patch b/patches/server/Fix-text-display-error-on-spawn.patch
index a377bb8369..17dacd56d5 100644
--- a/patches/server/Fix-text-display-error-on-spawn.patch
+++ b/patches/server/Fix-text-display-error-on-spawn.patch
@@ -9,11 +9,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/entity/Display.java
 +++ b/src/main/java/net/minecraft/world/entity/Display.java
 @@ -0,0 +0,0 @@ public abstract class Display extends Entity {
-             byte b = loadFlag((byte)0, nbt, "shadow", (byte)1);
-             b = loadFlag(b, nbt, "see_through", (byte)2);
-             b = loadFlag(b, nbt, "default_background", (byte)4);
--            Optional<Display.TextDisplay.Align> optional = Display.TextDisplay.Align.CODEC.decode(NbtOps.INSTANCE, nbt.get("alignment")).resultOrPartial(Util.prefix("Display entity", Display.LOGGER::error)).map(Pair::getFirst);
-+            Optional<Display.TextDisplay.Align> optional = Display.TextDisplay.Align.CODEC.decode(NbtOps.INSTANCE, nbt.get("alignment")).result().map(Pair::getFirst); // Paper
+             Logger logger = Display.LOGGER;
+ 
+             Objects.requireNonNull(logger);
+-            Optional<Display.TextDisplay.Align> optional = dataresult.resultOrPartial(Util.prefix("Display entity", logger::error)).map(Pair::getFirst);
++            Optional<Display.TextDisplay.Align> optional = dataresult.result().map(Pair::getFirst); // Paper - hide error message
+ 
              if (optional.isPresent()) {
-                 byte var10000;
-                 switch ((Display.TextDisplay.Align)optional.get()) {
+                 byte b1;
diff --git a/patches/server/Fix-this-stupid-bullshit.patch b/patches/server/Fix-this-stupid-bullshit.patch
index 6cf977ef88..041f8b9f4a 100644
--- a/patches/server/Fix-this-stupid-bullshit.patch
+++ b/patches/server/Fix-this-stupid-bullshit.patch
@@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/org/bukkit/craftbukkit/Main.java
 @@ -0,0 +0,0 @@ public class Main {
                      Calendar deadline = Calendar.getInstance();
-                     deadline.add(Calendar.DAY_OF_YEAR, -7);
+                     deadline.add(Calendar.DAY_OF_YEAR, -21);
                      if (buildDate.before(deadline.getTime())) {
 -                        System.err.println("*** Error, this build is outdated ***");
 +                        // Paper start - This is some stupid bullshit
diff --git a/patches/server/Implement-enchantWithLevels-API.patch b/patches/server/Implement-enchantWithLevels-API.patch
index 45dfaaa642..09afc07924 100644
--- a/patches/server/Implement-enchantWithLevels-API.patch
+++ b/patches/server/Implement-enchantWithLevels-API.patch
@@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory {
      }
  
-     // Paper start
+     // Paper start - Adventure
 +    @Override
 +    public ItemStack enchantWithLevels(ItemStack itemStack, int levels, boolean allowTreasure, java.util.Random random) {
 +        Preconditions.checkArgument(itemStack != null, "Argument 'itemStack' must not be null");
diff --git a/patches/server/Implement-ensureServerConversions-API.patch b/patches/server/Implement-ensureServerConversions-API.patch
index 261062df05..029161eabf 100644
--- a/patches/server/Implement-ensureServerConversions-API.patch
+++ b/patches/server/Implement-ensureServerConversions-API.patch
@@ -11,14 +11,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
 +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
 @@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory {
-     public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) {
          return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).getDisplayName());
      }
+     // Paper end - Adventure
 +
-+    // Paper start
++    // Paper start - ensure server conversions API
 +    @Override
 +    public ItemStack ensureServerConversions(ItemStack item) {
 +        return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item));
 +    }
-     // Paper end
++    // Paper end - ensure server conversions API
  }
diff --git a/patches/server/Implement-getI18NDisplayName.patch b/patches/server/Implement-getI18NDisplayName.patch
index f8fc98f589..cf1c5c355c 100644
--- a/patches/server/Implement-getI18NDisplayName.patch
+++ b/patches/server/Implement-getI18NDisplayName.patch
@@ -12,10 +12,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
 +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
 @@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory {
-     public ItemStack ensureServerConversions(ItemStack item) {
          return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item));
      }
+     // Paper end - ensure server conversions API
 +
++    // Paper start - add getI18NDisplayName
 +    @Override
 +    public String getI18NDisplayName(ItemStack item) {
 +        net.minecraft.world.item.ItemStack nms = null;
@@ -28,5 +29,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +        return nms != null ? net.minecraft.locale.Language.getInstance().getOrDefault(nms.getItem().getDescriptionId(nms)) : null;
 +    }
-     // Paper end
++    // Paper end - add getI18NDisplayName
  }
diff --git a/patches/server/Improve-scoreboard-entries.patch b/patches/server/Improve-scoreboard-entries.patch
index 591fd72248..6b6d8c9dae 100644
--- a/patches/server/Improve-scoreboard-entries.patch
+++ b/patches/server/Improve-scoreboard-entries.patch
@@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end
 +
      @Override
-     public void unregister() throws IllegalStateException {
+     public void unregister() {
          CraftScoreboard scoreboard = this.checkState();
 diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
diff --git a/patches/server/Lazily-track-plugin-scoreboards-by-default.patch b/patches/server/Lazily-track-plugin-scoreboards-by-default.patch
index 1c7ac091e9..7c64571eca 100644
--- a/patches/server/Lazily-track-plugin-scoreboards-by-default.patch
+++ b/patches/server/Lazily-track-plugin-scoreboards-by-default.patch
@@ -29,13 +29,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          Preconditions.checkArgument(renderType != null, "RenderType cannot be null");
          Preconditions.checkArgument(name.length() <= Short.MAX_VALUE, "The name '%s' is longer than the limit of 32767 characters (%s)", name, name.length());
          Preconditions.checkArgument(this.board.getObjective(name) == null, "An objective of name '%s' already exists", name);
-+        // Paper start - the block comment from the old registerNewObjective didnt cause a conflict when rebasing, so this block wasn't added to the adventure registerNewObjective
++        // Paper start - lazily track plugin scoreboards
 +        if (((CraftCriteria) criteria).criteria != net.minecraft.world.scores.criteria.ObjectiveCriteria.DUMMY && !this.registeredGlobally) {
 +            net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this);
 +            this.registeredGlobally = true;
 +        }
 +        // Paper end
-         net.minecraft.world.scores.Objective objective = board.addObjective(name, ((CraftCriteria) criteria).criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
+         net.minecraft.world.scores.Objective objective = this.board.addObjective(name, ((CraftCriteria) criteria).criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
          return new CraftObjective(this, objective);
      }
 diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
diff --git a/patches/server/MC-Dev-fixes.patch b/patches/server/MC-Dev-fixes.patch
index dc176e1953..793bdf76c9 100644
--- a/patches/server/MC-Dev-fixes.patch
+++ b/patches/server/MC-Dev-fixes.patch
@@ -201,31 +201,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  return InteractionResult.PASS;
              }
          }
-diff --git a/src/main/java/net/minecraft/world/level/block/SignBlock.java b/src/main/java/net/minecraft/world/level/block/SignBlock.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/net/minecraft/world/level/block/SignBlock.java
-+++ b/src/main/java/net/minecraft/world/level/block/SignBlock.java
-@@ -0,0 +0,0 @@ public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterlo
-     public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
-         ItemStack itemStack = player.getItemInHand(hand);
-         Item item = itemStack.getItem();
--        Item signBlockEntity = itemStack.getItem();
--        SignApplicator var10000;
--        if (signBlockEntity instanceof SignApplicator signApplicator) {
--            var10000 = signApplicator;
--        } else {
--            var10000 = null;
--        }
--
--        SignApplicator signApplicator2 = var10000;
-+        SignApplicator signApplicator2 = item instanceof SignApplicator signApplicator ? signApplicator : null; // Paper - decompile fixes
-         boolean bl = signApplicator2 != null && player.mayBuild();
--        BlockEntity bl2 = world.getBlockEntity(pos);
--        if (bl2 instanceof SignBlockEntity signBlockEntity) {
-+        if (world.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity) { // Paper - decompile fixes
-             if (!world.isClientSide) {
-                 boolean bl2 = signBlockEntity.isFacingFrontText(player);
-                 SignText signText = signBlockEntity.getText(bl2);
 diff --git a/src/main/java/net/minecraft/world/level/block/WallHangingSignBlock.java b/src/main/java/net/minecraft/world/level/block/WallHangingSignBlock.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/block/WallHangingSignBlock.java
diff --git a/patches/server/Mitigate-effects-of-WorldCreator-keepSpawnLoaded-ret.patch b/patches/server/Mitigate-effects-of-WorldCreator-keepSpawnLoaded-ret.patch
index 64dd3e4fcc..ecf9fa115a 100644
--- a/patches/server/Mitigate-effects-of-WorldCreator-keepSpawnLoaded-ret.patch
+++ b/patches/server/Mitigate-effects-of-WorldCreator-keepSpawnLoaded-ret.patch
@@ -21,5 +21,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                            return;
 +                        }
                          // Paper end
-                         if ( modern )
-                         {
+ 
+                         // Paper start - ItemFactory#getSpawnEgg (paper had original method that returned ItemStack, upstream added identical but returned Material)
diff --git a/patches/server/Multiple-Entries-with-Scoreboards.patch b/patches/server/Multiple-Entries-with-Scoreboards.patch
index 7122d754a1..a22d70e092 100644
--- a/patches/server/Multiple-Entries-with-Scoreboards.patch
+++ b/patches/server/Multiple-Entries-with-Scoreboards.patch
@@ -93,7 +93,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper end
 +
      @Override
-     public boolean removePlayer(OfflinePlayer player) throws IllegalStateException, IllegalArgumentException {
+     public boolean removePlayer(OfflinePlayer player) {
          Preconditions.checkArgument(player != null, "OfflinePlayer cannot be null");
 @@ -0,0 +0,0 @@ final class CraftTeam extends CraftScoreboardComponent implements Team {
          return true;
diff --git a/patches/server/Prevent-softlocked-end-exit-portal-generation.patch b/patches/server/Prevent-softlocked-end-exit-portal-generation.patch
index 56a3cac973..10f0d8ad4d 100644
--- a/patches/server/Prevent-softlocked-end-exit-portal-generation.patch
+++ b/patches/server/Prevent-softlocked-end-exit-portal-generation.patch
@@ -17,6 +17,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            this.portalLocation = this.portalLocation.atY(this.level.getMinBuildHeight() + 1);
 +        }
 +        // Paper end
-         endPodiumFeature.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation);
+         worldgenendtrophy.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation);
      }
  
diff --git a/patches/server/Reset-Ender-Crystals-on-Dragon-Spawn.patch b/patches/server/Reset-Ender-Crystals-on-Dragon-Spawn.patch
index ca10588561..d000e866e0 100644
--- a/patches/server/Reset-Ender-Crystals-on-Dragon-Spawn.patch
+++ b/patches/server/Reset-Ender-Crystals-on-Dragon-Spawn.patch
@@ -15,10 +15,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
 +++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
 @@ -0,0 +0,0 @@ public class EndDragonFight {
-             enderDragon.moveTo((double)this.origin.getX(), (double)(128 + this.origin.getY()), (double)this.origin.getZ(), this.level.random.nextFloat() * 360.0F, 0.0F);
-             this.level.addFreshEntity(enderDragon);
-             this.dragonUUID = enderDragon.getUUID();
+             entityenderdragon.moveTo((double) this.origin.getX(), (double) (128 + this.origin.getY()), (double) this.origin.getZ(), this.level.random.nextFloat() * 360.0F, 0.0F);
+             this.level.addFreshEntity(entityenderdragon);
+             this.dragonUUID = entityenderdragon.getUUID();
 +            this.resetSpikeCrystals(); // Paper
          }
  
-         return enderDragon;
+         return entityenderdragon;
diff --git a/patches/server/Setup-Gradle-project.patch b/patches/server/Setup-Gradle-project.patch
index 7200d99d46..d8995f6bb7 100644
--- a/patches/server/Setup-Gradle-project.patch
+++ b/patches/server/Setup-Gradle-project.patch
@@ -462,7 +462,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -            <plugin>
 -                <groupId>net.md-5</groupId>
 -                <artifactId>scriptus</artifactId>
--                <version>0.4.1</version>
+-                <version>0.5.0</version>
 -                <executions>
 -                    <execution>
 -                        <id>ex-spigot</id>
@@ -548,7 +548,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -            <plugin>
 -                <groupId>org.apache.maven.plugins</groupId>
 -                <artifactId>maven-shade-plugin</artifactId>
--                <version>3.4.1</version>
+-                <version>3.5.0</version>
 -                <executions>
 -                    <execution>
 -                        <phase>package</phase>
diff --git a/patches/server/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/patches/server/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch
index a46534b52e..de8ee7d258 100644
--- a/patches/server/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch
+++ b/patches/server/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch
@@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/craftbukkit/Main.java
 +++ b/src/main/java/org/bukkit/craftbukkit/Main.java
 @@ -0,0 +0,0 @@ public class Main {
-                     deadline.add(Calendar.DAY_OF_YEAR, -7);
+                     deadline.add(Calendar.DAY_OF_YEAR, -21);
                      if (buildDate.before(deadline.getTime())) {
                          System.err.println("*** Error, this build is outdated ***");
 -                        System.err.println("*** Please download a new build as per instructions from https://www.spigotmc.org/go/outdated-spigot ***");
diff --git a/patches/server/Toggle-for-removing-existing-dragon.patch b/patches/server/Toggle-for-removing-existing-dragon.patch
index 1b46b5adbe..2879920410 100644
--- a/patches/server/Toggle-for-removing-existing-dragon.patch
+++ b/patches/server/Toggle-for-removing-existing-dragon.patch
@@ -9,11 +9,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
 +++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
 @@ -0,0 +0,0 @@ public class EndDragonFight {
-             this.dragonUUID = enderDragon.getUUID();
-             LOGGER.info("Found that there's a dragon still alive ({})", (Object)enderDragon);
+             this.dragonUUID = entityenderdragon.getUUID();
+             EndDragonFight.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon);
              this.dragonKilled = false;
--            if (!bl) {
-+            if (!bl && this.level.paperConfig().entities.behavior.shouldRemoveDragon) {
-                 LOGGER.info("But we didn't have a portal, let's remove it.");
-                 enderDragon.discard();
+-            if (!flag) {
++            if (!flag && this.level.paperConfig().entities.behavior.shouldRemoveDragon) {
+                 EndDragonFight.LOGGER.info("But we didn't have a portal, let's remove it.");
+                 entityenderdragon.discard();
                  this.dragonUUID = null;
diff --git a/patches/server/ensure-reset-EnderDragon-boss-event-name.patch b/patches/server/ensure-reset-EnderDragon-boss-event-name.patch
index a17feefa65..f0f1f314eb 100644
--- a/patches/server/ensure-reset-EnderDragon-boss-event-name.patch
+++ b/patches/server/ensure-reset-EnderDragon-boss-event-name.patch
@@ -13,12 +13,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      private static final int GATEWAY_DISTANCE = 96;
      public static final int DRAGON_SPAWN_Y = 128;
      private final Predicate<Entity> validPlayer;
--    public final ServerBossEvent dragonEvent = (ServerBossEvent)(new ServerBossEvent(Component.translatable("entity.minecraft.ender_dragon"), BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS)).setPlayBossMusic(true).setCreateWorldFog(true);
 +    private static final Component DEFAULT_BOSS_EVENT_NAME = Component.translatable("entity.minecraft.ender_dragon"); // Paper
-+    public final ServerBossEvent dragonEvent = (ServerBossEvent)(new ServerBossEvent(DEFAULT_BOSS_EVENT_NAME, BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS)).setPlayBossMusic(true).setCreateWorldFog(true); // Paper
+     public final ServerBossEvent dragonEvent;
      public final ServerLevel level;
      private final BlockPos origin;
-     private final ObjectArrayList<Integer> gateways = new ObjectArrayList<>();
+@@ -0,0 +0,0 @@ public class EndDragonFight {
+     }
+ 
+     public EndDragonFight(ServerLevel world, long gatewaysSeed, EndDragonFight.Data data, BlockPos origin) {
+-        this.dragonEvent = (ServerBossEvent) (new ServerBossEvent(Component.translatable("entity.minecraft.ender_dragon"), BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS)).setPlayBossMusic(true).setCreateWorldFog(true);
++        this.dragonEvent = (ServerBossEvent) (new ServerBossEvent(DEFAULT_BOSS_EVENT_NAME, BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS)).setPlayBossMusic(true).setCreateWorldFog(true); // Paper
+         this.gateways = new ObjectArrayList();
+         this.ticksSinceLastPlayerScan = 21;
+         this.skipArenaLoadedCheck = false;
 @@ -0,0 +0,0 @@ public class EndDragonFight {
              this.ticksSinceDragonSeen = 0;
              if (dragon.hasCustomName()) {
diff --git a/work/Bukkit b/work/Bukkit
index 01aa02eb53..82af5dc60e 160000
--- a/work/Bukkit
+++ b/work/Bukkit
@@ -1 +1 @@
-Subproject commit 01aa02eb531ba554701b02986193c874ccb7635d
+Subproject commit 82af5dc60eae0a6223be15ea4f69c560521c97a9
diff --git a/work/CraftBukkit b/work/CraftBukkit
index b60a95c8cf..d548daac2f 160000
--- a/work/CraftBukkit
+++ b/work/CraftBukkit
@@ -1 +1 @@
-Subproject commit b60a95c8cf3ca3a6353be1ecf2a6baa6f9072c57
+Subproject commit d548daac2f99b1b570f9d229464f55d10d9a58b8
diff --git a/work/Spigot b/work/Spigot
index 9ebce8afbf..b41c46db51 160000
--- a/work/Spigot
+++ b/work/Spigot
@@ -1 +1 @@
-Subproject commit 9ebce8afbf14ba4b857ce5befe716fecbd6d8879
+Subproject commit b41c46db51ec4aca746def5ac9080ec319c4abdb