diff options
Diffstat (limited to 'patches/api/0243-Add-StructuresLocateEvent.patch')
-rw-r--r-- | patches/api/0243-Add-StructuresLocateEvent.patch | 534 |
1 files changed, 534 insertions, 0 deletions
diff --git a/patches/api/0243-Add-StructuresLocateEvent.patch b/patches/api/0243-Add-StructuresLocateEvent.patch new file mode 100644 index 0000000000..10ef586cce --- /dev/null +++ b/patches/api/0243-Add-StructuresLocateEvent.patch @@ -0,0 +1,534 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: dfsek <[email protected]> +Date: Tue, 15 Sep 2020 21:59:16 -0700 +Subject: [PATCH] Add StructuresLocateEvent + +Co-authored-by: Jake Potrebic <[email protected]> + +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..1ac3369455972aeb1ade5dc023d1f818cd3535fa +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/world/StructureLocateEvent.java +@@ -0,0 +1,163 @@ ++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..582af444b058708638683e7d6f9b79685c04c061 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/world/StructuresLocateEvent.java +@@ -0,0 +1,213 @@ ++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; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.world.WorldEvent; ++import org.bukkit.generator.structure.Structure; ++import org.bukkit.generator.structure.StructureType; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.jetbrains.annotations.UnmodifiableView; ++ ++/** ++ * Called <b>before</b> a set of configured structures 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>A dolphin swims to a treasure location.</li> ++ * <li>A trade is done with a villager for a map.</li> ++ * <li>{@link World#locateNearestStructure(Location, StructureType, int, boolean)} is invoked.</li> ++ * <li>{@link World#locateNearestStructure(Location, Structure, int, boolean)} is invoked.</li> ++ * </ul> ++ */ ++public class StructuresLocateEvent extends WorldEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Location origin; ++ private Result result; ++ private List<Structure> structures; ++ private List<ConfiguredStructure> legacy$structures; ++ private int radius; ++ private boolean findUnexplored; ++ ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ 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.radius = radius; ++ this.findUnexplored = findUnexplored; ++ } ++ ++ /** ++ * Gets the {@link Location} from which the search is to be conducted. ++ * ++ * @return {@link Location} where search begins ++ */ ++ public @NotNull Location getOrigin() { ++ return this.origin.clone(); ++ } ++ ++ /** ++ * Gets the {@link Location} and {@link Structure} set as the result, if it was defined. ++ * <p> ++ * Returns {@code null} if it has not been set by {@link StructuresLocateEvent#setResult(Result)}. ++ * Since this event fires <i>before</i> the search is done, the actual result is unknown at this point. ++ * ++ * @return The result location and structure, if it has been set. {@code null} if it has not. ++ * @see World#locateNearestStructure(Location, StructureType, int, boolean) ++ */ ++ public @Nullable Result getResult() { ++ return this.result; ++ } ++ ++ /** ++ * Sets the result {@link Location} and {@link Structure}. This causes the search to be ++ * skipped, and the result object passed here to be used as the result. ++ * ++ * @param result the {@link Location} and {@link Structure} of the search. ++ */ ++ public void setResult(@Nullable Result result) { ++ this.result = result; ++ } ++ ++ /** ++ * 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 ++ */ ++ public @NotNull @UnmodifiableView List<Structure> getStructures() { ++ return Collections.unmodifiableList(this.structures); ++ } ++ ++ /** ++ * Sets the list of Structures that are valid targets for the search. ++ * ++ * @param structures a list of Structures targets ++ */ ++ public void setStructures(final @NotNull List<Structure> structures) { ++ this.structures = structures; ++ this.legacy$structures = new TransformingRandomAccessList<>(this.structures, ConfiguredStructure::fromModern, ConfiguredStructure::toModern); ++ } ++ ++ /** ++ * 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 (in chunks) ++ */ ++ 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 (in chunks) ++ */ ++ 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; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static @NotNull HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ /** ++ * Result for {@link StructuresLocateEvent}. ++ */ ++ 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..1e7b53f9bc13dcd5a0a4a40004591e4f850496a0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/world/structure/ConfiguredStructure.java +@@ -0,0 +1,113 @@ ++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) [email protected](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 91117cad12eee0bdaac8e0398a0f7f288ba27a40..43f410326d6d68242113e2fefe31af256889ed9c 100644 +--- a/src/main/java/org/bukkit/Registry.java ++++ b/src/main/java/org/bukkit/Registry.java +@@ -292,6 +292,15 @@ 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. + * |