From 09a83f66ee57b5f50daa9d885d9868c5c6e444bc Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Thu, 25 Apr 2024 12:16:00 -0700
Subject: [PATCH] compile fixes

---
 patches/api/More-Enchantment-API.patch        |  4 ++
 ...nate-Current-redstone-implementation.patch |  2 +-
 .../server/Add-PlayerShearBlockEvent.patch    |  8 +--
 patches/server/Adventure.patch                | 24 +++------
 .../Allow-Saving-of-Oversized-Chunks.patch    | 13 +----
 ...culate-regionfile-header-if-it-is-co.patch | 54 +++++++++----------
 patches/server/Collision-optimisations.patch  |  2 +-
 .../Fix-World-isChunkGenerated-calls.patch    |  8 +--
 patches/server/Missing-Entity-API.patch       |  2 +
 patches/server/More-Enchantment-API.patch     | 44 ++-------------
 .../server/Optimise-general-POI-access.patch  |  6 +--
 ...oleAppender-for-console-improvements.patch | 26 +++++++++
 12 files changed, 82 insertions(+), 111 deletions(-)

diff --git a/patches/api/More-Enchantment-API.patch b/patches/api/More-Enchantment-API.patch
index 55863eaed9..7a7f41eb97 100644
--- a/patches/api/More-Enchantment-API.patch
+++ b/patches/api/More-Enchantment-API.patch
@@ -13,6 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@
 +package io.papermc.paper.enchantments;
 +
++@Deprecated(forRemoval = true, since = "As of 1.20.5 enchantments do not have a rarity.")
 +public enum EnchantmentRarity {
 +
 +    COMMON(10),
@@ -99,8 +100,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * Gets the rarity of this enchantment.
 +     *
 +     * @return the rarity
++     * @deprecated As of 1.20.5 enchantments do not have a rarity.
 +     */
 +    @NotNull
++    @Deprecated(forRemoval = true, since = "1.20.5")
++    @Contract("-> fail")
 +    public abstract io.papermc.paper.enchantments.EnchantmentRarity getRarity();
 +
 +    /**
diff --git a/patches/server/Add-Alternate-Current-redstone-implementation.patch b/patches/server/Add-Alternate-Current-redstone-implementation.patch
index 2eea2ae430..b6468d2fd0 100644
--- a/patches/server/Add-Alternate-Current-redstone-implementation.patch
+++ b/patches/server/Add-Alternate-Current-redstone-implementation.patch
@@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import net.minecraft.world.level.block.Block;
 +import net.minecraft.world.level.block.state.BlockState;
 +import net.minecraft.world.level.chunk.ChunkAccess;
-+import net.minecraft.world.level.chunk.ChunkStatus;
++import net.minecraft.world.level.chunk.status.ChunkStatus;
 +import net.minecraft.world.level.chunk.LevelChunkSection;
 +
 +public class LevelHelper {
diff --git a/patches/server/Add-PlayerShearBlockEvent.patch b/patches/server/Add-PlayerShearBlockEvent.patch
index c7ce627503..fab444bab6 100644
--- a/patches/server/Add-PlayerShearBlockEvent.patch
+++ b/patches/server/Add-PlayerShearBlockEvent.patch
@@ -22,10 +22,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
              if (stack.is(Items.SHEARS)) {
 +                // Paper start - Add PlayerShearBlockEvent
-+                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<>());
++                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(stack), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), new java.util.ArrayList<>());
 +                event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3)));
 +                if (!event.callEvent()) {
-+                    return InteractionResult.PASS;
++                    return ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION;
 +                }
 +                // Paper end
                  world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F);
@@ -47,10 +47,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              return ItemInteractionResult.sidedSuccess(world.isClientSide);
          } else {
 +            // Paper start - Add PlayerShearBlockEvent
-+            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<>());
++            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(stack), 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 ItemInteractionResult.PASS;
++                return ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION;
 +            }
 +            // Paper end - Add PlayerShearBlockEvent
              Direction direction = hit.getDirection();
diff --git a/patches/server/Adventure.patch b/patches/server/Adventure.patch
index 1459623dd3..2df02555f9 100644
--- a/patches/server/Adventure.patch
+++ b/patches/server/Adventure.patch
@@ -1627,11 +1627,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +package io.papermc.paper.adventure;
 +
 +import com.mojang.datafixers.util.Pair;
-+import java.util.function.Function;
++import com.mojang.serialization.JavaOps;
 +import net.kyori.adventure.text.Component;
 +import net.kyori.adventure.text.serializer.ComponentSerializer;
 +import net.minecraft.network.chat.ComponentSerialization;
-+import net.minecraft.util.JavaOps;
 +
 +final class WrapperAwareSerializer implements ComponentSerializer<Component, Component, net.minecraft.network.chat.Component> {
 +    @Override
@@ -1640,26 +1639,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            return ((AdventureComponent) input).adventure;
 +        }
 +        final Object obj = ComponentSerialization.CODEC.encodeStart(JavaOps.INSTANCE, input)
-+            .get().map(Function.identity(), partial -> {
-+                throw new RuntimeException("Failed to encode Minecraft Component: " + input + "; " + partial.message());
-+            });
++            .getOrThrow(s -> new RuntimeException("Failed to encode Minecraft Component: " + input + "; " + s));
 +        final Pair<Component, Object> converted = AdventureCodecs.COMPONENT_CODEC.decode(JavaOps.INSTANCE, obj)
-+            .get().map(Function.identity(), partial -> {
-+                throw new RuntimeException("Failed to decode to adventure Component: " + obj + "; " + partial.message());
-+            });
++            .getOrThrow(s -> new RuntimeException("Failed to decode to adventure Component: " + obj + "; " + s));
 +        return converted.getFirst();
 +    }
 +
 +    @Override
 +    public net.minecraft.network.chat.Component serialize(final Component component) {
 +        final Object obj = AdventureCodecs.COMPONENT_CODEC.encodeStart(JavaOps.INSTANCE, component)
-+            .get().map(Function.identity(), partial -> {
-+                throw new RuntimeException("Failed to encode adventure Component: " + component + "; " + partial.message());
-+            });
++            .getOrThrow(s -> new RuntimeException("Failed to encode adventure Component: " + component + "; " + s));
 +        final Pair<net.minecraft.network.chat.Component, Object> converted = ComponentSerialization.CODEC.decode(JavaOps.INSTANCE, obj)
-+            .get().map(Function.identity(), partial -> {
-+                throw new RuntimeException("Failed to decode to Minecraft Component: " + obj + "; " + partial.message());
-+            });
++            .getOrThrow(s -> new RuntimeException("Failed to decode to Minecraft Component: " + obj + "; " + s));
 +        return converted.getFirst();
 +    }
 +}
@@ -5854,10 +5845,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    static <R> R require(final DataResult<R> result, final Function<String, String> errorMessage) {
-+        return switch (result) {
-+            case final DataResult.Error<R> error -> throw new RuntimeException(errorMessage.apply(error.message()));
-+            case final DataResult.Success<R> success -> success.value();
-+        };
++        return result.getOrThrow(s -> new RuntimeException(errorMessage.apply(s)));
 +    }
 +
 +    static List<Tag> invalidData() {
diff --git a/patches/server/Allow-Saving-of-Oversized-Chunks.patch b/patches/server/Allow-Saving-of-Oversized-Chunks.patch
index 8de7939ac8..b402a50327 100644
--- a/patches/server/Allow-Saving-of-Oversized-Chunks.patch
+++ b/patches/server/Allow-Saving-of-Oversized-Chunks.patch
@@ -50,19 +50,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  import net.minecraft.world.level.ChunkPos;
  import org.slf4j.Logger;
  
-@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
-     @VisibleForTesting
-     protected final RegionBitmap usedSectors;
-     public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper
-+    public final Path regionFile; // Paper
- 
-     public RegionFile(RegionStorageInfo storageKey, Path directory, Path path, boolean dsync) throws IOException {
-         this(storageKey, directory, path, RegionFileVersion.getCompressionFormat(), dsync); // Paper - Configurable region compression format
 @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
  
      public RegionFile(RegionStorageInfo storageKey, Path path, Path directory, RegionFileVersion compressionFormat, boolean dsync) throws IOException {
          this.header = ByteBuffer.allocateDirect(8192);
-+        this.regionFile = file; // Paper
 +        initOversizedState(); // Paper
          this.usedSectors = new RegionBitmap();
          this.info = storageKey;
@@ -124,11 +115,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    private Path getOversizedMetaFile() {
-+        return this.regionFile.getParent().resolve(this.regionFile.getFileName().toString().replaceAll("\\.mca$", "") + ".oversized.nbt");
++        return this.path.getParent().resolve(this.path.getFileName().toString().replaceAll("\\.mca$", "") + ".oversized.nbt");
 +    }
 +
 +    private Path getOversizedFile(int x, int z) {
-+        return this.regionFile.getParent().resolve(this.regionFile.getFileName().toString().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt");
++        return this.path.getParent().resolve(this.path.getFileName().toString().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt");
 +    }
 +
 +    synchronized CompoundTag getOversizedData(int x, int z) throws IOException {
diff --git a/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch b/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch
index 4cf82ff216..bb40aeb52b 100644
--- a/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch
+++ b/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch
@@ -91,10 +91,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
 +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
 @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
+     @VisibleForTesting
      protected final RegionBitmap usedSectors;
      public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper
-     public final Path regionFile; // Paper
-+
 +    // Paper start - Attempt to recalculate regionfile header if it is corrupt
 +    private static long roundToSectors(long bytes) {
 +        long sectors = bytes >>> 12; // 4096 = 2^12
@@ -153,15 +152,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    private void backupRegionFile() {
-+        Path backup = this.regionFile.getParent().resolve(this.regionFile.getFileName() + "." + new java.util.Random().nextLong() + ".backup");
++        Path backup = this.path.getParent().resolve(this.path.getFileName() + "." + new java.util.Random().nextLong() + ".backup");
 +        this.backupRegionFile(backup);
 +    }
 +
 +    private void backupRegionFile(Path to) {
 +        try {
 +            this.file.force(true);
-+            LOGGER.warn("Backing up regionfile \"" + this.regionFile.toAbsolutePath() + "\" to " + to.toAbsolutePath());
-+            java.nio.file.Files.copy(this.regionFile, to, java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
++            LOGGER.warn("Backing up regionfile \"" + this.path.toAbsolutePath() + "\" to " + to.toAbsolutePath());
++            java.nio.file.Files.copy(this.path, to, java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
 +            LOGGER.warn("Backed up the regionfile to " + to.toAbsolutePath());
 +        } catch (IOException ex) {
 +            LOGGER.error("Failed to backup to " + to.toAbsolutePath(), ex);
@@ -177,13 +176,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        if (!this.canRecalcHeader) {
 +            return false;
 +        }
-+        ChunkPos ourLowerLeftPosition = RegionFileStorage.getRegionFileCoordinates(this.regionFile);
++        ChunkPos ourLowerLeftPosition = RegionFileStorage.getRegionFileCoordinates(this.path);
 +        if (ourLowerLeftPosition == null) {
-+            LOGGER.error("Unable to get chunk location of regionfile " + this.regionFile.toAbsolutePath() + ", cannot recover header");
++            LOGGER.error("Unable to get chunk location of regionfile " + this.path.toAbsolutePath() + ", cannot recover header");
 +            return false;
 +        }
 +        synchronized (this) {
-+            LOGGER.warn("Corrupt regionfile header detected! Attempting to re-calculate header offsets for regionfile " + this.regionFile.toAbsolutePath(), new Throwable());
++            LOGGER.warn("Corrupt regionfile header detected! Attempting to re-calculate header offsets for regionfile " + this.path.toAbsolutePath(), new Throwable());
 +
 +            // try to backup file so maybe it could be sent to us for further investigation
 +
@@ -207,7 +206,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +                ChunkPos chunkPos = ChunkSerializer.getChunkCoordinate(compound);
 +                if (!inSameRegionfile(ourLowerLeftPosition, chunkPos)) {
-+                    LOGGER.error("Ignoring absolute chunk " + chunkPos + " in regionfile as it is not contained in the bounds of the regionfile '" + this.regionFile.toAbsolutePath() + "'. It should be in regionfile (" + (chunkPos.x >> 5) + "," + (chunkPos.z >> 5) + ")");
++                    LOGGER.error("Ignoring absolute chunk " + chunkPos + " in regionfile as it is not contained in the bounds of the regionfile '" + this.path.toAbsolutePath() + "'. It should be in regionfile (" + (chunkPos.x >> 5) + "," + (chunkPos.z >> 5) + ")");
 +                    continue;
 +                }
 +                int location = (chunkPos.x & 31) | ((chunkPos.z & 31) << 5);
@@ -229,7 +228,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                            isAikarOversized = true;
 +                        }
 +                    } catch (Exception ex) {
-+                        LOGGER.error("Failed to read aikar oversized data for absolute chunk (" + chunkPos.x + "," + chunkPos.z + ") in regionfile " + this.regionFile.toAbsolutePath() + ", oversized data for this chunk will be lost", ex);
++                        LOGGER.error("Failed to read aikar oversized data for absolute chunk (" + chunkPos.x + "," + chunkPos.z + ") in regionfile " + this.path.toAbsolutePath() + ", oversized data for this chunk will be lost", ex);
 +                        // fall through, if we can't read aikar oversized we can't risk corrupting chunk data
 +                    }
 +                }
@@ -337,7 +336,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                    if (newSectorAllocations.tryAllocate(sectorOffset, sectorLength)) {
 +                        calculatedOffsets[location] = sectorOffset << 8 | (sectorLength > 255 ? 255 : sectorLength); // support forge style oversized
 +                    } else {
-+                        LOGGER.error("Failed to allocate space for local chunk (overlapping data??) at (" + chunkX + "," + chunkZ + ") in regionfile " + this.regionFile.toAbsolutePath() + ", chunk will be regenerated");
++                        LOGGER.error("Failed to allocate space for local chunk (overlapping data??) at (" + chunkX + "," + chunkZ + ") in regionfile " + this.path.toAbsolutePath() + ", chunk will be regenerated");
 +                    }
 +                }
 +            }
@@ -361,7 +360,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                        calculatedOffsets[location] = sectorOffset << 8 | (sectorLength > 255 ? 255 : sectorLength); // support forge style oversized
 +                    } catch (IOException ex) {
 +                        newSectorAllocations.free(sectorOffset, sectorLength);
-+                        LOGGER.error("Failed to write new oversized chunk data holder, local chunk at (" + chunkX + "," + chunkZ + ") in regionfile " + this.regionFile.toAbsolutePath() + " will be regenerated");
++                        LOGGER.error("Failed to write new oversized chunk data holder, local chunk at (" + chunkX + "," + chunkZ + ") in regionfile " + this.path.toAbsolutePath() + " will be regenerated");
 +                    }
 +                }
 +            }
@@ -383,7 +382,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                try {
 +                    this.writeOversizedMeta();
 +                } catch (Exception ex) {
-+                    LOGGER.error("Failed to write aikar oversized chunk meta, all aikar style oversized chunk data will be lost for regionfile " + this.regionFile.toAbsolutePath(), ex);
++                    LOGGER.error("Failed to write aikar oversized chunk meta, all aikar style oversized chunk data will be lost for regionfile " + this.path.toAbsolutePath(), ex);
 +                    Files.deleteIfExists(this.getOversizedMetaFile());
 +                }
 +            } else {
@@ -394,7 +393,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +            // before we overwrite the old sectors, print a summary of the chunks that got changed.
 +
-+            LOGGER.info("Starting summary of changes for regionfile " + this.regionFile.toAbsolutePath());
++            LOGGER.info("Starting summary of changes for regionfile " + this.path.toAbsolutePath());
 +
 +            for (int chunkX = 0; chunkX < 32; ++chunkX) {
 +                for (int chunkZ = 0; chunkZ < 32; ++chunkZ) {
@@ -411,16 +410,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +                    if (oldOffset == 0) {
 +                        // found lost data
-+                        LOGGER.info("Found missing data for local chunk (" + chunkX + "," + chunkZ + ") in regionfile " + this.regionFile.toAbsolutePath());
++                        LOGGER.info("Found missing data for local chunk (" + chunkX + "," + chunkZ + ") in regionfile " + this.path.toAbsolutePath());
 +                    } else if (newOffset == 0) {
-+                        LOGGER.warn("Data for local chunk (" + chunkX + "," + chunkZ + ") could not be recovered in regionfile " + this.regionFile.toAbsolutePath() + ", it will be regenerated");
++                        LOGGER.warn("Data for local chunk (" + chunkX + "," + chunkZ + ") could not be recovered in regionfile " + this.path.toAbsolutePath() + ", it will be regenerated");
 +                    } else {
-+                        LOGGER.info("Local chunk (" + chunkX + "," + chunkZ + ") changed to point to newer data or correct chunk in regionfile " + this.regionFile.toAbsolutePath());
++                        LOGGER.info("Local chunk (" + chunkX + "," + chunkZ + ") changed to point to newer data or correct chunk in regionfile " + this.path.toAbsolutePath());
 +                    }
 +                }
 +            }
 +
-+            LOGGER.info("End of change summary for regionfile " + this.regionFile.toAbsolutePath());
++            LOGGER.info("End of change summary for regionfile " + this.path.toAbsolutePath());
 +
 +            // simply destroy the timestamp header, it's not used
 +
@@ -432,9 +431,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            try {
 +                this.flush();
 +                this.file.force(true); // try to ensure it goes through...
-+                LOGGER.info("Successfully wrote new header to disk for regionfile " + this.regionFile.toAbsolutePath());
++                LOGGER.info("Successfully wrote new header to disk for regionfile " + this.path.toAbsolutePath());
 +            } catch (IOException ex) {
-+                LOGGER.error("Failed to write new header to disk for regionfile " + this.regionFile.toAbsolutePath(), ex);
++                LOGGER.error("Failed to write new header to disk for regionfile " + this.path.toAbsolutePath(), ex);
 +            }
 +        }
 +
@@ -443,9 +442,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +    final boolean canRecalcHeader; // final forces compile fail on new constructor
 +    // Paper end - Attempt to recalculate regionfile header if it is corrupt
-+
      // Paper start - Cache chunk status
-     private final net.minecraft.world.level.chunk.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.ChunkStatus[32 * 32];
+     private final net.minecraft.world.level.chunk.status.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.status.ChunkStatus[32 * 32];
  
 @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
      public RegionFile(RegionStorageInfo storageKey, Path directory, Path path, boolean dsync) throws IOException {
@@ -464,8 +462,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        this.canRecalcHeader = canRecalcHeader;
 +        // Paper end - add can recalc flag
          this.header = ByteBuffer.allocateDirect(8192);
-         this.regionFile = file; // Paper
          initOversizedState(); // Paper
+         this.usedSectors = new RegionBitmap();
 @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
                      RegionFile.LOGGER.warn("Region file {} has truncated header: {}", path, i);
                  }
@@ -513,12 +511,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                        // Paper start - recalculate header on header corruption
 +                        if (offset < 2 || sectorLength <= 0 || ((long)offset * 4096L) > regionFileSize) {
 +                            if (canRecalcHeader) {
-+                                LOGGER.error("Detected invalid header for regionfile " + this.regionFile.toAbsolutePath() + "! Recalculating header...");
++                                LOGGER.error("Detected invalid header for regionfile " + this.path.toAbsolutePath() + "! Recalculating header...");
 +                                needsHeaderRecalc = true;
 +                                break;
 +                            } else {
 +                                // location = chunkX | (chunkZ << 5);
-+                                LOGGER.error("Detected invalid header for regionfile " + this.regionFile.toAbsolutePath() +
++                                LOGGER.error("Detected invalid header for regionfile " + this.path.toAbsolutePath() +
 +                                        "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header");
 +                                if (!hasBackedUp) {
 +                                    hasBackedUp = true;
@@ -531,11 +529,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                        }
 +                        boolean failedToAllocate = !this.usedSectors.tryAllocate(offset, sectorLength);
 +                        if (failedToAllocate) {
-+                            LOGGER.error("Overlapping allocation by local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") in regionfile " + this.regionFile.toAbsolutePath());
++                            LOGGER.error("Overlapping allocation by local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") in regionfile " + this.path.toAbsolutePath());
                          }
 +                        if (failedToAllocate & !canRecalcHeader) {
 +                            // location = chunkX | (chunkZ << 5);
-+                            LOGGER.error("Detected invalid header for regionfile " + this.regionFile.toAbsolutePath() +
++                            LOGGER.error("Detected invalid header for regionfile " + this.path.toAbsolutePath() +
 +                                    "! Cannot recalculate, removing local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") from header");
 +                            if (!hasBackedUp) {
 +                                hasBackedUp = true;
@@ -552,7 +550,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                // Paper start - recalculate header on header corruption
 +                // we move the recalc here so comparison to old header is correct when logging to console
 +                if (needsHeaderRecalc) { // true if header gave us overlapping allocations or had other issues
-+                    LOGGER.error("Recalculating regionfile " + this.regionFile.toAbsolutePath() + ", header gave erroneous offsets & locations");
++                    LOGGER.error("Recalculating regionfile " + this.path.toAbsolutePath() + ", header gave erroneous offsets & locations");
 +                    this.recalculateHeader();
 +                }
 +                // Paper end
diff --git a/patches/server/Collision-optimisations.patch b/patches/server/Collision-optimisations.patch
index b732ddac57..e0e42a9dbc 100644
--- a/patches/server/Collision-optimisations.patch
+++ b/patches/server/Collision-optimisations.patch
@@ -127,7 +127,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import net.minecraft.world.level.block.state.BlockState;
 +import net.minecraft.world.level.border.WorldBorder;
 +import net.minecraft.world.level.chunk.ChunkAccess;
-+import net.minecraft.world.level.chunk.ChunkStatus;
++import net.minecraft.world.level.chunk.status.ChunkStatus;
 +import net.minecraft.world.level.chunk.LevelChunkSection;
 +import net.minecraft.world.level.chunk.PalettedContainer;
 +import net.minecraft.world.level.material.FluidState;
diff --git a/patches/server/Fix-World-isChunkGenerated-calls.patch b/patches/server/Fix-World-isChunkGenerated-calls.patch
index 3edf49eab4..67e917d59d 100644
--- a/patches/server/Fix-World-isChunkGenerated-calls.patch
+++ b/patches/server/Fix-World-isChunkGenerated-calls.patch
@@ -94,16 +94,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
 +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
 @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
+     @VisibleForTesting
      protected final RegionBitmap usedSectors;
      public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper
-     public final Path regionFile; // Paper
 +    // Paper start - Cache chunk status
-+    private final net.minecraft.world.level.chunk.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.ChunkStatus[32 * 32];
++    private final net.minecraft.world.level.chunk.status.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.status.ChunkStatus[32 * 32];
 +
 +    private boolean closed;
 +
 +    // invoked on write/read
-+    public void setStatus(int x, int z, net.minecraft.world.level.chunk.ChunkStatus status) {
++    public void setStatus(int x, int z, net.minecraft.world.level.chunk.status.ChunkStatus status) {
 +        if (this.closed) {
 +            // We've used an invalid region file.
 +            throw new IllegalStateException("RegionFile is closed");
@@ -111,7 +111,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        this.statuses[getChunkLocation(x, z)] = status;
 +    }
 +
-+    public net.minecraft.world.level.chunk.ChunkStatus getStatusIfCached(int x, int z) {
++    public net.minecraft.world.level.chunk.status.ChunkStatus getStatusIfCached(int x, int z) {
 +        if (this.closed) {
 +            // We've used an invalid region file.
 +            throw new IllegalStateException("RegionFile is closed");
diff --git a/patches/server/Missing-Entity-API.patch b/patches/server/Missing-Entity-API.patch
index 6258a590a2..a229b75ebd 100644
--- a/patches/server/Missing-Entity-API.patch
+++ b/patches/server/Missing-Entity-API.patch
@@ -30,6 +30,8 @@ public net.minecraft.world.entity.animal.Rabbit moreCarrotTicks
 public net.minecraft.world.entity.AreaEffectCloud ownerUUID
 public net.minecraft.world.entity.animal.MushroomCow stewEffects
 public net.minecraft.world.entity.Entity FLAG_INVISIBLE
+public net.minecraft.world.entity.animal.Cat setRelaxStateOne(Z)V
+public net.minecraft.world.entity.animal.Cat isRelaxStateOne()Z
 
 Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
 Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/patches/server/More-Enchantment-API.patch b/patches/server/More-Enchantment-API.patch
index eb2be97b33..2f7b689c21 100644
--- a/patches/server/More-Enchantment-API.patch
+++ b/patches/server/More-Enchantment-API.patch
@@ -4,7 +4,7 @@ Date: Thu, 6 May 2021 19:57:58 -0700
 Subject: [PATCH] More Enchantment API
 
 == AT ==
-public net.minecraft.world.item.enchantment.Enchantment slots
+public net.minecraft.world.item.enchantment.Enchantment definition
 
 Co-authored-by: Luis <luisc99@icloud.com>
 
@@ -48,7 +48,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +    @Override
 +    public io.papermc.paper.enchantments.EnchantmentRarity getRarity() {
-+        return fromNMSRarity(handle.getRarity());
++        throw new UnsupportedOperationException("Enchantments don't have a rarity anymore in 1.20.5+.");
 +    }
 +
 +    @Override
@@ -80,49 +80,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +    @Override
 +    public java.util.Set<org.bukkit.inventory.EquipmentSlot> getActiveSlots() {
-+        return java.util.stream.Stream.of(handle.slots).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet());
-+    }
-+
-+    public static io.papermc.paper.enchantments.EnchantmentRarity fromNMSRarity(net.minecraft.world.item.enchantment.Enchantment.Rarity nmsRarity) {
-+        if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON) {
-+            return io.papermc.paper.enchantments.EnchantmentRarity.COMMON;
-+        } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.UNCOMMON) {
-+            return io.papermc.paper.enchantments.EnchantmentRarity.UNCOMMON;
-+        } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.RARE) {
-+            return io.papermc.paper.enchantments.EnchantmentRarity.RARE;
-+        } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.VERY_RARE) {
-+            return io.papermc.paper.enchantments.EnchantmentRarity.VERY_RARE;
-+        }
-+
-+        throw new IllegalArgumentException(String.format("Unable to convert %s to a enum value of %s.", nmsRarity, io.papermc.paper.enchantments.EnchantmentRarity.class));
++        return java.util.stream.Stream.of(handle.definition.slots()).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet());
 +    }
      // Paper end
  
      @Override
-diff --git a/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java
-@@ -0,0 +0,0 @@
-+package io.papermc.paper.enchantments;
-+
-+import net.minecraft.world.item.enchantment.Enchantment.Rarity;
-+import org.bukkit.craftbukkit.enchantments.CraftEnchantment;
-+import org.junit.jupiter.api.Test;
-+
-+import static org.junit.jupiter.api.Assertions.assertNotNull;
-+
-+public class EnchantmentRarityTest {
-+
-+    @Test
-+    public void test() {
-+        for (Rarity nmsRarity : Rarity.values()) {
-+            // Will throw exception if a bukkit counterpart is not found
-+            CraftEnchantment.fromNMSRarity(nmsRarity);
-+        }
-+    }
-+}
 diff --git a/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java
 new file mode 100644
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
diff --git a/patches/server/Optimise-general-POI-access.patch b/patches/server/Optimise-general-POI-access.patch
index 74db7a83d4..cd044aabd7 100644
--- a/patches/server/Optimise-general-POI-access.patch
+++ b/patches/server/Optimise-general-POI-access.patch
@@ -1029,9 +1029,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            villageplace,
 +            type -> type.is(PoiTypes.NETHER_PORTAL),
 +            (BlockPos pos) -> {
-+                net.minecraft.world.level.chunk.ChunkAccess lowest = this.level.getChunk(pos.getX() >> 4, pos.getZ() >> 4, net.minecraft.world.level.chunk.ChunkStatus.EMPTY);
-+                if (!lowest.getStatus().isOrAfter(net.minecraft.world.level.chunk.ChunkStatus.FULL)
-+                    && (lowest.getBelowZeroRetrogen() == null || !lowest.getBelowZeroRetrogen().targetStatus().isOrAfter(net.minecraft.world.level.chunk.ChunkStatus.SPAWN))) {
++                net.minecraft.world.level.chunk.ChunkAccess lowest = this.level.getChunk(pos.getX() >> 4, pos.getZ() >> 4, net.minecraft.world.level.chunk.status.ChunkStatus.EMPTY);
++                if (!lowest.getStatus().isOrAfter(net.minecraft.world.level.chunk.status.ChunkStatus.FULL)
++                    && (lowest.getBelowZeroRetrogen() == null || !lowest.getBelowZeroRetrogen().targetStatus().isOrAfter(net.minecraft.world.level.chunk.status.ChunkStatus.SPAWN))) {
 +                    // why would we generate the chunk?
 +                    return false;
 +                }
diff --git a/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch
index a8beacefeb..07441aa8c4 100644
--- a/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch
+++ b/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch
@@ -592,6 +592,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              } catch (Exception e) {
              }
          }
+diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalCompletionHandler.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalCompletionHandler.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/util/TerminalCompletionHandler.java
++++ b/src/main/java/org/bukkit/craftbukkit/util/TerminalCompletionHandler.java
+@@ -0,0 +0,0 @@ import java.io.IOException;
+ import java.util.HashSet;
+ import java.util.List;
+ import java.util.Set;
+-import jline.console.ConsoleReader;
+-import jline.console.completer.CompletionHandler;
+ 
+ /**
+  * SPIGOT-6705: Make sure we print the display line again on tab completion, so that the user does not get stuck on it
+  * e.g. The user needs to press y / n to continue
+  */
+-public class TerminalCompletionHandler implements CompletionHandler {
++public class TerminalCompletionHandler /* implements CompletionHandler */ { /* Paper - comment out whole class
+ 
+     private final TerminalConsoleWriterThread writerThread;
+     private final CompletionHandler delegate;
+@@ -0,0 +0,0 @@ public class TerminalCompletionHandler implements CompletionHandler {
+ 
+         return result;
+     }
++*/ // Paper end - comment out whole class
+ }
 diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java