-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 before a structure/feature is located.
-+ * This happens when:
-+ *
-+ * - The /locate command is used.
-+ * - An Eye of Ender is used.
-+ * - An Explorer/Treasure Map is activated.
-+ * - {@link World#locateNearestStructure(Location, StructureType, int, boolean)} is invoked.
-+ *
-+ *
-+ * @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.
-+ *
-+ * Returns {@code null} if it has not been set by {@link StructureLocateEvent#setResult(Location)}.
-+ * Since this event fires before 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.
-+ *
-+ * 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.
-+ *
-+ * 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.
-+ *
-+ * 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.
-+ *
-+ * 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 structures;
-+ private List 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 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 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 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 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 PILLAGER_OUTPOST = create("pillager_outpost");
-+ public static final Reference MINESHAFT = create("mineshaft");
-+ public static final Reference MINESHAFT_MESA = create("mineshaft_mesa");
-+ public static final Reference WOODLAND_MANSION = create("mansion");
-+ public static final Reference JUNGLE_TEMPLE = create("jungle_pyramid");
-+ public static final Reference DESERT_PYRAMID = create("desert_pyramid");
-+ public static final Reference IGLOO = create("igloo");
-+ public static final Reference SHIPWRECK = create("shipwreck");
-+ public static final Reference SHIPWRECK_BEACHED = create("shipwreck_beached");
-+ public static final Reference SWAMP_HUT = create("swamp_hut");
-+ public static final Reference STRONGHOLD = create("stronghold");
-+ public static final Reference OCEAN_MONUMENT = create("monument");
-+ public static final Reference OCEAN_RUIN_COLD = create("ocean_ruin_cold");
-+ public static final Reference OCEAN_RUIN_WARM = create("ocean_ruin_warm");
-+ public static final Reference FORTRESS = create("fortress");
-+ public static final Reference NETHER_FOSSIL = create("nether_fossil");
-+ public static final Reference END_CITY = create("end_city");
-+ public static final Reference BURIED_TREASURE = create("buried_treasure");
-+ public static final Reference BASTION_REMNANT = create("bastion_remnant");
-+ public static final Reference VILLAGE_PLAINS = create("village_plains");
-+ public static final Reference VILLAGE_DESERT = create("village_desert");
-+ public static final Reference VILLAGE_SAVANNA = create("village_savanna");
-+ public static final Reference VILLAGE_SNOWY = create("village_snowy");
-+ public static final Reference VILLAGE_TAIGA = create("village_taiga");
-+ public static final Reference RUINED_PORTAL_STANDARD = create("ruined_portal");
-+ public static final Reference RUINED_PORTAL_DESERT = create("ruined_portal_desert");
-+ public static final Reference RUINED_PORTAL_JUNGLE = create("ruined_portal_jungle");
-+ public static final Reference RUINED_PORTAL_SWAMP = create("ruined_portal_swamp");
-+ public static final Reference RUINED_PORTAL_MOUNTAIN = create("ruined_portal_mountain");
-+ public static final Reference RUINED_PORTAL_OCEAN = create("ruined_portal_ocean");
-+ public static final Reference RUINED_PORTAL_NETHER = create("ruined_portal_nether");
-+ // public static final Reference 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 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 extends Iterable {
- * @see GameEvent
- */
- Registry 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 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
-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
-+ *
-+ * 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 extends Iterable {
+ * @see GameEvent
*/
- @Deprecated(forRemoval = true)
- Registry 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 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:
-+ *
-+ * - evaporates water
-+ * - dries sponges
-+ * - has lava spread faster and further
-+ *
-+ *
-+ * @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
-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
-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 CONFIGURED_STRUCTURE_REGISTRY_KEY = RegistryKeyImpl.createInternal("worldgen/structure");
-+ @Deprecated(forRemoval = true)
-+ static final RegistryEntry 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> REGISTRY_ENTRIES;
- private static final Map, RegistryEntry, ?, ?>> BY_REGISTRY_KEY;
- private static final Map, 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 @Nullable Registry getRegistry(final Class type) {
- final RegistryKey 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) 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 registry = (RegistryHolder) 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>> 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 BUILT_IN_STRUCTURES = new LinkedHashMap<>();
-+ private static final Map> 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 structureRegistry = AbstractTestingBase.REGISTRY_CUSTOM.registryOrThrow(Registries.STRUCTURE);
-+ assertEquals(BUILT_IN_STRUCTURES.size(), structureRegistry.size(), "configured structure maps should be the same size");
-+
-+ Map 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 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 missing) {
-+ final StringJoiner joiner = new StringJoiner("\n", "Missing: \n", "");
-+
-+ missing.forEach((key, configuredFeature) -> {
-+ joiner.add("public static final Reference " + 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> 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
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
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