diff --git a/patches/api/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/patches/api/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch
deleted file mode 100644
index 146869c0ad..0000000000
--- a/patches/api/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch
+++ /dev/null
@@ -1,319 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
-Date: Wed, 12 Sep 2018 18:53:35 +0300
-Subject: [PATCH] Add an API for CanPlaceOn and CanDestroy NBT values
-
-
-diff --git a/src/main/java/com/destroystokyo/paper/Namespaced.java b/src/main/java/com/destroystokyo/paper/Namespaced.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/com/destroystokyo/paper/Namespaced.java
-@@ -0,0 +0,0 @@
-+package com.destroystokyo.paper;
-+
-+import org.jetbrains.annotations.NotNull;
-+
-+/**
-+ * Represents a namespaced resource, see {@link org.bukkit.NamespacedKey} for single elements
-+ * or {@link com.destroystokyo.paper.NamespacedTag} for a collection of elements
-+ *
-+ * Namespaces may only contain lowercase alphanumeric characters, periods,
-+ * underscores, and hyphens.
-+ * <p>
-+ * Keys may only contain lowercase alphanumeric characters, periods,
-+ * underscores, hyphens, and forward slashes.
-+ * <p>
-+ * You should not be implementing this interface yourself, use {@link org.bukkit.NamespacedKey}
-+ * or {@link com.destroystokyo.paper.NamespacedTag} as needed instead.
-+ */
-+public interface Namespaced {
-+    /**
-+     * Gets the namespace this resource is a part of
-+     * <p>
-+     * This is contractually obligated to only contain lowercase alphanumeric characters,
-+     * periods, underscores, and hyphens.
-+     *
-+     * @return resource namespace
-+     */
-+    @NotNull
-+    String getNamespace();
-+
-+    /**
-+     * Gets the key corresponding to this resource
-+     * <p>
-+     * This is contractually obligated to only contain lowercase alphanumeric characters,
-+     * periods, underscores, hyphens, and forward slashes.
-+     *
-+     * @return resource key
-+     */
-+    @NotNull
-+    String getKey();
-+}
-diff --git a/src/main/java/com/destroystokyo/paper/NamespacedTag.java b/src/main/java/com/destroystokyo/paper/NamespacedTag.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/com/destroystokyo/paper/NamespacedTag.java
-@@ -0,0 +0,0 @@
-+package com.destroystokyo.paper;
-+
-+import com.google.common.base.Preconditions;
-+import java.util.Locale;
-+import java.util.UUID;
-+import java.util.regex.Pattern;
-+import org.bukkit.plugin.Plugin;
-+import org.jetbrains.annotations.NotNull;
-+
-+/**
-+ * Represents a String based key pertaining to a tagged entry. Consists of two components - a namespace
-+ * and a key.
-+ * <p>
-+ * Namespaces may only contain lowercase alphanumeric characters, periods,
-+ * underscores, and hyphens.
-+ * <p>
-+ * Keys may only contain lowercase alphanumeric characters, periods,
-+ * underscores, hyphens, and forward slashes.
-+ *
-+ */
-+// Paper - entire class, based on org.bukkit.NamespacedKey
-+public final class NamespacedTag implements com.destroystokyo.paper.Namespaced {
-+
-+    /**
-+     * The namespace representing all inbuilt keys.
-+     */
-+    public static final String MINECRAFT = "minecraft";
-+    /**
-+     * The namespace representing all keys generated by Bukkit for backwards
-+     * compatibility measures.
-+     */
-+    public static final String BUKKIT = "bukkit";
-+    //
-+    private static final Pattern VALID_NAMESPACE = Pattern.compile("[a-z0-9._-]+");
-+    private static final Pattern VALID_KEY = Pattern.compile("[a-z0-9/._-]+");
-+    //
-+    private final String namespace;
-+    private final String key;
-+
-+    /**
-+     * Create a key in a specific namespace.
-+     *
-+     * @param namespace String representing a grouping of keys
-+     * @param key Name for this specific key
-+     * @deprecated should never be used by plugins, for internal use only!!
-+     */
-+    @Deprecated
-+    public NamespacedTag(@NotNull String namespace, @NotNull String key) {
-+        Preconditions.checkArgument(namespace != null && VALID_NAMESPACE.matcher(namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", namespace);
-+        Preconditions.checkArgument(key != null && VALID_KEY.matcher(key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", key);
-+
-+        this.namespace = namespace;
-+        this.key = key;
-+
-+        String string = toString();
-+        Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters", string);
-+    }
-+
-+    /**
-+     * Create a key in the plugin's namespace.
-+     * <p>
-+     * Namespaces may only contain lowercase alphanumeric characters, periods,
-+     * underscores, and hyphens.
-+     * <p>
-+     * Keys may only contain lowercase alphanumeric characters, periods,
-+     * underscores, hyphens, and forward slashes.
-+     *
-+     * @param plugin the plugin to use for the namespace
-+     * @param key the key to create
-+     */
-+    public NamespacedTag(@NotNull Plugin plugin, @NotNull String key) {
-+        Preconditions.checkArgument(plugin != null, "Plugin cannot be null");
-+        Preconditions.checkArgument(key != null, "Key cannot be null");
-+
-+        this.namespace = plugin.getName().toLowerCase(Locale.ROOT);
-+        this.key = key.toLowerCase().toLowerCase(Locale.ROOT);
-+
-+        // Check validity after normalization
-+        Preconditions.checkArgument(VALID_NAMESPACE.matcher(this.namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace);
-+        Preconditions.checkArgument(VALID_KEY.matcher(this.key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", this.key);
-+
-+        String string = toString();
-+        Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters (%s)", string);
-+    }
-+
-+    @NotNull
-+    public String getNamespace() {
-+        return namespace;
-+    }
-+
-+    @NotNull
-+    public String getKey() {
-+        return key;
-+    }
-+
-+    @Override
-+    public int hashCode() {
-+        int hash = 7;
-+        hash = 47 * hash + this.namespace.hashCode();
-+        hash = 47 * hash + this.key.hashCode();
-+        return hash;
-+    }
-+
-+    @Override
-+    public boolean equals(Object obj) {
-+        if (obj == null) {
-+            return false;
-+        }
-+        if (getClass() != obj.getClass()) {
-+            return false;
-+        }
-+        final NamespacedTag other = (NamespacedTag) obj;
-+        return this.namespace.equals(other.namespace) && this.key.equals(other.key);
-+    }
-+
-+    @Override
-+    public String toString() {
-+        return "#" + this.namespace + ":" + this.key;
-+    }
-+
-+    /**
-+     * Return a new random key in the {@link #BUKKIT} namespace.
-+     *
-+     * @return new key
-+     * @deprecated should never be used by plugins, for internal use only!!
-+     */
-+    @Deprecated
-+    public static NamespacedTag randomKey() {
-+        return new NamespacedTag(BUKKIT, UUID.randomUUID().toString());
-+    }
-+
-+    /**
-+     * Get a key in the Minecraft namespace.
-+     *
-+     * @param key the key to use
-+     * @return new key in the Minecraft namespace
-+     */
-+    @NotNull
-+    public static NamespacedTag minecraft(@NotNull String key) {
-+        return new NamespacedTag(MINECRAFT, key);
-+    }
-+}
-diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/bukkit/NamespacedKey.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/NamespacedKey.java
-+++ b/src/main/java/org/bukkit/NamespacedKey.java
-@@ -0,0 +0,0 @@ import org.jetbrains.annotations.Nullable;
-  * underscores, hyphens, and forward slashes.
-  *
-  */
--public final class NamespacedKey implements net.kyori.adventure.key.Key { // Paper - implement Key
-+public final class NamespacedKey implements net.kyori.adventure.key.Key, com.destroystokyo.paper.Namespaced { // Paper - implement Key and Namespaced
- 
-     /**
-      * The namespace representing all inbuilt keys.
-@@ -0,0 +0,0 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap
-     }
- 
-     @NotNull
-+    @Override // Paper
-     public String getNamespace() {
-         return namespace;
-     }
- 
-     @NotNull
-+    @Override // Paper
-     public String getKey() {
-         return key;
-     }
-diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
-+++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
-@@ -0,0 +0,0 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
-     @SuppressWarnings("javadoc")
-     @NotNull
-     ItemMeta clone();
-+
-+    // Paper start - Add an API for CanPlaceOn and CanDestroy NBT values
-+    /**
-+     * Gets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE}
-+     *
-+     * @return Set of materials
-+     * @deprecated Minecraft does not limit this to the material enum, Use {@link #getDestroyableKeys()} as a replacement
-+     */
-+    @Deprecated
-+    Set<org.bukkit.Material> getCanDestroy();
-+
-+    /**
-+     * Sets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE}
-+     *
-+     * @param canDestroy Set of materials
-+     * @deprecated Minecraft does not limit this to the material enum, Use {@link #setDestroyableKeys(Collection)} as a replacement
-+     */
-+    @Deprecated
-+    void setCanDestroy(Set<org.bukkit.Material> canDestroy);
-+
-+    /**
-+     * Gets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE}
-+     *
-+     * @return Set of materials
-+     * @deprecated Minecraft does not limit this to the material enum, Use {@link #getPlaceableKeys()} as a replacement
-+     */
-+    @Deprecated
-+    Set<org.bukkit.Material> getCanPlaceOn();
-+
-+    /**
-+     * Sets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE}
-+     *
-+     * @param canPlaceOn Set of materials
-+     * @deprecated Minecraft does not limit this to the material enum, Use {@link #setPlaceableKeys(Collection)} as a replacement
-+     */
-+    @Deprecated
-+    void setCanPlaceOn(Set<org.bukkit.Material> canPlaceOn);
-+
-+    /**
-+     * Gets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE}
-+     *
-+     * @return Set of {@link com.destroystokyo.paper.Namespaced}
-+     */
-+    @NotNull
-+    Set<com.destroystokyo.paper.Namespaced> getDestroyableKeys();
-+
-+    /**
-+     * Sets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE}
-+     *
-+     * @param canDestroy Collection of {@link com.destroystokyo.paper.Namespaced}
-+     */
-+    void setDestroyableKeys(@NotNull Collection<com.destroystokyo.paper.Namespaced> canDestroy);
-+
-+    /**
-+     * Gets the collection of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE}
-+     *
-+     * @return Set of {@link com.destroystokyo.paper.Namespaced}
-+     */
-+    @NotNull
-+    Set<com.destroystokyo.paper.Namespaced> getPlaceableKeys();
-+
-+    /**
-+     * Sets the set of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE}
-+     *
-+     * @param canPlaceOn Collection of {@link com.destroystokyo.paper.Namespaced}
-+     */
-+    @NotNull
-+    void setPlaceableKeys(@NotNull Collection<com.destroystokyo.paper.Namespaced> canPlaceOn);
-+
-+    /**
-+     * Checks for the existence of any keys that the item can be placed on
-+     *
-+     * @return true if this item has placeable keys
-+     */
-+    boolean hasPlaceableKeys();
-+
-+    /**
-+     * Checks for the existence of any keys that the item can destroy
-+     *
-+     * @return true if this item has destroyable keys
-+     */
-+    boolean hasDestroyableKeys();
-+    // Paper end
- }
diff --git a/patches/api/Fix-Spigot-annotation-mistakes.patch b/patches/api/Fix-Spigot-annotation-mistakes.patch
index b67239bb6c..328c288450 100644
--- a/patches/api/Fix-Spigot-annotation-mistakes.patch
+++ b/patches/api/Fix-Spigot-annotation-mistakes.patch
@@ -355,7 +355,7 @@ diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/buk
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/NamespacedKey.java
 +++ b/src/main/java/org/bukkit/NamespacedKey.java
-@@ -0,0 +0,0 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key, com.des
+@@ -0,0 +0,0 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap
  
      /**
       * Create a key in a specific namespace.
diff --git a/patches/api/Return-null-for-empty-String-in-NamespacedKey.fromSt.patch b/patches/api/Return-null-for-empty-String-in-NamespacedKey.fromSt.patch
index 5c92f8302f..bc2ecc52eb 100644
--- a/patches/api/Return-null-for-empty-String-in-NamespacedKey.fromSt.patch
+++ b/patches/api/Return-null-for-empty-String-in-NamespacedKey.fromSt.patch
@@ -8,7 +8,7 @@ diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/buk
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/NamespacedKey.java
 +++ b/src/main/java/org/bukkit/NamespacedKey.java
-@@ -0,0 +0,0 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key, com.des
+@@ -0,0 +0,0 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap
          this.key = key;
  
          String string = toString();
@@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      /**
-@@ -0,0 +0,0 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key, com.des
+@@ -0,0 +0,0 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap
          Preconditions.checkArgument(isValidKey(this.key), "Invalid key. Must be [a-z0-9/._-]: %s", this.key);
  
          String string = toString();
@@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      @NotNull
-@@ -0,0 +0,0 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key, com.des
+@@ -0,0 +0,0 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap
       */
      @Nullable
      public static NamespacedKey fromString(@NotNull String string, @Nullable Plugin defaultNamespace) {
diff --git a/patches/server/Ability-to-apply-mending-to-XP-API.patch b/patches/server/Ability-to-apply-mending-to-XP-API.patch
index 1bdf2cf4d5..beaab26622 100644
--- a/patches/server/Ability-to-apply-mending-to-XP-API.patch
+++ b/patches/server/Ability-to-apply-mending-to-XP-API.patch
@@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        final var stackEntry = net.minecraft.world.item.enchantment.EnchantmentHelper
 +            .getRandomItemWith(net.minecraft.world.item.enchantment.Enchantments.MENDING, handle);
 +        final net.minecraft.world.item.ItemStack itemstack = stackEntry != null ? stackEntry.getValue() : net.minecraft.world.item.ItemStack.EMPTY;
-+        if (!itemstack.isEmpty() && itemstack.getItem().components().has(net.minecraft.core.component.DataComponents.MAX_STACK_SIZE)) {
++        if (!itemstack.isEmpty() && itemstack.getItem().components().has(net.minecraft.core.component.DataComponents.MAX_DAMAGE)) {
 +            net.minecraft.world.entity.ExperienceOrb orb = net.minecraft.world.entity.EntityType.EXPERIENCE_ORB.create(handle.level());
 +            orb.value = amount;
 +            orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM;
diff --git a/patches/server/Add-Structure-check-API.patch b/patches/server/Add-Structure-check-API.patch
index 7a996f9923..02236a7c59 100644
--- a/patches/server/Add-Structure-check-API.patch
+++ b/patches/server/Add-Structure-check-API.patch
@@ -15,7 +15,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    // Paper start - structure check API
 +    @Override
 +    public boolean hasStructureAt(final io.papermc.paper.math.Position position, final Structure structure) {
-+        return this.world.structureManager().getStructureWithPieceAt(io.papermc.paper.util.MCUtil.toBlockPos(position), net.minecraft.resources.ResourceKey.create(net.minecraft.core.registries.Registries.STRUCTURE, CraftNamespacedKey.toMinecraft(structure.getKey()))).isValid();
++        net.minecraft.world.level.levelgen.structure.Structure vanillaStructure = this.world.registryAccess()
++            .registryOrThrow(net.minecraft.core.registries.Registries.STRUCTURE)
++            .getHolder(CraftNamespacedKey.toMinecraft(structure.getStructureType().getKey()))
++            .orElseThrow()
++            .value();
++        return this.world.structureManager().getStructureWithPieceAt(
++            io.papermc.paper.util.MCUtil.toBlockPos(position),
++            vanillaStructure
++        ).isValid();
 +    }
 +    // Paper end