diff --git a/patches/server/Add-PlayerShearBlockEvent.patch b/patches/server/Add-PlayerShearBlockEvent.patch
index b52fc498a0..c7ce627503 100644
--- a/patches/server/Add-PlayerShearBlockEvent.patch
+++ b/patches/server/Add-PlayerShearBlockEvent.patch
@@ -50,7 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), new java.util.ArrayList<>());
 +            event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4)));
 +            if (!event.callEvent()) {
-+                return InteractionResult.PASS;
++                return ItemInteractionResult.PASS;
 +            }
 +            // Paper end - Add PlayerShearBlockEvent
              Direction direction = hit.getDirection();
diff --git a/patches/server/Add-Raw-Byte-Entity-Serialization.patch b/patches/server/Add-Raw-Byte-Entity-Serialization.patch
index 688ab2ee40..848fc3eea0 100644
--- a/patches/server/Add-Raw-Byte-Entity-Serialization.patch
+++ b/patches/server/Add-Raw-Byte-Entity-Serialization.patch
@@ -54,15 +54,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
 +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
 @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues {
-         return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(compound));
+         return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.parse(MinecraftServer.getServer().registryAccess(), compound).orElseThrow());
      }
  
+-    private byte[] serializeNbtToBytes(CompoundTag compound) {
 +    @Override
 +    public byte[] serializeEntity(org.bukkit.entity.Entity entity) {
 +        Preconditions.checkNotNull(entity, "null cannot be serialized");
 +        Preconditions.checkArgument(entity instanceof org.bukkit.craftbukkit.entity.CraftEntity, "only CraftEntities can be serialized");
 +
-+        CompoundTag compound = new CompoundTag();
++        net.minecraft.nbt.CompoundTag compound = new net.minecraft.nbt.CompoundTag();
 +        ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().serializeEntity(compound);
 +        return serializeNbtToBytes(compound);
 +    }
@@ -72,9 +73,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        Preconditions.checkNotNull(data, "null cannot be deserialized");
 +        Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing");
 +
-+        CompoundTag compound = deserializeNbtFromBytes(data);
++        net.minecraft.nbt.CompoundTag compound = deserializeNbtFromBytes(data);
 +        int dataVersion = compound.getInt("DataVersion");
-+        compound = (CompoundTag) MinecraftServer.getServer().fixerUpper.update(References.ENTITY, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, this.getDataVersion()).getValue();
++        compound = (net.minecraft.nbt.CompoundTag) MinecraftServer.getServer().fixerUpper.update(References.ENTITY, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, this.getDataVersion()).getValue();
 +        if (!preserveUUID) {
 +            // Generate a new UUID so we don't have to worry about deserializing the same entity twice
 +            compound.remove("UUID");
@@ -83,6 +84,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            .orElseThrow(() -> new IllegalArgumentException("An ID was not found for the data. Did you downgrade?")).getBukkitEntity();
 +    }
 +
-     private byte[] serializeNbtToBytes(CompoundTag compound) {
++    private byte[] serializeNbtToBytes(net.minecraft.nbt.CompoundTag compound) {
          compound.putInt("DataVersion", getDataVersion());
          java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
+         try {
diff --git a/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch
index 1da0e69865..42dd267b50 100644
--- a/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch
+++ b/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch
@@ -19,7 +19,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        Preconditions.checkNotNull(item, "null cannot be serialized");
 +        Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized");
 +
-+        return serializeNbtToBytes((item instanceof CraftItemStack ? ((CraftItemStack) item).handle : CraftItemStack.asNMSCopy(item)).save(new CompoundTag()));
++        return serializeNbtToBytes((net.minecraft.nbt.CompoundTag) (item instanceof CraftItemStack ? ((CraftItemStack) item).handle : CraftItemStack.asNMSCopy(item)).save(MinecraftServer.getServer().registryAccess()));
 +    }
 +
 +    @Override
@@ -27,10 +27,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        Preconditions.checkNotNull(data, "null cannot be deserialized");
 +        Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing");
 +
-+        CompoundTag compound = deserializeNbtFromBytes(data);
++        net.minecraft.nbt.CompoundTag compound = deserializeNbtFromBytes(data);
 +        final int dataVersion = compound.getInt("DataVersion");
-+        compound = (CompoundTag) MinecraftServer.getServer().fixerUpper.update(References.ITEM_STACK, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, this.getDataVersion()).getValue();
-+        return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(compound));
++        compound = (net.minecraft.nbt.CompoundTag) MinecraftServer.getServer().fixerUpper.update(References.ITEM_STACK, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, this.getDataVersion()).getValue();
++        return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.parse(MinecraftServer.getServer().registryAccess(), compound).orElseThrow());
 +    }
 +
 +    private byte[] serializeNbtToBytes(CompoundTag compound) {
@@ -47,8 +47,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        return outputStream.toByteArray();
 +    }
 +
-+    private CompoundTag deserializeNbtFromBytes(byte[] data) {
-+        CompoundTag compound;
++    private net.minecraft.nbt.CompoundTag deserializeNbtFromBytes(byte[] data) {
++        net.minecraft.nbt.CompoundTag compound;
 +        try {
 +            compound = net.minecraft.nbt.NbtIo.readCompressed(
 +                new java.io.ByteArrayInputStream(data), net.minecraft.nbt.NbtAccounter.unlimitedHeap()
diff --git a/patches/server/Cache-map-ids-on-item-frames.patch b/patches/server/Cache-map-ids-on-item-frames.patch
index 1abe765e44..2b661b917d 100644
--- a/patches/server/Cache-map-ids-on-item-frames.patch
+++ b/patches/server/Cache-map-ids-on-item-frames.patch
@@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
                  if (this.level.paperConfig().maps.itemFrameCursorUpdateInterval > 0 && this.tickCount % this.level.paperConfig().maps.itemFrameCursorUpdateInterval == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks // Paper - Make item frame map cursor update interval configurable
 -                    MapId mapid = (MapId) itemstack.get(DataComponents.MAP_ID);
-+                    Integer integer = entityitemframe.cachedMapId; // Paper - Perf: Cache map ids on item frames
++                    MapId mapid = entityitemframe.cachedMapId; // Paper - Perf: Cache map ids on item frames
                      MapItemSavedData worldmap = MapItem.getSavedData(mapid, this.level);
  
                      if (worldmap != null) {
@@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public static final int NUM_ROTATIONS = 8;
      public float dropChance;
      public boolean fixed;
-+    public Integer cachedMapId; // Paper - Perf: Cache map ids on item frames
++    public @Nullable MapId cachedMapId; // Paper - Perf: Cache map ids on item frames
  
      public ItemFrame(EntityType<? extends ItemFrame> type, Level world) {
          super(type, world);
@@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      private void onItemChanged(ItemStack stack) {
-+        this.cachedMapId = MapItem.getMapId(stack); // Paper - Perf: Cache map ids on item frames
++        this.cachedMapId = stack.getComponents().get(net.minecraft.core.component.DataComponents.MAP_ID); // Paper - Perf: Cache map ids on item frames
          if (!stack.isEmpty() && stack.getFrame() != this) {
              stack.setEntityRepresentation(this);
          }
diff --git a/patches/server/Expose-protocol-version.patch b/patches/server/Expose-protocol-version.patch
index 4f55ae6f04..d60caf0797 100644
--- a/patches/server/Expose-protocol-version.patch
+++ b/patches/server/Expose-protocol-version.patch
@@ -10,7 +10,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
 @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues {
      public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) {
-         return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()];
+         return io.papermc.paper.inventory.ItemRarity.values()[itemStack.getRarity().ordinal()];
      }
 +
 +    @Override
diff --git a/patches/server/Fix-UnsafeValues-loadAdvancement.patch b/patches/server/Fix-UnsafeValues-loadAdvancement.patch
index 33f1c9429d..a357c26bbf 100644
--- a/patches/server/Fix-UnsafeValues-loadAdvancement.patch
+++ b/patches/server/Fix-UnsafeValues-loadAdvancement.patch
@@ -23,7 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +            MinecraftServer.getServer().getAdvancements().advancements = mapBuilder.build();
 +            final net.minecraft.advancements.AdvancementTree tree = MinecraftServer.getServer().getAdvancements().tree();
-+            tree.addAll(List.of(holder));
++            tree.addAll(java.util.List.of(holder));
 +
 +            // recalculate advancement position
 +            final net.minecraft.advancements.AdvancementNode node = tree.get(minecraftkey);
diff --git a/patches/server/Item-Rarity-API.patch b/patches/server/Item-Rarity-API.patch
index db24dc99f6..f66b378adf 100644
--- a/patches/server/Item-Rarity-API.patch
+++ b/patches/server/Item-Rarity-API.patch
@@ -21,12 +21,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        if (item == null) {
 +            throw new IllegalArgumentException(material + " is not an item, and rarity does not apply to blocks");
 +        }
-+        return io.papermc.paper.inventory.ItemRarity.values()[item.rarity.ordinal()];
++        return io.papermc.paper.inventory.ItemRarity.values()[item.components().getOrDefault(net.minecraft.core.component.DataComponents.RARITY, net.minecraft.world.item.Rarity.COMMON).ordinal()];
 +    }
 +
 +    @Override
 +    public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) {
-+        return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()];
++        return io.papermc.paper.inventory.ItemRarity.values()[itemStack.getRarity().ordinal()];
 +    }
      // Paper end
  
diff --git a/patches/server/ItemStack-Tooltip-API.patch b/patches/server/ItemStack-Tooltip-API.patch
index a57e9e936d..37c29b717e 100644
--- a/patches/server/ItemStack-Tooltip-API.patch
+++ b/patches/server/ItemStack-Tooltip-API.patch
@@ -14,13 +14,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      // Paper end
 +    // Paper start - expose itemstack tooltip lines
 +    @Override
-+    public List<net.kyori.adventure.text.Component> computeTooltipLines(final ItemStack itemStack, final io.papermc.paper.inventory.tooltip.TooltipContext tooltipContext, final org.bukkit.entity.Player player) {
++    public java.util.List<net.kyori.adventure.text.Component> computeTooltipLines(final ItemStack itemStack, final io.papermc.paper.inventory.tooltip.TooltipContext tooltipContext, final org.bukkit.entity.Player player) {
 +        Preconditions.checkArgument(tooltipContext != null, "tooltipContext cannot be null");
 +        net.minecraft.world.item.TooltipFlag.Default flag = tooltipContext.isAdvanced() ? net.minecraft.world.item.TooltipFlag.ADVANCED : net.minecraft.world.item.TooltipFlag.NORMAL;
 +        if (tooltipContext.isCreative()) {
 +            flag = flag.asCreative();
 +        }
-+        final List<net.minecraft.network.chat.Component> lines = CraftItemStack.asNMSCopy(itemStack).getTooltipLines(player == null ? null : ((org.bukkit.craftbukkit.entity.CraftPlayer) player).getHandle(), flag);
++        final java.util.List<net.minecraft.network.chat.Component> lines = CraftItemStack.asNMSCopy(itemStack).getTooltipLines(player == null ? null : ((org.bukkit.craftbukkit.entity.CraftPlayer) player).getHandle(), flag);
 +        return lines.stream().map(io.papermc.paper.adventure.PaperAdventure::asAdventure).toList();
 +    }
 +    // Paper end - expose itemstack tooltip lines
diff --git a/patches/server/ItemStack-repair-check-API.patch b/patches/server/ItemStack-repair-check-API.patch
index fb1bb5e948..a9785c3161 100644
--- a/patches/server/ItemStack-repair-check-API.patch
+++ b/patches/server/ItemStack-repair-check-API.patch
@@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
 +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
 @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues {
-         return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()];
+         return io.papermc.paper.inventory.ItemRarity.values()[itemStack.getRarity().ordinal()];
      }
  
 +    @Override
diff --git a/patches/server/LootTable-API-and-replenishable-lootables.patch b/patches/server/LootTable-API-and-replenishable-lootables.patch
index 68de2a8aea..50780be420 100644
--- a/patches/server/LootTable-API-and-replenishable-lootables.patch
+++ b/patches/server/LootTable-API-and-replenishable-lootables.patch
@@ -673,9 +673,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        // Copied from super with changes, always check the original method
 +        this.lootableData.loadNbt(nbt); // Paper
 +        if (nbt.contains("LootTable", 8)) {
-+            this.setLootTable(ResourceLocation.tryParse(nbt.getString("LootTable")));
-+            try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate
-+            this.setLootTableSeed(nbt.getLong("LootTableSeed"));
++            final var loc = new net.minecraft.resources.ResourceLocation(nbt.getString("LootTable"));
++            this.setLootTable(ResourceKey.create(net.minecraft.core.registries.Registries.LOOT_TABLE, loc));
++            try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable.location()); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate
++            if (nbt.contains("LootTableSeed", 4)) {
++                this.setLootTableSeed(nbt.getLong("LootTableSeed"));
++            } else {
++                this.setLootTableSeed(0L);
++            }
 +            return false; // Paper - always load the items, table may still remain
 +        } else {
 +            return false;
@@ -694,11 +699,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        // Copied from super with changes, always check the original method
 +        net.minecraft.world.level.Level level = this.getLevel();
 +        BlockPos blockPos = this.getBlockPos();
-+        ResourceLocation resourceLocation = this.getLootTable();
-+        if (this.lootableData.shouldReplenish(player) && level != null) { // Paper
-+            net.minecraft.world.level.storage.loot.LootTable lootTable = level.getServer().getLootData().getLootTable(resourceLocation);
++        ResourceKey<LootTable> resourceKey = this.getLootTable();
++        if (this.lootableData.shouldReplenish(player) && resourceKey != null && level != null && level.getServer() != null) { // Paper
++            net.minecraft.world.level.storage.loot.LootTable lootTable = level.getServer().reloadableRegistries().getLootTable(resourceKey);
 +            if (player instanceof net.minecraft.server.level.ServerPlayer) {
-+                net.minecraft.advancements.CriteriaTriggers.GENERATE_LOOT.trigger((net.minecraft.server.level.ServerPlayer)player, resourceLocation);
++                net.minecraft.advancements.CriteriaTriggers.GENERATE_LOOT.trigger((net.minecraft.server.level.ServerPlayer)player, resourceKey);
 +            }
 +
 +            this.lootableData.processRefill(player); // Paper
diff --git a/patches/server/MC-Utils.patch b/patches/server/MC-Utils.patch
index f21ab41545..cae05842d3 100644
--- a/patches/server/MC-Utils.patch
+++ b/patches/server/MC-Utils.patch
@@ -6171,12 +6171,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    public @Nullable ChunkAccess getAvailableChunkNow() {
 +        // TODO can we just getStatusFuture(EMPTY)?
 +        for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getParent(); curr != next; curr = next, next = next.getParent()) {
-+            CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> future = this.getFutureIfPresentUnchecked(curr);
-+            Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = future.getNow(null);
-+            if (either == null || either.left().isEmpty()) {
++            CompletableFuture<ChunkResult<ChunkAccess>> future = this.getFutureIfPresentUnchecked(curr);
++            ChunkResult<ChunkAccess> either = future.getNow(null);
++            if (either == null || either.isSuccess()) {
 +                continue;
 +            }
-+            return either.left().get();
++            return either.orElseThrow(IllegalStateException::new);
 +        }
 +        return null;
 +    }
@@ -6214,11 +6214,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
 +    // Paper start
-+    public ChunkStatus getChunkHolderStatus() {
++    public @Nullable ChunkStatus getChunkHolderStatus() {
 +        for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getParent(); curr != next; curr = next, next = next.getParent()) {
-+            CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> future = this.getFutureIfPresentUnchecked(curr);
-+            Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = future.getNow(null);
-+            if (either == null || !either.left().isPresent()) {
++            CompletableFuture<ChunkResult<ChunkAccess>> future = this.getFutureIfPresentUnchecked(curr);
++            ChunkResult<ChunkAccess> either = future.getNow(null);
++            if (either == null || !either.isSuccess()) {
 +                continue;
 +            }
 +            return curr;
@@ -6291,8 +6291,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              this.tickingChunkFuture = chunkStorage.prepareTickingChunk(this);
              this.scheduleFullChunkPromotion(chunkStorage, this.tickingChunkFuture, executor, FullChunkStatus.BLOCK_TICKING);
 +            // Paper start - cache ticking ready status
-+            this.tickingChunkFuture.thenAccept(either -> {
-+                either.ifLeft(chunk -> {
++            this.tickingChunkFuture.thenAccept(chunkResult -> {
++                chunkResult.ifSuccess(chunk -> {
 +                    // note: Here is a very good place to add callbacks to logic waiting on this.
 +                    ChunkHolder.this.isTickingReady = true;
 +                    io.papermc.paper.chunk.system.ChunkSystem.onChunkTicking(chunk, this);
@@ -6306,7 +6306,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -            this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK);
 +            // Paper start
 +            if (this.isTickingReady) {
-+                io.papermc.paper.chunk.system.ChunkSystem.onChunkNotTicking(this.tickingChunkFuture.join().left().get(), this); // Paper
++                io.papermc.paper.chunk.system.ChunkSystem.onChunkNotTicking(this.tickingChunkFuture.join().orElseThrow(IllegalStateException::new), this); // Paper
 +            }
 +            // Paper end
 +            this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage
diff --git a/patches/server/Only-tick-item-frames-if-players-can-see-it.patch b/patches/server/Only-tick-item-frames-if-players-can-see-it.patch
index 4d5169d57a..60e5b70e6d 100644
--- a/patches/server/Only-tick-item-frames-if-players-can-see-it.patch
+++ b/patches/server/Only-tick-item-frames-if-players-can-see-it.patch
@@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          Entity entity = this.entity;
  
 -        if (entity instanceof ItemFrame entityitemframe) {
-+        if (!this.trackedPlayers.isEmpty() && entity instanceof ItemFrame) { // Paper - Perf: Only tick item frames if players can see it
++        if (!this.trackedPlayers.isEmpty() && entity instanceof ItemFrame entityitemframe) { // Paper - Perf: Only tick item frames if players can see it
              if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block
                  ItemStack itemstack = entityitemframe.getItem();