From 9b34dc14d92a468a57f6354671cb95a2242519f4 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 14 Jun 2024 14:07:44 -0700
Subject: [PATCH] remove api that was scheduled for removal

---
 patches/api/Add-Heightmap-API.patch           | 153 --------
 .../Add-ItemStackRecipeChoice-Draft-API.patch |  67 ----
 patches/api/Add-PlayerInitialSpawnEvent.patch |  32 --
 patches/api/Add-PlayerLocaleChangeEvent.patch |  72 ----
 patches/api/Add-StructuresLocateEvent.patch   | 347 +-----------------
 patches/api/Add-missing-effects.patch         |  87 +----
 patches/api/Adventure.patch                   |  13 -
 patches/api/EntityTransformedEvent.patch      | 107 ------
 ...orldBorder-isInBounds-Location-check.patch |  29 --
 patches/api/More-PotionEffectType-API.patch   |   8 +-
 patches/api/More-World-API.patch              |  50 ---
 patches/server/Add-Heightmap-API.patch        |  40 --
 .../server/Add-StructuresLocateEvent.patch    | 196 ----------
 ...wn-location-event-changing-location.patch} |  16 +-
 .../Implement-Player-Client-Options-API.patch |   2 +-
 patches/server/More-World-API.patch           |  25 --
 ...patch => Use-null-Locale-by-default.patch} |   5 +-
 17 files changed, 13 insertions(+), 1236 deletions(-)
 delete mode 100644 patches/api/Add-ItemStackRecipeChoice-Draft-API.patch
 delete mode 100644 patches/api/Add-PlayerInitialSpawnEvent.patch
 delete mode 100644 patches/api/Add-PlayerLocaleChangeEvent.patch
 delete mode 100644 patches/api/EntityTransformedEvent.patch
 delete mode 100644 patches/api/Expose-WorldBorder-isInBounds-Location-check.patch
 delete mode 100644 patches/server/Add-Heightmap-API.patch
 rename patches/server/{Add-PlayerInitialSpawnEvent.patch => Fix-spawn-location-event-changing-location.patch} (58%)
 rename patches/server/{Implement-PlayerLocaleChangeEvent.patch => Use-null-Locale-by-default.patch} (89%)

diff --git a/patches/api/Add-Heightmap-API.patch b/patches/api/Add-Heightmap-API.patch
index fc06929944..add1d9adf9 100644
--- a/patches/api/Add-Heightmap-API.patch
+++ b/patches/api/Add-Heightmap-API.patch
@@ -5,51 +5,6 @@ Subject: [PATCH] Add Heightmap API
 
 Changed to use upstream's heightmap API - Machine_Maker
 
-diff --git a/src/main/java/com/destroystokyo/paper/HeightmapType.java b/src/main/java/com/destroystokyo/paper/HeightmapType.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/com/destroystokyo/paper/HeightmapType.java
-@@ -0,0 +0,0 @@
-+package com.destroystokyo.paper;
-+
-+import org.jetbrains.annotations.ApiStatus;
-+
-+/**
-+ * Enumeration of different heightmap types maintained by the server. Generally using these maps is much faster
-+ * than using an iterative search for a block in a given x, z coordinate.
-+ *
-+ * @deprecated Upstream has added their own API for using the game heightmaps. See {@link org.bukkit.HeightMap} and the
-+ * non-deprecated getHighestBlock methods on World such as {@link org.bukkit.World#getHighestBlockAt(org.bukkit.Location, org.bukkit.HeightMap)}.
-+ */
-+@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+public enum HeightmapType {
-+
-+    /**
-+     * The highest block used for lighting in the world. Also the block returned by {@link org.bukkit.World#getHighestBlockYAt(int, int)}}
-+     */
-+    LIGHT_BLOCKING,
-+
-+    /**
-+     * References the highest block in the world.
-+     */
-+    ANY,
-+
-+    /**
-+     * References the highest solid block in a world.
-+     */
-+    SOLID,
-+
-+    /**
-+     * References the highest solid or liquid block in a world.
-+     */
-+    SOLID_OR_LIQUID,
-+
-+    /**
-+     * References the highest solid or liquid block in a world, excluding leaves.
-+     */
-+    SOLID_OR_LIQUID_NO_LEAVES;
-+}
 diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/Location.java
@@ -70,22 +25,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    /**
-+     * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightmap)
-+     * @param heightmap The heightmap to use for finding the highest y location.
-+     * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightmap)
-+     * @throws NullPointerException if {{@link #getWorld()}} is {@code null}
-+     * @throws UnsupportedOperationException if {@link World#getHighestBlockYAt(int, int, com.destroystokyo.paper.HeightmapType)} does not support the specified heightmap
-+     * @deprecated Use {@link org.bukkit.Location#toHighestLocation(HeightMap)}
-+     */
-+    @NotNull
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    public Location toHighestLocation(@NotNull final com.destroystokyo.paper.HeightmapType heightmap) {
-+        final Location ret = this.clone();
-+        ret.setY(this.getWorld().getHighestBlockYAt(this, heightmap));
-+        return ret;
-+    }
-+
-+    /**
 +     * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightMap)
 +     * @param heightMap The heightmap to use for finding the highest y location.
 +     * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ(), heightMap)
@@ -101,95 +40,3 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      // Paper start - Expand Explosions API
      /**
       * Creates explosion at this location with given power
-diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/World.java
-+++ b/src/main/java/org/bukkit/World.java
-@@ -0,0 +0,0 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
-     @NotNull
-     public Block getHighestBlockAt(@NotNull Location location);
- 
-+    // Paper start - Add heightmap API
-+    /**
-+     * Returns the highest block's y-coordinate at the specified block coordinates that match the specified heightmap's conditions.
-+     * <p>
-+     * <b>implNote:</b> Implementations are recommended to use an iterative search as a fallback before resorting to
-+     * throwing an {@code UnsupportedOperationException}.
-+     * </p>
-+     *
-+     * @param x The block's x-coordinate.
-+     * @param z The block's z-coordinate.
-+     * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType}
-+     * @return The highest block's y-coordinate at (x, z) that matches the specified heightmap's conditions.
-+     * @throws UnsupportedOperationException If the heightmap type is not supported.
-+     * @deprecated Upstream has added support for this, use {@link World#getHighestBlockYAt(int, int, HeightMap)}
-+     *
-+     * @see com.destroystokyo.paper.HeightmapType
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    public int getHighestBlockYAt(int x, int z, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException;
-+
-+    /**
-+     * Returns the highest block's y-coordinate at the specified block coordinates that match the specified heightmap's conditions.
-+     * Note that the y-coordinate of the specified location is ignored.
-+     * <p>
-+     * <b>implNote:</b> Implementations are recommended to use an iterative search as a fallback before resorting to
-+     * throwing an {@code UnsupportedOperationException}.
-+     * </p>
-+     *
-+     * @param location The specified block coordinates.
-+     * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType}
-+     * @return The highest block's y-coordinate at {@code location} that matches the specified heightmap's conditions.
-+     * @throws UnsupportedOperationException If the heightmap type is not supported.
-+     * @deprecated Upstream has added support for this, use {@link World#getHighestBlockYAt(Location, HeightMap)}
-+     * @see com.destroystokyo.paper.HeightmapType
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    default int getHighestBlockYAt(@NotNull Location location, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException {
-+        return this.getHighestBlockYAt(location.getBlockX(), location.getBlockZ(), heightmap);
-+    }
-+
-+    /**
-+     * Returns the highest {@link Block} at the specified block coordinates that match the specified heightmap's conditions.
-+     * <p>
-+     * <b>implNote:</b> Implementations are recommended to use an iterative search as a fallback before resorting to
-+     * throwing an {@code UnsupportedOperationException}.
-+     * </p>
-+     * @param x The block's x-coordinate.
-+     * @param z The block's z-coordinate.
-+     * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType}
-+     * @return The highest {@link Block} at (x, z) that matches the specified heightmap's conditions.
-+     * @throws UnsupportedOperationException If the heightmap type is not supported.
-+     * @deprecated Upstream has added support for this, use {@link World#getHighestBlockAt(int, int, HeightMap)}
-+     * @see com.destroystokyo.paper.HeightmapType
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    @NotNull
-+    default Block getHighestBlockAt(int x, int z, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException {
-+        return this.getBlockAt(x, this.getHighestBlockYAt(x, z, heightmap), z);
-+    }
-+
-+    /**
-+     * Returns the highest {@link Block} at the specified block coordinates that match the specified heightmap's conditions.
-+     * Note that the y-coordinate of the specified location is ignored.
-+     * <p>
-+     * <b>implNote:</b> Implementations are recommended to use an iterative search as a fallback before resorting to
-+     * throwing an {@code UnsupportedOperationException}.
-+     * </p>
-+     * @param location The specified block coordinates.
-+     * @param heightmap The specified heightmap to use. See {@link com.destroystokyo.paper.HeightmapType}
-+     * @return The highest {@link Block} at {@code location} that matches the specified heightmap's conditions.
-+     * @throws UnsupportedOperationException If the heightmap type is not supported.
-+     * @deprecated Upstream has added support for this, use {@link World#getHighestBlockAt(Location, HeightMap)}
-+     * @see com.destroystokyo.paper.HeightmapType
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    @NotNull
-+    default Block getHighestBlockAt(@NotNull Location location, @NotNull com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException {
-+        return this.getHighestBlockAt(location.getBlockX(), location.getBlockZ(), heightmap);
-+    }
-+    // Paper end
-+
-     /**
-      * Gets the highest block corresponding to the {@link HeightMap} at the
-      * given coordinates.
diff --git a/patches/api/Add-ItemStackRecipeChoice-Draft-API.patch b/patches/api/Add-ItemStackRecipeChoice-Draft-API.patch
deleted file mode 100644
index f8f45f7bd0..0000000000
--- a/patches/api/Add-ItemStackRecipeChoice-Draft-API.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Aikar <aikar@aikar.co>
-Date: Thu, 13 Sep 2018 21:39:26 -0400
-Subject: [PATCH] Add ItemStackRecipeChoice Draft API
-
-This is based on Spigots Draft API. This is subject to change
-
-Allows creating recipes that must match isSimilar to full item stack.
-
-diff --git a/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java b/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/com/destroystokyo/paper/inventory/ItemStackRecipeChoice.java
-@@ -0,0 +0,0 @@
-+package com.destroystokyo.paper.inventory;
-+
-+import org.bukkit.inventory.ItemStack;
-+import org.bukkit.inventory.RecipeChoice;
-+
-+import java.util.ArrayList;
-+import java.util.List;
-+import org.jetbrains.annotations.ApiStatus;
-+
-+/**
-+ * Allows crafting Items that require full matching itemstacks to complete the recipe for custom items
-+ * @deprecated Draft API
-+ */
-+@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+public class ItemStackRecipeChoice implements RecipeChoice {
-+
-+    protected final List<ItemStack> choices = new ArrayList<>();
-+
-+    public ItemStackRecipeChoice(ItemStack choices) {
-+        this.choices.add(choices);
-+    }
-+
-+    public ItemStackRecipeChoice(List<ItemStack> choices) {
-+        this.choices.addAll(choices);
-+    }
-+
-+    @Override
-+    public ItemStack getItemStack() {
-+        return choices.isEmpty() ? null : choices.get(0);
-+    }
-+
-+    @Override
-+    public RecipeChoice clone() {
-+        try {
-+            ItemStackRecipeChoice clone = (ItemStackRecipeChoice) super.clone();
-+            clone.choices.addAll(this.choices);
-+            return clone;
-+        } catch (CloneNotSupportedException ex) {
-+            throw new AssertionError(ex);
-+        }
-+    }
-+
-+    @Override
-+    public boolean test(ItemStack itemStack) {
-+        for (ItemStack stack : choices) {
-+            if (stack.isSimilar(itemStack)) {
-+                return true;
-+            }
-+        }
-+        return false;
-+    }
-+}
diff --git a/patches/api/Add-PlayerInitialSpawnEvent.patch b/patches/api/Add-PlayerInitialSpawnEvent.patch
deleted file mode 100644
index c5077e2cd2..0000000000
--- a/patches/api/Add-PlayerInitialSpawnEvent.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Steve Anton <anxuiz.nx@gmail.com>
-Date: Mon, 29 Feb 2016 18:13:58 -0600
-Subject: [PATCH] Add PlayerInitialSpawnEvent
-
-For modifying a player's initial spawn location as they join the server
-
-diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerInitialSpawnEvent.java
-@@ -0,0 +0,0 @@
-+package com.destroystokyo.paper.event.player;
-+
-+import org.bukkit.Location;
-+import org.bukkit.entity.Player;
-+import org.jetbrains.annotations.ApiStatus;
-+import org.jetbrains.annotations.NotNull;
-+import org.spigotmc.event.player.PlayerSpawnLocationEvent;
-+
-+/**
-+ * @deprecated Use {@link PlayerSpawnLocationEvent}, Duplicate API
-+ */
-+@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+public class PlayerInitialSpawnEvent extends PlayerSpawnLocationEvent {
-+
-+    @ApiStatus.Internal
-+    public PlayerInitialSpawnEvent(@NotNull Player player, @NotNull Location spawnLocation) {
-+        super(player, spawnLocation);
-+    }
-+}
diff --git a/patches/api/Add-PlayerLocaleChangeEvent.patch b/patches/api/Add-PlayerLocaleChangeEvent.patch
deleted file mode 100644
index 0dcfedba82..0000000000
--- a/patches/api/Add-PlayerLocaleChangeEvent.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Isaac Moore <rmsy@me.com>
-Date: Mon, 29 Feb 2016 18:02:25 -0600
-Subject: [PATCH] Add PlayerLocaleChangeEvent
-
-
-diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerLocaleChangeEvent.java
-@@ -0,0 +0,0 @@
-+package com.destroystokyo.paper.event.player;
-+
-+import org.bukkit.entity.Player;
-+import org.bukkit.event.HandlerList;
-+import org.bukkit.event.player.PlayerEvent;
-+import org.jetbrains.annotations.ApiStatus;
-+import org.jetbrains.annotations.NotNull;
-+import org.jetbrains.annotations.Nullable;
-+
-+/**
-+ * Called when the locale of the player is changed.
-+ *
-+ * @deprecated Replaced by {@link org.bukkit.event.player.PlayerLocaleChangeEvent} upstream
-+ */
-+@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+public class PlayerLocaleChangeEvent extends PlayerEvent {
-+
-+    private static final HandlerList HANDLER_LIST = new HandlerList();
-+
-+    private final String oldLocale;
-+    private final String newLocale;
-+
-+    @ApiStatus.Internal
-+    public PlayerLocaleChangeEvent(final @NotNull Player player, final @Nullable String oldLocale, final @NotNull String newLocale) {
-+        super(player);
-+        this.oldLocale = oldLocale;
-+        this.newLocale = newLocale;
-+    }
-+
-+    /**
-+     * Gets the locale the player switched from.
-+     *
-+     * @return player's old locale
-+     */
-+    @Nullable
-+    public String getOldLocale() {
-+        return this.oldLocale;
-+    }
-+
-+    /**
-+     * Gets the locale the player is changed to.
-+     *
-+     * @return player's new locale
-+     */
-+    @NotNull
-+    public String getNewLocale() {
-+        return this.newLocale;
-+    }
-+
-+    @Override
-+    @NotNull
-+    public HandlerList getHandlers() {
-+        return HANDLER_LIST;
-+    }
-+
-+    @NotNull
-+    public static HandlerList getHandlerList() {
-+        return HANDLER_LIST;
-+    }
-+}
diff --git a/patches/api/Add-StructuresLocateEvent.patch b/patches/api/Add-StructuresLocateEvent.patch
index b9c4a511c1..92be15dbc0 100644
--- a/patches/api/Add-StructuresLocateEvent.patch
+++ b/patches/api/Add-StructuresLocateEvent.patch
@@ -5,175 +5,6 @@ Subject: [PATCH] Add StructuresLocateEvent
 
 Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
 
-diff --git a/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java b/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java
-@@ -0,0 +0,0 @@
-+package io.papermc.paper.event.world;
-+
-+import org.bukkit.Location;
-+import org.bukkit.StructureType;
-+import org.bukkit.World;
-+import org.bukkit.event.Cancellable;
-+import org.bukkit.event.HandlerList;
-+import org.bukkit.event.world.WorldEvent;
-+import org.jetbrains.annotations.ApiStatus;
-+import org.jetbrains.annotations.NotNull;
-+import org.jetbrains.annotations.Nullable;
-+
-+/**
-+ * Called <b>before</b> a structure/feature is located.
-+ * This happens when:
-+ * <ul>
-+ *     <li>The /locate command is used.<br></li>
-+ *     <li>An Eye of Ender is used.</li>
-+ *     <li>An Explorer/Treasure Map is activated.</li>
-+ *     <li>{@link World#locateNearestStructure(Location, StructureType, int, boolean)} is invoked.</li>
-+ * </ul>
-+ *
-+ * @deprecated no longer used, see {@link StructuresLocateEvent}
-+ */
-+@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+public class StructureLocateEvent extends WorldEvent implements Cancellable {
-+
-+    private static final HandlerList HANDLER_LIST = new HandlerList();
-+
-+    private final Location origin;
-+    private Location result = null;
-+    private StructureType type;
-+    private int radius;
-+    private boolean findUnexplored;
-+
-+    private boolean cancelled;
-+
-+    @ApiStatus.Internal
-+    public StructureLocateEvent(@NotNull World world, @NotNull Location origin, @NotNull StructureType structureType, int radius, boolean findUnexplored) {
-+        super(world);
-+        this.origin = origin;
-+        this.type = structureType;
-+        this.radius = radius;
-+        this.findUnexplored = findUnexplored;
-+    }
-+
-+    /**
-+     * Gets the location set as the structure location, if it was defined.
-+     * <p>
-+     * Returns {@code null} if it has not been set by {@link StructureLocateEvent#setResult(Location)}.
-+     * Since this event fires <i>before</i> the search is done, the actual location is unknown at this point.
-+     *
-+     * @return The result location, if it has been set. {@code null} if it has not.
-+     * @see World#locateNearestStructure(Location, StructureType, int, boolean)
-+     */
-+    @Nullable
-+    public Location getResult() {
-+        return this.result;
-+    }
-+
-+    /**
-+     * Sets the result {@link Location}. This causes the search to be skipped, and the location passed here to be used as the result.
-+     *
-+     * @param result the {@link Location} of the structure.
-+     */
-+    public void setResult(@Nullable Location result) {
-+        this.result = result;
-+    }
-+
-+    /**
-+     * Gets the {@link StructureType} that is to be located.
-+     *
-+     * @return the structure type.
-+     */
-+    @NotNull
-+    public StructureType getType() {
-+        return this.type;
-+    }
-+
-+    /**
-+     * Sets the {@link StructureType} that is to be located.
-+     *
-+     * @param type the structure type.
-+     */
-+    public void setType(@NotNull StructureType type) {
-+        this.type = type;
-+    }
-+
-+    /**
-+     * Gets the {@link Location} from which the search is to be conducted.
-+     *
-+     * @return {@link Location} where search begins
-+     */
-+    @NotNull
-+    public Location getOrigin() {
-+        return this.origin;
-+    }
-+
-+    /**
-+     * Gets the search radius in which to attempt locating the structure.
-+     * <p>
-+     * This radius may not always be obeyed during the structure search!
-+     *
-+     * @return the search radius.
-+     */
-+    public int getRadius() {
-+        return this.radius;
-+    }
-+
-+    /**
-+     * Sets the search radius in which to attempt locating the structure.
-+     * <p>
-+     * This radius may not always be obeyed during the structure search!
-+     *
-+     * @param radius the search radius.
-+     */
-+    public void setRadius(int radius) {
-+        this.radius = radius;
-+    }
-+
-+    /**
-+     * Gets whether to search exclusively for unexplored structures.
-+     * <p>
-+     * As with the search radius, this value is not always obeyed.
-+     *
-+     * @return Whether to search for only unexplored structures.
-+     */
-+    public boolean shouldFindUnexplored() {
-+        return this.findUnexplored;
-+    }
-+
-+    /**
-+     * Sets whether to search exclusively for unexplored structures.
-+     * <p>
-+     * As with the search radius, this value is not always obeyed.
-+     *
-+     * @param findUnexplored Whether to search for only unexplored structures.
-+     */
-+    public void setFindUnexplored(boolean findUnexplored) {
-+        this.findUnexplored = findUnexplored;
-+    }
-+
-+    @Override
-+    public boolean isCancelled() {
-+        return this.cancelled;
-+    }
-+
-+    @Override
-+    public void setCancelled(boolean cancel) {
-+        this.cancelled = cancel;
-+    }
-+
-+    @NotNull
-+    public static HandlerList getHandlerList() {
-+        return HANDLER_LIST;
-+    }
-+
-+    @NotNull
-+    @Override
-+    public HandlerList getHandlers() {
-+        return HANDLER_LIST;
-+    }
-+}
 diff --git a/src/main/java/io/papermc/paper/event/world/StructuresLocateEvent.java b/src/main/java/io/papermc/paper/event/world/StructuresLocateEvent.java
 new file mode 100644
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
@@ -183,11 +14,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +package io.papermc.paper.event.world;
 +
 +import io.papermc.paper.math.Position;
-+import io.papermc.paper.util.TransformingRandomAccessList;
-+import io.papermc.paper.world.structure.ConfiguredStructure;
 +import java.util.Collections;
 +import java.util.List;
-+import java.util.Objects;
 +import org.bukkit.Location;
 +import org.bukkit.World;
 +import org.bukkit.event.Cancellable;
@@ -220,7 +48,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    private final Location origin;
 +    private Result result;
 +    private List<Structure> structures;
-+    private List<ConfiguredStructure> legacy$structures;
 +    private int radius;
 +    private boolean findUnexplored;
 +
@@ -230,7 +57,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    public StructuresLocateEvent(@NotNull World world, @NotNull Location origin, @NotNull List<Structure> structures, int radius, boolean findUnexplored) {
 +        super(world);
 +        this.origin = origin;
-+        this.setStructures(structures);
++        this.structures = structures;
 +        this.radius = radius;
 +        this.findUnexplored = findUnexplored;
 +    }
@@ -268,28 +95,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    /**
-+     * Gets a mutable list of ConfiguredStructures that are valid targets for the search.
-+     *
-+     * @return a mutable list of ConfiguredStructures
-+     * @deprecated use {@link #getStructures()}
-+     */
-+    @Deprecated(forRemoval = true)
-+    public @NotNull List<ConfiguredStructure> getConfiguredStructures() {
-+        return this.legacy$structures;
-+    }
-+
-+    /**
-+     * Sets the list of ConfiguredStructures that are valid targets for the search.
-+     *
-+     * @param configuredStructures a list of ConfiguredStructure targets
-+     * @deprecated use {@link #setStructures(List)}
-+     */
-+    @Deprecated(forRemoval = true)
-+    public void setConfiguredStructures(@NotNull List<ConfiguredStructure> configuredStructures) {
-+        this.setStructures(configuredStructures.stream().map(ConfiguredStructure::toModern).toList());
-+    }
-+
-+    /**
 +     * Gets an unmodifiable list of Structures that are valid targets for the search.
 +     *
 +     * @return an unmodifiable list of Structures
@@ -305,7 +110,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     */
 +    public void setStructures(final @NotNull List<Structure> structures) {
 +        this.structures = structures;
-+        this.legacy$structures = new TransformingRandomAccessList<>(this.structures, ConfiguredStructure::fromModern, ConfiguredStructure::toModern);
 +    }
 +
 +    /**
@@ -377,158 +181,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    public record Result(@NotNull Position pos, @NotNull Structure structure) {
 +
 +        @Deprecated(forRemoval = true)
-+        public Result(final @NotNull Location position, @NotNull ConfiguredStructure configuredStructure) {
-+            this(position, configuredStructure.toModern());
-+        }
-+
-+        @Deprecated(forRemoval = true)
-+        public @NotNull ConfiguredStructure configuredStructure() {
-+            return Objects.requireNonNull(ConfiguredStructure.fromModern(this.structure), "Please use the newer Structure API");
-+        }
-+
-+        @Deprecated(forRemoval = true)
 +        public @NotNull Location position() {
 +            //noinspection DataFlowIssue
 +            return this.pos.toLocation(null);
 +        }
 +    }
 +}
-diff --git a/src/main/java/io/papermc/paper/world/structure/ConfiguredStructure.java b/src/main/java/io/papermc/paper/world/structure/ConfiguredStructure.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/io/papermc/paper/world/structure/ConfiguredStructure.java
-@@ -0,0 +0,0 @@
-+package io.papermc.paper.world.structure;
-+
-+import io.papermc.paper.registry.Reference;
-+import java.util.Objects;
-+import org.bukkit.Keyed;
-+import org.bukkit.NamespacedKey;
-+import org.bukkit.Registry;
-+import org.bukkit.StructureType;
-+import org.bukkit.generator.structure.Structure;
-+import org.jetbrains.annotations.ApiStatus;
-+import org.jetbrains.annotations.NotNull;
-+import org.jetbrains.annotations.Nullable;
-+
-+/**
-+ * Represents a configured structure each with a
-+ * {@link StructureType}. Multiple ConfiguredStructures can have
-+ * the same {@link StructureType}.
-+ * @deprecated use {@link Structure}
-+ */
-+@Deprecated(forRemoval = true)
-+@ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+public final class ConfiguredStructure implements Keyed {
-+
-+    public static final Reference<ConfiguredStructure> PILLAGER_OUTPOST = create("pillager_outpost");
-+    public static final Reference<ConfiguredStructure> MINESHAFT = create("mineshaft");
-+    public static final Reference<ConfiguredStructure> MINESHAFT_MESA = create("mineshaft_mesa");
-+    public static final Reference<ConfiguredStructure> WOODLAND_MANSION = create("mansion");
-+    public static final Reference<ConfiguredStructure> JUNGLE_TEMPLE = create("jungle_pyramid");
-+    public static final Reference<ConfiguredStructure> DESERT_PYRAMID = create("desert_pyramid");
-+    public static final Reference<ConfiguredStructure> IGLOO = create("igloo");
-+    public static final Reference<ConfiguredStructure> SHIPWRECK = create("shipwreck");
-+    public static final Reference<ConfiguredStructure> SHIPWRECK_BEACHED = create("shipwreck_beached");
-+    public static final Reference<ConfiguredStructure> SWAMP_HUT = create("swamp_hut");
-+    public static final Reference<ConfiguredStructure> STRONGHOLD = create("stronghold");
-+    public static final Reference<ConfiguredStructure> OCEAN_MONUMENT = create("monument");
-+    public static final Reference<ConfiguredStructure> OCEAN_RUIN_COLD = create("ocean_ruin_cold");
-+    public static final Reference<ConfiguredStructure> OCEAN_RUIN_WARM = create("ocean_ruin_warm");
-+    public static final Reference<ConfiguredStructure> FORTRESS = create("fortress");
-+    public static final Reference<ConfiguredStructure> NETHER_FOSSIL = create("nether_fossil");
-+    public static final Reference<ConfiguredStructure> END_CITY = create("end_city");
-+    public static final Reference<ConfiguredStructure> BURIED_TREASURE = create("buried_treasure");
-+    public static final Reference<ConfiguredStructure> BASTION_REMNANT = create("bastion_remnant");
-+    public static final Reference<ConfiguredStructure> VILLAGE_PLAINS = create("village_plains");
-+    public static final Reference<ConfiguredStructure> VILLAGE_DESERT = create("village_desert");
-+    public static final Reference<ConfiguredStructure> VILLAGE_SAVANNA = create("village_savanna");
-+    public static final Reference<ConfiguredStructure> VILLAGE_SNOWY = create("village_snowy");
-+    public static final Reference<ConfiguredStructure> VILLAGE_TAIGA = create("village_taiga");
-+    public static final Reference<ConfiguredStructure> RUINED_PORTAL_STANDARD = create("ruined_portal");
-+    public static final Reference<ConfiguredStructure> RUINED_PORTAL_DESERT = create("ruined_portal_desert");
-+    public static final Reference<ConfiguredStructure> RUINED_PORTAL_JUNGLE = create("ruined_portal_jungle");
-+    public static final Reference<ConfiguredStructure> RUINED_PORTAL_SWAMP = create("ruined_portal_swamp");
-+    public static final Reference<ConfiguredStructure> RUINED_PORTAL_MOUNTAIN = create("ruined_portal_mountain");
-+    public static final Reference<ConfiguredStructure> RUINED_PORTAL_OCEAN = create("ruined_portal_ocean");
-+    public static final Reference<ConfiguredStructure> RUINED_PORTAL_NETHER = create("ruined_portal_nether");
-+    // public static final Reference<ConfiguredStructure> ANCIENT_CITY = create("ancient_city"); // TODO remove when upstream adds "jigsaw" StructureType
-+
-+    private final NamespacedKey key;
-+    private final StructureType structureType;
-+
-+    ConfiguredStructure(@NotNull NamespacedKey key, @NotNull StructureType structureType) {
-+        this.key = key;
-+        this.structureType = structureType;
-+    }
-+
-+    @Override
-+    public @NotNull NamespacedKey getKey() {
-+        return this.key;
-+    }
-+
-+    /**
-+     * Gets the structure type for this configure structure.
-+     *
-+     * @return the structure type
-+     */
-+    public @NotNull StructureType getStructureType() {
-+        return this.structureType;
-+    }
-+
-+    @Override
-+    public boolean equals(Object o) {
-+        if (this == o) return true;
-+        if (o == null || getClass() != o.getClass()) return false;
-+        ConfiguredStructure structure = (ConfiguredStructure) o;
-+        return this.key.equals(structure.key) && this.structureType.equals(structure.structureType);
-+    }
-+
-+    @Override
-+    public int hashCode() {
-+        return Objects.hash(this.key, this.structureType);
-+    }
-+
-+    @Override
-+    public String toString() {
-+        return "ConfiguredStructure{" +
-+            "key=" + this.key +
-+            ", structureType=" + this.structureType +
-+            '}';
-+    }
-+
-+    private static @NotNull Reference<ConfiguredStructure> create(@NotNull String name) {
-+        return Reference.create(Registry.CONFIGURED_STRUCTURE, NamespacedKey.minecraft(name));
-+    }
-+
-+    @ApiStatus.Internal
-+    public @NotNull Structure toModern() {
-+        return Objects.requireNonNull(Registry.STRUCTURE.get(this.key));
-+    }
-+
-+    @ApiStatus.Internal
-+    public static @Nullable ConfiguredStructure fromModern(@NotNull Structure structure) {
-+        return Registry.CONFIGURED_STRUCTURE.get(structure.getKey());
-+    }
-+}
-diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/Registry.java
-+++ b/src/main/java/org/bukkit/Registry.java
-@@ -0,0 +0,0 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
-      * @see GameEvent
-      */
-     Registry<GameEvent> GAME_EVENT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.GAME_EVENT); // Paper
-+    // Paper start
-+    /**
-+     * Configured structures.
-+     * @see io.papermc.paper.world.structure.ConfiguredStructure
-+     * @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#STRUCTURE}
-+     */
-+    @Deprecated(forRemoval = true)
-+    Registry<io.papermc.paper.world.structure.ConfiguredStructure> CONFIGURED_STRUCTURE = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.world.structure.ConfiguredStructure.class), "No registry present for ConfiguredStructure. This is a bug.");
-+    // Paper end
-     /**
-      * Get the object by its key.
-      *
diff --git a/patches/api/Add-missing-effects.patch b/patches/api/Add-missing-effects.patch
index 78e2975368..06e4e4dc60 100644
--- a/patches/api/Add-missing-effects.patch
+++ b/patches/api/Add-missing-effects.patch
@@ -58,84 +58,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * The sound of an ender portal being created in the overworld
 +     */
 +    END_PORTAL_CREATED_IN_OVERWORLD(1038, Type.SOUND),
-+    /**
-+     * The sound of phantom's bites
-+     *
-+     * @deprecated use {@link #PHANTOM_BITE}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    PHANTOM_BITES(1039, Type.SOUND),
-+    /**
-+     * The sound of zombie converting to drowned zombie
-+     *
-+     * @deprecated use {@link #ZOMBIE_CONVERTED_TO_DROWNED}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    ZOMBIE_CONVERTS_TO_DROWNED(1040, Type.SOUND),
-+    /**
-+     * The sound of a husk converting to zombie by drowning
-+     *
-+     * @deprecated use {@link #HUSK_CONVERTED_TO_ZOMBIE}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    HUSK_CONVERTS_TO_ZOMBIE(1041, Type.SOUND),
-+    /**
-+     * The sound of a grindstone being used
-+     *
-+     * @deprecated use {@link #GRINDSTONE_USE}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    GRINDSTONE_USED(1042, Type.SOUND),
-+    /**
-+     * The sound of a book page being turned
-+     *
-+     * @deprecated use {@link #BOOK_PAGE_TURN}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    BOOK_PAGE_TURNED(1043, Type.SOUND),
-+    /**
-+     * Particles displayed when a composter composts
-+     *
-+     * @deprecated use {@link #COMPOSTER_FILL_ATTEMPT}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    COMPOSTER_COMPOSTS(1500, Type.VISUAL),
-+    /**
-+     * Particles displayed when lava converts a block (either water to stone, or
-+     * removing existing blocks such as torches)
-+     *
-+     * @deprecated use {@link #LAVA_INTERACT}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    LAVA_CONVERTS_BLOCK(1501, Type.VISUAL),
-+    /**
-+     * Particles displayd when a redstone torch burns out
-+     *
-+     * @deprecated use {@link #REDSTONE_TORCH_BURNOUT}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    REDSTONE_TORCH_BURNS_OUT(1502, Type.VISUAL),
-+    /**
-+     * Particles displayed when an ender eye is placed
-+     *
-+     * @deprecated use {@link #END_PORTAL_FRAME_FILL}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    ENDER_EYE_PLACED(1503, Type.VISUAL),
-+    /**
-+     * Particles displayed when an ender dragon destroys block
-+     *
-+     * @deprecated use {@link #ENDER_DRAGON_DESTROY_BLOCK}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    ENDER_DRAGON_DESTROYS_BLOCK(2008, Type.VISUAL),
-+    /**
-+     * Particles displayed when a wet sponge vaporizes in nether.
-+     *
-+     * @deprecated use {@link #SPONGE_DRY}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    WET_SPONGE_VAPORIZES_IN_NETHER(2009, Type.VISUAL),
 +
 +    SOUND_STOP_JUKEBOX_SONG(1011, Type.SOUND),
 +
@@ -262,18 +184,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public Class<?> getData() {
 -        return this.data;
 +        return this.data == null ? null : this.data.get(0); // Paper
-     }
- 
++    }
++
 +    // Paper start - support deprecated data types
 +    @org.jetbrains.annotations.ApiStatus.Internal
 +    public boolean isApplicable(Object obj) {
 +        return this.data != null && com.google.common.collect.Iterables.any(this.data, aClass -> aClass.isAssignableFrom(obj.getClass()));
-+    }
+     }
 +    // Paper end - support deprecated data types
-+
+ 
      /**
       * Gets the Effect associated with the given ID.
-      *
 @@ -0,0 +0,0 @@ public enum Effect {
  
      static {
diff --git a/patches/api/Adventure.patch b/patches/api/Adventure.patch
index affed87f9c..95b0116ced 100644
--- a/patches/api/Adventure.patch
+++ b/patches/api/Adventure.patch
@@ -459,19 +459,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        this.result = result;
 +    }
 +
-+    /**
-+     * If this decorating is part of a preview request/response.
-+     *
-+     * @return {@code true} if part of previewing
-+     * @deprecated chat preview was removed in 1.19.3
-+     */
-+    @Deprecated(forRemoval = true, since = "1.19.3")
-+    @ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    @Contract(value = "-> false", pure = true)
-+    public boolean isPreview() {
-+        return false;
-+    }
-+
 +    @Override
 +    public boolean isCancelled() {
 +        return this.cancelled;
diff --git a/patches/api/EntityTransformedEvent.patch b/patches/api/EntityTransformedEvent.patch
deleted file mode 100644
index e2d6c4a4fa..0000000000
--- a/patches/api/EntityTransformedEvent.patch
+++ /dev/null
@@ -1,107 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Anthony MacAllister <anthonymmacallister@gmail.com>
-Date: Thu, 26 Jul 2018 15:28:53 -0400
-Subject: [PATCH] EntityTransformedEvent
-
-
-diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityTransformedEvent.java
-@@ -0,0 +0,0 @@
-+package com.destroystokyo.paper.event.entity;
-+
-+import org.bukkit.entity.Entity;
-+import org.bukkit.event.Cancellable;
-+import org.bukkit.event.HandlerList;
-+import org.bukkit.event.entity.EntityEvent;
-+import org.jetbrains.annotations.ApiStatus;
-+import org.jetbrains.annotations.NotNull;
-+
-+/**
-+ * Fired when an entity transforms into another entity
-+ * <p>
-+ * If the event is cancelled, the entity will not transform
-+ *
-+ * @deprecated Bukkit has added {@link org.bukkit.event.entity.EntityTransformEvent}, you should start using that
-+ */
-+@Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+public class EntityTransformedEvent extends EntityEvent implements Cancellable {
-+
-+    private static final HandlerList HANDLER_LIST = new HandlerList();
-+
-+    private final Entity transformed;
-+    private final TransformedReason reason;
-+
-+    private boolean cancelled;
-+
-+    @ApiStatus.Internal
-+    public EntityTransformedEvent(@NotNull Entity entity, @NotNull Entity transformed, @NotNull TransformedReason reason) {
-+        super(entity);
-+        this.transformed = transformed;
-+        this.reason = reason;
-+    }
-+
-+    /**
-+     * The entity after it has transformed
-+     *
-+     * @return Transformed entity
-+     */
-+    @NotNull
-+    public Entity getTransformed() {
-+        return this.transformed;
-+    }
-+
-+    /**
-+     * @return The reason for the transformation
-+     */
-+    @NotNull
-+    public TransformedReason getReason() {
-+        return this.reason;
-+    }
-+
-+    @Override
-+    public boolean isCancelled(){
-+        return this.cancelled;
-+    }
-+
-+    @Override
-+    public void setCancelled(boolean cancel){
-+        this.cancelled = cancel;
-+    }
-+
-+    @Override
-+    @NotNull
-+    public HandlerList getHandlers(){
-+        return HANDLER_LIST;
-+    }
-+
-+    @NotNull
-+    public static HandlerList getHandlerList(){
-+        return HANDLER_LIST;
-+    }
-+
-+    public enum TransformedReason {
-+        /**
-+         * When a zombie drowns
-+         */
-+        DROWNED,
-+        /**
-+         * When a zombie villager is cured
-+         */
-+        CURED,
-+        /**
-+         * When a villager turns to a zombie villager
-+         */
-+        INFECTED,
-+        /**
-+         * When a mooshroom turns to a cow
-+         */
-+        SHEARED,
-+        /**
-+         * When a pig turns to a zombified piglin
-+         */
-+        LIGHTNING
-+    }
-+}
diff --git a/patches/api/Expose-WorldBorder-isInBounds-Location-check.patch b/patches/api/Expose-WorldBorder-isInBounds-Location-check.patch
deleted file mode 100644
index bc7ab61229..0000000000
--- a/patches/api/Expose-WorldBorder-isInBounds-Location-check.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Zach Brown <1254957+zachbr@users.noreply.github.com>
-Date: Sat, 21 Jan 2017 17:03:10 -0600
-Subject: [PATCH] Expose WorldBorder#isInBounds(Location) check
-
-
-diff --git a/src/main/java/org/bukkit/WorldBorder.java b/src/main/java/org/bukkit/WorldBorder.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/WorldBorder.java
-+++ b/src/main/java/org/bukkit/WorldBorder.java
-@@ -0,0 +0,0 @@ public interface WorldBorder {
-      * @return The absolute maximum center coordinate of the WorldBorder
-      */
-     public double getMaxCenterCoordinate();
-+
-+    // Paper start
-+    /**
-+     * Checks if the location is within the boundaries of this border.
-+     * 
-+     * @param location specific location to check
-+     * @return true if the location is within the bounds of this border, false otherwise.
-+     * @deprecated use {@link #isInside(Location)} for an upstream compatible replacement
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    public default boolean isInBounds(@NotNull Location location) {
-+        return this.isInside(location);
-+    }
-+    // Paper end
- }
diff --git a/patches/api/More-PotionEffectType-API.patch b/patches/api/More-PotionEffectType-API.patch
index af0bd7e71f..53ecfaaf2e 100644
--- a/patches/api/More-PotionEffectType-API.patch
+++ b/patches/api/More-PotionEffectType-API.patch
@@ -9,10 +9,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/Registry.java
 +++ b/src/main/java/org/bukkit/Registry.java
 @@ -0,0 +0,0 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
+      * @see GameEvent
       */
-     @Deprecated(forRemoval = true)
-     Registry<io.papermc.paper.world.structure.ConfiguredStructure> CONFIGURED_STRUCTURE = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.world.structure.ConfiguredStructure.class), "No registry present for ConfiguredStructure. This is a bug.");
+     Registry<GameEvent> GAME_EVENT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.GAME_EVENT); // Paper
 +
++    // Paper start - potion effect type registry
 +    /**
 +     * Potion effect types.
 +     *
@@ -37,9 +38,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            return StreamSupport.stream(this.spliterator(), false);
 +        }
 +    };
-     // Paper end
++    // Paper end - potion effect type registry
      /**
       * Get the object by its key.
+      *
 diff --git a/src/main/java/org/bukkit/potion/PotionEffectType.java b/src/main/java/org/bukkit/potion/PotionEffectType.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/potion/PotionEffectType.java
diff --git a/patches/api/More-World-API.patch b/patches/api/More-World-API.patch
index 228460e8a4..815ad88aa2 100644
--- a/patches/api/More-World-API.patch
+++ b/patches/api/More-World-API.patch
@@ -47,20 +47,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    /**
-+     * Checks if the world:
-+     * <ul>
-+     *     <li>evaporates water</li>
-+     *     <li>dries sponges</li>
-+     *     <li>has lava spread faster and further</li>
-+     * </ul>
-+     *
-+     * @return true if ultrawarm, false if not
-+     * @deprecated use {@link #isUltraWarm()}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    boolean isUltrawarm();
-+
-+    /**
 +     * Gets the coordinate scaling of this world.
 +     *
 +     * @return the coordinate scale
@@ -68,42 +54,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    double getCoordinateScale();
 +
 +    /**
-+     * Checks if the world has skylight access
-+     *
-+     * @return whether there is skylight
-+     * @deprecated use {@link #hasSkyLight()}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    boolean hasSkylight();
-+
-+    /**
-+     * Checks if the world has a bedrock ceiling
-+     *
-+     * @return whether the world has a bedrock ceiling
-+     * @deprecated use {@link #hasCeiling()}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    boolean hasBedrockCeiling();
-+
-+    /**
-+     * Checks if beds work
-+     *
-+     * @return whether beds work
-+     * @deprecated use {@link #isBedWorks()}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    boolean doesBedWork();
-+
-+    /**
-+     * Checks if respawn anchors work
-+     *
-+     * @return whether respawn anchors work
-+     * @deprecated use {@link #isRespawnAnchorWorks()}
-+     */
-+    @Deprecated(forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.21")
-+    boolean doesRespawnAnchorWork();
-+
-+    /**
 +     * Checks if this world has a fixed time
 +     *
 +     * @return whether this world has fixed time
diff --git a/patches/server/Add-Heightmap-API.patch b/patches/server/Add-Heightmap-API.patch
deleted file mode 100644
index 6f3a2b902d..0000000000
--- a/patches/server/Add-Heightmap-API.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Spottedleaf <Spottedleaf@users.noreply.github.com>
-Date: Tue, 1 Jan 2019 02:22:01 -0800
-Subject: [PATCH] Add Heightmap API
-
-
-diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
-+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
-@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
-         return CraftBlock.at(this.world, new BlockPos(x, y, z));
-     }
- 
-+    // Paper start - Implement heightmap api
-+    @Override
-+    public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException {
-+        this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas
-+
-+        switch (heightmap) {
-+            case LIGHT_BLOCKING:
-+                throw new UnsupportedOperationException(); // TODO
-+                //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z);
-+            case ANY:
-+                return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE, x, z);
-+            case SOLID:
-+                return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR, x, z);
-+            case SOLID_OR_LIQUID:
-+                return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING, x, z);
-+            case SOLID_OR_LIQUID_NO_LEAVES:
-+                return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z);
-+            default:
-+                throw new UnsupportedOperationException();
-+        }
-+    }
-+    // Paper end
-+
-     @Override
-     public Location getSpawnLocation() {
-         BlockPos spawn = this.world.getSharedSpawnPos();
diff --git a/patches/server/Add-StructuresLocateEvent.patch b/patches/server/Add-StructuresLocateEvent.patch
index 8ca547c3f5..d2003e50bf 100644
--- a/patches/server/Add-StructuresLocateEvent.patch
+++ b/patches/server/Add-StructuresLocateEvent.patch
@@ -5,76 +5,6 @@ Subject: [PATCH] Add StructuresLocateEvent
 
 Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
 
-diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/io/papermc/paper/registry/PaperRegistries.java
-+++ b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
-@@ -0,0 +0,0 @@ import static io.papermc.paper.registry.entry.RegistryEntry.entry;
- @DefaultQualifier(NonNull.class)
- public final class PaperRegistries {
- 
-+    @Deprecated(forRemoval = true)
-+    @org.jetbrains.annotations.VisibleForTesting
-+    public static final RegistryKey<io.papermc.paper.world.structure.ConfiguredStructure> CONFIGURED_STRUCTURE_REGISTRY_KEY = RegistryKeyImpl.createInternal("worldgen/structure");
-+    @Deprecated(forRemoval = true)
-+    static final RegistryEntry<Structure, io.papermc.paper.world.structure.ConfiguredStructure, ?> CONFIGURED_STRUCTURE_REGISTRY_ENTRY = entry(Registries.STRUCTURE, CONFIGURED_STRUCTURE_REGISTRY_KEY, io.papermc.paper.world.structure.ConfiguredStructure.class, io.papermc.paper.world.structure.PaperConfiguredStructure::minecraftToBukkit).delayed();
-+
-     static final List<RegistryEntry<?, ?, ?>> REGISTRY_ENTRIES;
-     private static final Map<RegistryKey<?>, RegistryEntry<?, ?, ?>> BY_REGISTRY_KEY;
-     private static final Map<ResourceKey<?>, RegistryEntry<?, ?, ?>> BY_RESOURCE_KEY;
-diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
-+++ b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
-@@ -0,0 +0,0 @@ public class PaperRegistryAccess implements RegistryAccess {
-     public <T extends Keyed> @Nullable Registry<T> getRegistry(final Class<T> type) {
-         final RegistryKey<T> registryKey;
-         final @Nullable RegistryEntry<?, T, ?> entry;
--        registryKey = requireNonNull(byType(type), () -> type + " is not a valid registry type");
--        entry = PaperRegistries.getEntry(registryKey);
-+        if (type == io.papermc.paper.world.structure.ConfiguredStructure.class) { // manually handle "duplicate" registries to avoid polluting maps in PaperRegistries
-+            registryKey = (RegistryKey<T>) PaperRegistries.CONFIGURED_STRUCTURE_REGISTRY_KEY;
-+            entry = (RegistryEntry<?, T, ?>) PaperRegistries.CONFIGURED_STRUCTURE_REGISTRY_ENTRY;
-+        } else {
-+            registryKey = requireNonNull(byType(type), () -> type + " is not a valid registry type");
-+            entry = PaperRegistries.getEntry(registryKey);
-+        }
-         final @Nullable RegistryHolder<T> registry = (RegistryHolder<T>) this.registries.get(registryKey);
-         if (registry != null) {
-             // if the registry exists, return right away. Since this is the "legacy" method, we return DelayedRegistry
-diff --git a/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java b/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java
-@@ -0,0 +0,0 @@
-+package io.papermc.paper.world.structure;
-+
-+import java.util.Objects;
-+import net.minecraft.core.Registry;
-+import net.minecraft.core.registries.BuiltInRegistries;
-+import net.minecraft.resources.ResourceLocation;
-+import net.minecraft.world.level.levelgen.structure.Structure;
-+import org.bukkit.NamespacedKey;
-+import org.bukkit.StructureType;
-+import org.bukkit.craftbukkit.CraftRegistry;
-+import org.checkerframework.checker.nullness.qual.NonNull;
-+import org.checkerframework.checker.nullness.qual.Nullable;
-+import org.checkerframework.framework.qual.DefaultQualifier;
-+
-+@DefaultQualifier(NonNull.class)
-+@Deprecated(forRemoval = true)
-+public final class PaperConfiguredStructure {
-+
-+    private PaperConfiguredStructure() {
-+    }
-+
-+    public static @Nullable ConfiguredStructure minecraftToBukkit(NamespacedKey key, Structure nms) {
-+        final ResourceLocation structureTypeLoc = Objects.requireNonNull(BuiltInRegistries.STRUCTURE_TYPE.getKey(nms.type()), "unexpected structure type " + nms.type());
-+        final @Nullable StructureType structureType = StructureType.getStructureTypes().get(structureTypeLoc.getPath());
-+        return structureType == null ? null : new ConfiguredStructure(key, structureType);
-+    }
-+}
 diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -104,129 +34,3 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          ChunkGeneratorStructureState chunkgeneratorstructurestate = world.getChunkSource().getGeneratorState();
          Map<StructurePlacement, Set<Holder<Structure>>> map = new Object2ObjectArrayMap();
          Iterator iterator = structures.iterator();
-diff --git a/src/test/java/io/papermc/paper/world/structure/ConfiguredStructureTest.java b/src/test/java/io/papermc/paper/world/structure/ConfiguredStructureTest.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/test/java/io/papermc/paper/world/structure/ConfiguredStructureTest.java
-@@ -0,0 +0,0 @@
-+package io.papermc.paper.world.structure;
-+
-+import io.papermc.paper.registry.Reference;
-+import net.minecraft.core.Registry;
-+import net.minecraft.core.registries.Registries;
-+import net.minecraft.resources.ResourceKey;
-+import net.minecraft.resources.ResourceLocation;
-+import net.minecraft.server.Bootstrap;
-+import net.minecraft.world.level.levelgen.structure.Structure;
-+import net.minecraft.world.level.levelgen.structure.BuiltinStructures;
-+import org.bukkit.NamespacedKey;
-+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
-+import org.bukkit.support.AbstractTestingBase;
-+import org.junit.jupiter.api.AfterAll;
-+import org.junit.jupiter.api.BeforeAll;
-+import org.junit.jupiter.api.Test;
-+
-+import java.io.PrintStream;
-+import java.lang.reflect.Field;
-+import java.lang.reflect.Modifier;
-+import java.util.LinkedHashMap;
-+import java.util.Map;
-+import java.util.StringJoiner;
-+
-+import static org.junit.jupiter.api.Assertions.assertEquals;
-+import static org.junit.jupiter.api.Assertions.assertNotNull;
-+import static org.junit.jupiter.api.Assertions.assertTrue;
-+
-+@Deprecated(forRemoval = true)
-+public class ConfiguredStructureTest extends AbstractTestingBase {
-+
-+    private static final Map<ResourceLocation, String> BUILT_IN_STRUCTURES = new LinkedHashMap<>();
-+    private static final Map<NamespacedKey, Reference<?>> DEFAULT_CONFIGURED_STRUCTURES = new LinkedHashMap<>();
-+
-+    private static PrintStream out;
-+
-+    @BeforeAll
-+    public static void collectStructures() throws ReflectiveOperationException {
-+        out = System.out;
-+        System.setOut(Bootstrap.STDOUT);
-+        for (Field field : BuiltinStructures.class.getDeclaredFields()) {
-+            if (field.getType().equals(ResourceKey.class) && Modifier.isStatic(field.getModifiers())) {
-+                BUILT_IN_STRUCTURES.put(((ResourceKey<?>) field.get(null)).location(), field.getName());
-+            }
-+        }
-+        for (Field field : ConfiguredStructure.class.getDeclaredFields()) {
-+            if (field.getType().equals(Reference.class) && Modifier.isStatic(field.getModifiers())) {
-+                final Reference<?> ref = (Reference<?>) field.get(null);
-+                DEFAULT_CONFIGURED_STRUCTURES.put(ref.getKey(), ref);
-+            }
-+        }
-+    }
-+
-+    @Test
-+    public void testMinecraftToApi() {
-+        Registry<Structure> structureRegistry = AbstractTestingBase.REGISTRY_CUSTOM.registryOrThrow(Registries.STRUCTURE);
-+        assertEquals(BUILT_IN_STRUCTURES.size(), structureRegistry.size(), "configured structure maps should be the same size");
-+
-+        Map<ResourceLocation, Structure> missing = new LinkedHashMap<>();
-+        for (Structure feature : structureRegistry) {
-+            final ResourceLocation key = structureRegistry.getKey(feature);
-+            assertNotNull(key, "Missing built-in registry key");
-+            if (key.equals(BuiltinStructures.ANCIENT_CITY.location()) || key.equals(BuiltinStructures.TRAIL_RUINS.location()) || key.equals(BuiltinStructures.TRIAL_CHAMBERS.location())) {
-+                continue; // TODO remove when upstream adds "jigsaw" StructureType
-+            }
-+            if (DEFAULT_CONFIGURED_STRUCTURES.get(CraftNamespacedKey.fromMinecraft(key)) == null) {
-+                missing.put(key, feature);
-+            }
-+        }
-+
-+        assertTrue(missing.isEmpty(), printMissing(missing));
-+    }
-+
-+    @Test
-+    public void testApiToMinecraft() {
-+        Registry<Structure> structureRegistry = AbstractTestingBase.REGISTRY_CUSTOM.registryOrThrow(Registries.STRUCTURE);
-+        for (NamespacedKey apiKey : DEFAULT_CONFIGURED_STRUCTURES.keySet()) {
-+            assertTrue(structureRegistry.containsKey(CraftNamespacedKey.toMinecraft(apiKey)), apiKey + " does not have a minecraft counterpart");
-+        }
-+    }
-+
-+    private static String printMissing(Map<ResourceLocation, Structure> missing) {
-+        final StringJoiner joiner = new StringJoiner("\n", "Missing: \n", "");
-+
-+        missing.forEach((key, configuredFeature) -> {
-+            joiner.add("public static final Reference<ConfiguredStructure> " + BUILT_IN_STRUCTURES.get(key) + " = create(\"" + key.getPath() + "\");");
-+        });
-+
-+        return joiner.toString();
-+    }
-+
-+    @AfterAll
-+    public static void after() {
-+        System.setOut(out);
-+    }
-+}
-diff --git a/src/test/java/org/bukkit/registry/PerRegistryTest.java b/src/test/java/org/bukkit/registry/PerRegistryTest.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/test/java/org/bukkit/registry/PerRegistryTest.java
-+++ b/src/test/java/org/bukkit/registry/PerRegistryTest.java
-@@ -0,0 +0,0 @@ public class PerRegistryTest extends AbstractTestingBase {
-                 if (!(object instanceof CraftRegistry<?, ?> registry)) {
-                     continue;
-                 }
-+                if (object == Registry.CONFIGURED_STRUCTURE) continue; // Paper - skip
- 
-                 data.add(Arguments.of(registry));
-             } catch (ReflectiveOperationException e) {
-diff --git a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
-+++ b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
-@@ -0,0 +0,0 @@ public class RegistryArgumentAddedTest extends AbstractTestingBase {
-         loadedRegistries.addAll(io.papermc.paper.registry.PaperRegistryAccess.instance().getLoadedServerBackedRegistries());
-         // Paper end
-         Set<io.papermc.paper.registry.RegistryKey<?>> notFound = new HashSet<>(); // Paper
-+        loadedRegistries.remove(io.papermc.paper.registry.PaperRegistries.CONFIGURED_STRUCTURE_REGISTRY_KEY); // Paper - ignore
- 
-         RegistriesArgumentProvider
-                 .getData()
diff --git a/patches/server/Add-PlayerInitialSpawnEvent.patch b/patches/server/Fix-spawn-location-event-changing-location.patch
similarity index 58%
rename from patches/server/Add-PlayerInitialSpawnEvent.patch
rename to patches/server/Fix-spawn-location-event-changing-location.patch
index 0075528ea2..218f61d3a2 100644
--- a/patches/server/Add-PlayerInitialSpawnEvent.patch
+++ b/patches/server/Fix-spawn-location-event-changing-location.patch
@@ -1,12 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Steve Anton <anxuiz.nx@gmail.com>
 Date: Thu, 3 Mar 2016 00:09:38 -0600
-Subject: [PATCH] Add PlayerInitialSpawnEvent
-
-For modifying a player's initial spawn location as they join the server
-
-This is a duplicate API from spigot, so use our duplicate subclass and
-improve setPosition to use raw
+Subject: [PATCH] Fix spawn location event changing location
 
 == AT ==
 public net.minecraft.world.entity.Entity setRot(FF)V
@@ -17,15 +12,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/server/players/PlayerList.java
 @@ -0,0 +0,0 @@ public abstract class PlayerList {
  
-         // Spigot start - spawn location event
-         Player spawnPlayer = player.getBukkitEntity();
--        org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(spawnPlayer, spawnPlayer.getLocation());
-+        org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(spawnPlayer, spawnPlayer.getLocation()); // Paper use our duplicate event
-         this.cserver.getPluginManager().callEvent(ev);
- 
-         Location loc = ev.getSpawnLocation();
-@@ -0,0 +0,0 @@ public abstract class PlayerList {
- 
          player.spawnIn(worldserver1);
          player.gameMode.setLevel((ServerLevel) player.level());
 -        player.absMoveTo(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
diff --git a/patches/server/Implement-Player-Client-Options-API.patch b/patches/server/Implement-Player-Client-Options-API.patch
index ac57f4497d..c60c075fc2 100644
--- a/patches/server/Implement-Player-Client-Options-API.patch
+++ b/patches/server/Implement-Player-Client-Options-API.patch
@@ -124,7 +124,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          if (this.getMainArm() != clientOptions.mainHand()) {
              PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), this.getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT);
 @@ -0,0 +0,0 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
-             this.server.server.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.language, clientOptions.language())); // Paper
+             this.server.server.getPluginManager().callEvent(event);
          }
          // CraftBukkit end
 +        // Paper start - don't call options events on login
diff --git a/patches/server/More-World-API.patch b/patches/server/More-World-API.patch
index fe380536eb..aabb4b516e 100644
--- a/patches/server/More-World-API.patch
+++ b/patches/server/More-World-API.patch
@@ -14,36 +14,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
 +    // Paper start
 +    @Override
-+    public boolean isUltrawarm() {
-+        return getHandle().dimensionType().ultraWarm();
-+    }
-+
-+    @Override
 +    public double getCoordinateScale() {
 +        return getHandle().dimensionType().coordinateScale();
 +    }
 +
 +    @Override
-+    public boolean hasSkylight() {
-+        return getHandle().dimensionType().hasSkyLight();
-+    }
-+
-+    @Override
-+    public boolean hasBedrockCeiling() {
-+        return getHandle().dimensionType().hasSkyLight();
-+    }
-+
-+    @Override
-+    public boolean doesBedWork() {
-+        return getHandle().dimensionType().bedWorks();
-+    }
-+
-+    @Override
-+    public boolean doesRespawnAnchorWork() {
-+        return getHandle().dimensionType().respawnAnchorWorks();
-+    }
-+
-+    @Override
 +    public boolean isFixedTime() {
 +        return getHandle().dimensionType().hasFixedTime();
 +    }
diff --git a/patches/server/Implement-PlayerLocaleChangeEvent.patch b/patches/server/Use-null-Locale-by-default.patch
similarity index 89%
rename from patches/server/Implement-PlayerLocaleChangeEvent.patch
rename to patches/server/Use-null-Locale-by-default.patch
index 2d670e13bf..7a551ce206 100644
--- a/patches/server/Implement-PlayerLocaleChangeEvent.patch
+++ b/patches/server/Use-null-Locale-by-default.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Isaac Moore <rmsy@me.com>
 Date: Tue, 19 Apr 2016 14:09:31 -0500
-Subject: [PATCH] Implement PlayerLocaleChangeEvent
+Subject: [PATCH] Use null Locale by default
 
 
 diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -34,10 +34,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        if (this.language == null || !this.language.equals(clientOptions.language())) { // Paper
              PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(this.getBukkitEntity(), clientOptions.language());
              this.server.server.getPluginManager().callEvent(event);
-+            this.server.server.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.language, clientOptions.language())); // Paper
          }
-         // CraftBukkit end
-         this.language = clientOptions.language();
 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java