mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-28 23:38:25 +01:00
Add StructuresLocateEvent as replacement for StructureLocateEvent (#7524)
This commit is contained in:
parent
fd5b9dd153
commit
1641e0c524
11 changed files with 1027 additions and 210 deletions
112
patches/api/Add-PaperRegistry.patch
Normal file
112
patches/api/Add-PaperRegistry.patch
Normal file
|
@ -0,0 +1,112 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 2 Mar 2022 13:36:21 -0800
|
||||
Subject: [PATCH] Add PaperRegistry
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/registry/Reference.java b/src/main/java/io/papermc/paper/registry/Reference.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/registry/Reference.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.registry;
|
||||
+
|
||||
+import org.bukkit.Keyed;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.Registry;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a reference to a server-backed registry value that may
|
||||
+ * change.
|
||||
+ *
|
||||
+ * @param <T> type of the value
|
||||
+ */
|
||||
+public interface Reference<T extends Keyed> extends Keyed {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the value from the registry with the key.
|
||||
+ *
|
||||
+ * @return the value
|
||||
+ * @throws java.util.NoSuchElementException if there is no value with this key
|
||||
+ */
|
||||
+ @NotNull T value();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the value from the registry with the key.
|
||||
+ *
|
||||
+ * @return the value or null if it doesn't exist
|
||||
+ */
|
||||
+ @Nullable T valueOrNull();
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a reference to a registered value.
|
||||
+ *
|
||||
+ * @param registry the registry the value is located in
|
||||
+ * @param key the key to the value
|
||||
+ * @param <T> the type of the value
|
||||
+ * @return a reference
|
||||
+ */
|
||||
+ static <T extends Keyed> @NotNull Reference<T> create(@NotNull Registry<T> registry, @NotNull NamespacedKey key) {
|
||||
+ return new ReferenceImpl<>(registry, key);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/registry/ReferenceImpl.java b/src/main/java/io/papermc/paper/registry/ReferenceImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/registry/ReferenceImpl.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.registry;
|
||||
+
|
||||
+import org.bukkit.Keyed;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.Registry;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+import java.util.NoSuchElementException;
|
||||
+
|
||||
+record ReferenceImpl<T extends Keyed>(@NotNull Registry<T> registry, @NotNull NamespacedKey key) implements Reference<T> {
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull T value() {
|
||||
+ final T value = this.registry.get(this.key);
|
||||
+ if (value == null) {
|
||||
+ throw new NoSuchElementException("No such value with key " + this.key);
|
||||
+ }
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @Nullable T valueOrNull() {
|
||||
+ return this.registry.get(this.key);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull NamespacedKey getKey() {
|
||||
+ return this.key;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/UnsafeValues.java
|
||||
+++ b/src/main/java/org/bukkit/UnsafeValues.java
|
||||
@@ -0,0 +0,0 @@ public interface UnsafeValues {
|
||||
* Use this when sending custom packets, so that there are no collisions on the client or server.
|
||||
*/
|
||||
public int nextEntityId();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the server-backed registry for a type.
|
||||
+ *
|
||||
+ * @param classOfT type
|
||||
+ * @param <T> type
|
||||
+ * @return the server-backed registry
|
||||
+ * @throws IllegalArgumentException if there isn't a registry for that type
|
||||
+ */
|
||||
+ <T extends Keyed> @org.jetbrains.annotations.NotNull Registry<T> registryFor(Class<T> classOfT);
|
||||
// Paper end
|
||||
}
|
|
@ -1,167 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: dfsek <dfsek@protonmail.com>
|
||||
Date: Tue, 15 Sep 2020 21:59:16 -0700
|
||||
Subject: [PATCH] Add StructureLocateEvent
|
||||
|
||||
|
||||
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.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>
|
||||
+ */
|
||||
+public class StructureLocateEvent extends WorldEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private final Location origin;
|
||||
+ private Location result = null;
|
||||
+ private StructureType type;
|
||||
+ private int radius;
|
||||
+ private boolean findUnexplored;
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * 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. null if it has not.
|
||||
+ * @see World#locateNearestStructure(Location, StructureType, int, boolean)
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Location getResult() {
|
||||
+ return 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 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 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 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 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 cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancelled = cancel;
|
||||
+ }
|
||||
+}
|
461
patches/api/Add-StructuresLocateEvent.patch
Normal file
461
patches/api/Add-StructuresLocateEvent.patch
Normal file
|
@ -0,0 +1,461 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: dfsek <dfsek@protonmail.com>
|
||||
Date: Tue, 15 Sep 2020 21:59:16 -0700
|
||||
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.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)
|
||||
+public class StructureLocateEvent extends WorldEvent implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+ private final Location origin;
|
||||
+ private Location result = null;
|
||||
+ private StructureType type;
|
||||
+ private int radius;
|
||||
+ private boolean findUnexplored;
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * 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. null if it has not.
|
||||
+ * @see World#locateNearestStructure(Location, StructureType, int, boolean)
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Location getResult() {
|
||||
+ return 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 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 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 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 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 cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancelled = cancel;
|
||||
+ }
|
||||
+}
|
||||
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
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/world/StructuresLocateEvent.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.event.world;
|
||||
+
|
||||
+import io.papermc.paper.world.structure.ConfiguredStructure;
|
||||
+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.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+
|
||||
+/**
|
||||
+ * 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, org.bukkit.StructureType, 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<ConfiguredStructure> configuredStructures;
|
||||
+ private int radius;
|
||||
+ private boolean findUnexplored;
|
||||
+ private boolean cancelled;
|
||||
+
|
||||
+ public StructuresLocateEvent(@NotNull World world, @NotNull Location origin, @NotNull List<ConfiguredStructure> configuredStructures, int radius, boolean findUnexplored) {
|
||||
+ super(world);
|
||||
+ this.origin = origin;
|
||||
+ this.configuredStructures = configuredStructures;
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the {@link Location} and {@link ConfiguredStructure} 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. null if it has not.
|
||||
+ * @see World#locateNearestStructure(Location, org.bukkit.StructureType, int, boolean)
|
||||
+ */
|
||||
+ public @Nullable Result getResult() {
|
||||
+ return this.result;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the result {@link Location} and {@link ConfiguredStructure}. 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 ConfiguredStructure} 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
|
||||
+ */
|
||||
+ public @NotNull List<ConfiguredStructure> getConfiguredStructures() {
|
||||
+ return this.configuredStructures;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the list of ConfiguredStructures that are valid targets for the search.
|
||||
+ *
|
||||
+ * @param configuredStructures a list of ConfiguredStructure targets
|
||||
+ */
|
||||
+ public void setConfiguredStructures(@NotNull List<ConfiguredStructure> configuredStructures) {
|
||||
+ this.configuredStructures = new ArrayList<>(configuredStructures);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * 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;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull HandlerList getHandlers() {
|
||||
+ return HANDLER_LIST;
|
||||
+ }
|
||||
+
|
||||
+ public static @NotNull HandlerList getHandlerList() {
|
||||
+ return HANDLER_LIST;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Result for {@link StructuresLocateEvent}.
|
||||
+ */
|
||||
+ public record Result(@NotNull Location position, @NotNull ConfiguredStructure configuredStructure) {
|
||||
+ }
|
||||
+}
|
||||
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 org.bukkit.Keyed;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.Registry;
|
||||
+import org.bukkit.StructureType;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import java.util.Objects;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a configured structure each with a
|
||||
+ * {@link StructureType}. Multiple ConfiguredStructures can have
|
||||
+ * the same {@link StructureType}.
|
||||
+ */
|
||||
+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");
|
||||
+
|
||||
+ 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));
|
||||
+ }
|
||||
+}
|
||||
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> {
|
||||
return GameEvent.getByKey(key);
|
||||
}
|
||||
};
|
||||
+ // Paper start
|
||||
+ /**
|
||||
+ * Configured structures.
|
||||
+ * @see io.papermc.paper.world.structure.ConfiguredStructure
|
||||
+ */
|
||||
+ Registry<io.papermc.paper.world.structure.ConfiguredStructure> CONFIGURED_STRUCTURE = Bukkit.getUnsafe().registryFor(io.papermc.paper.world.structure.ConfiguredStructure.class);
|
||||
+ // Paper end
|
||||
|
||||
/**
|
||||
* Get the object by its key.
|
|
@ -65,9 +65,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/org/bukkit/UnsafeValues.java
|
||||
+++ b/src/main/java/org/bukkit/UnsafeValues.java
|
||||
@@ -0,0 +0,0 @@ public interface UnsafeValues {
|
||||
* Use this when sending custom packets, so that there are no collisions on the client or server.
|
||||
* @throws IllegalArgumentException if there isn't a registry for that type
|
||||
*/
|
||||
public int nextEntityId();
|
||||
<T extends Keyed> @org.jetbrains.annotations.NotNull Registry<T> registryFor(Class<T> classOfT);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the item rarity of a material. The material <b>MUST</b> be an item.
|
||||
|
|
|
@ -9,10 +9,9 @@ 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> {
|
||||
return GameEvent.getByKey(key);
|
||||
}
|
||||
};
|
||||
+ // Paper start
|
||||
* @see io.papermc.paper.world.structure.ConfiguredStructure
|
||||
*/
|
||||
Registry<io.papermc.paper.world.structure.ConfiguredStructure> CONFIGURED_STRUCTURE = Bukkit.getUnsafe().registryFor(io.papermc.paper.world.structure.ConfiguredStructure.class);
|
||||
+ /**
|
||||
+ * Potion effect types.
|
||||
+ *
|
||||
|
@ -32,10 +31,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ return Arrays.stream(org.bukkit.potion.PotionEffectType.values()).iterator();
|
||||
+ }
|
||||
+ };
|
||||
+ // Paper end
|
||||
// Paper end
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
220
patches/server/Add-PaperRegistry.patch
Normal file
220
patches/server/Add-PaperRegistry.patch
Normal file
|
@ -0,0 +1,220 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 2 Mar 2022 13:33:08 -0800
|
||||
Subject: [PATCH] Add PaperRegistry
|
||||
|
||||
PaperRegistry is a server-backed impl of bukkit's Registry interface
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistry.java b/src/main/java/io/papermc/paper/registry/PaperRegistry.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistry.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.registry;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import com.google.common.base.Suppliers;
|
||||
+import net.minecraft.core.Holder;
|
||||
+import net.minecraft.core.Registry;
|
||||
+import net.minecraft.core.RegistryAccess;
|
||||
+import net.minecraft.resources.ResourceKey;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import org.bukkit.Keyed;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+import java.util.Collections;
|
||||
+import java.util.HashMap;
|
||||
+import java.util.Iterator;
|
||||
+import java.util.Map;
|
||||
+import java.util.Objects;
|
||||
+import java.util.Optional;
|
||||
+import java.util.function.Supplier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public abstract class PaperRegistry<API extends Keyed, MINECRAFT> implements org.bukkit.Registry<API> {
|
||||
+
|
||||
+ @SuppressWarnings("FieldMayBeFinal") // non-final for testing
|
||||
+ private static Supplier<RegistryAccess> REGISTRY_ACCESS = Suppliers.memoize(() -> MinecraftServer.getServer().registryAccess());
|
||||
+ private static final Map<RegistryKey<?, ?>, PaperRegistry<?, ?>> INTERNAL_REGISTRIES = new HashMap<>();
|
||||
+ public static final Map<RegistryKey<?, ?>, PaperRegistry<?, ?>> REGISTRIES = Collections.unmodifiableMap(INTERNAL_REGISTRIES);
|
||||
+ private static final Map<Class<?>, PaperRegistry<?, ?>> REGISTRY_BY_API_CLASS = new HashMap<>();
|
||||
+ private static final Map<ResourceKey<? extends Registry<?>>, PaperRegistry<?, ?>> REGISTRY_BY_RES_KEY = new HashMap<>();
|
||||
+
|
||||
+ private boolean registered;
|
||||
+ private final RegistryKey<API, MINECRAFT> registryKey;
|
||||
+ private final Supplier<Registry<MINECRAFT>> registry;
|
||||
+ private final Map<NamespacedKey, API> cache = new HashMap<>();
|
||||
+
|
||||
+ public PaperRegistry(RegistryKey<API, MINECRAFT> registryKey) {
|
||||
+ this.registryKey = registryKey;
|
||||
+ this.registry = Suppliers.memoize(() -> REGISTRY_ACCESS.get().registryOrThrow(this.registryKey.resourceKey()));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @Nullable API get(NamespacedKey key) {
|
||||
+ return this.cache.computeIfAbsent(key, k -> {
|
||||
+ final @Nullable MINECRAFT nms = this.registry.get().get(CraftNamespacedKey.toMinecraft(k));
|
||||
+ if (nms != null) {
|
||||
+ return this.convertToApi(k, nms);
|
||||
+ }
|
||||
+ return null;
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ public abstract API convertToApi(NamespacedKey key, MINECRAFT nms);
|
||||
+
|
||||
+ public API convertToApi(ResourceLocation resourceLocation, MINECRAFT nms) {
|
||||
+ return this.convertToApi(CraftNamespacedKey.fromMinecraft(resourceLocation), nms);
|
||||
+ }
|
||||
+
|
||||
+ public API convertToApi(Holder<MINECRAFT> nmsHolder) {
|
||||
+ final Optional<ResourceKey<MINECRAFT>> key = nmsHolder.unwrapKey();
|
||||
+ if (nmsHolder.isBound() && key.isPresent()) {
|
||||
+ return this.convertToApi(key.get().location(), nmsHolder.value());
|
||||
+ } else if (!nmsHolder.isBound() && key.isPresent()) {
|
||||
+ return this.convertToApi(key.get().location(), this.registry.get().getOrThrow(key.get()));
|
||||
+ } else if (nmsHolder.isBound() && key.isEmpty()) {
|
||||
+ final @Nullable ResourceLocation loc = this.registry.get().getKey(nmsHolder.value());
|
||||
+ if (loc != null) {
|
||||
+ return this.convertToApi(loc, nmsHolder.value());
|
||||
+ }
|
||||
+ }
|
||||
+ throw new IllegalStateException("Cannot convert " + nmsHolder + " to an API type in: " + this.registryKey);
|
||||
+ }
|
||||
+
|
||||
+ public MINECRAFT getMinecraftValue(API apiValue) {
|
||||
+ return this.registry.get().getOptional(CraftNamespacedKey.toMinecraft(apiValue.getKey())).orElseThrow();
|
||||
+ }
|
||||
+
|
||||
+ public Holder<MINECRAFT> getMinecraftHolder(API apiValue) {
|
||||
+ return this.registry.get().getHolderOrThrow(ResourceKey.create(this.registryKey.resourceKey(), CraftNamespacedKey.toMinecraft(apiValue.getKey())));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Iterator<API> iterator() {
|
||||
+ return this.registry.get().keySet().stream().map(key -> this.get(CraftNamespacedKey.fromMinecraft(key))).iterator();
|
||||
+ }
|
||||
+
|
||||
+ public void clearCache() {
|
||||
+ this.cache.clear();
|
||||
+ }
|
||||
+
|
||||
+ public void register() {
|
||||
+ if (this.registered) {
|
||||
+ throw new IllegalStateException("Already registered: " + this.registryKey.apiClass());
|
||||
+ }
|
||||
+ INTERNAL_REGISTRIES.put(this.registryKey, this);
|
||||
+ REGISTRY_BY_API_CLASS.put(this.registryKey.apiClass(), this);
|
||||
+ REGISTRY_BY_RES_KEY.put(this.registryKey.resourceKey(), this);
|
||||
+ this.registered = true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(@Nullable Object o) {
|
||||
+ if (this == o) return true;
|
||||
+ if (o == null || !PaperRegistry.class.isAssignableFrom(o.getClass())) return false;
|
||||
+ PaperRegistry<?, ?> that = (PaperRegistry<?, ?>) o;
|
||||
+ return this.registryKey.equals(that.registryKey);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return Objects.hash(this.registryKey);
|
||||
+ }
|
||||
+
|
||||
+ protected static <T> Supplier<Registry<T>> registryFor(ResourceKey<? extends Registry<T>> registryKey) {
|
||||
+ return Suppliers.memoize(() -> REGISTRY_ACCESS.get().registryOrThrow(registryKey));
|
||||
+ }
|
||||
+
|
||||
+ public static void clearCaches() {
|
||||
+ for (PaperRegistry<?, ?> registry : INTERNAL_REGISTRIES.values()) {
|
||||
+ registry.clearCache();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("unchecked")
|
||||
+ public static <T extends Keyed> PaperRegistry<T, ?> getRegistry(Class<T> classOfT) {
|
||||
+ Preconditions.checkArgument(REGISTRY_BY_API_CLASS.containsKey(classOfT), "No registry for that type");
|
||||
+ return (PaperRegistry<T, ?>) REGISTRY_BY_API_CLASS.get(classOfT);
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("unchecked")
|
||||
+ public static <T> PaperRegistry<?, T> getRegistry(ResourceKey<? extends Registry<T>> resourceKey) {
|
||||
+ Preconditions.checkArgument(REGISTRY_BY_RES_KEY.containsKey(resourceKey));
|
||||
+ return (PaperRegistry<?, T>) REGISTRY_BY_RES_KEY.get(resourceKey);
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("unchecked")
|
||||
+ public static <A extends Keyed, M> PaperRegistry<A, M> getRegistry(RegistryKey<A, M> registryKey) {
|
||||
+ Preconditions.checkArgument(INTERNAL_REGISTRIES.containsKey(registryKey));
|
||||
+ return (PaperRegistry<A, M>) INTERNAL_REGISTRIES.get(registryKey);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/registry/RegistryKey.java b/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.registry;
|
||||
+
|
||||
+import net.minecraft.core.Registry;
|
||||
+import net.minecraft.resources.ResourceKey;
|
||||
+import org.bukkit.Keyed;
|
||||
+
|
||||
+public record RegistryKey<API extends Keyed, MINECRAFT>(Class<API> apiClass, ResourceKey<? extends Registry<MINECRAFT>> resourceKey) {
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.packRepository.setSelected(dataPacks);
|
||||
this.worldData.setDataPackConfig(MinecraftServer.getSelectedPacks(this.packRepository));
|
||||
this.resources.managers.updateRegistryTags(this.registryAccess());
|
||||
+ io.papermc.paper.PaperRegistry.clearCaches(); // Paper
|
||||
new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper
|
||||
if (Thread.currentThread() != this.serverThread) return; // Paper
|
||||
//this.getPlayerList().saveAll(); // Paper - we don't need to do this
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
public int nextEntityId() {
|
||||
return net.minecraft.world.entity.Entity.nextEntityId();
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public <T extends org.bukkit.Keyed> Registry<T> registryFor(Class<T> classOfT) {
|
||||
+ return io.papermc.paper.registry.PaperRegistry.getRegistry(classOfT);
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
/**
|
||||
diff --git a/src/test/java/org/bukkit/support/AbstractTestingBase.java b/src/test/java/org/bukkit/support/AbstractTestingBase.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/test/java/org/bukkit/support/AbstractTestingBase.java
|
||||
+++ b/src/test/java/org/bukkit/support/AbstractTestingBase.java
|
||||
@@ -0,0 +0,0 @@ public abstract class AbstractTestingBase {
|
||||
MultiPackResourceManager resourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, Collections.singletonList(new VanillaPackResources(ServerPacksSource.BUILT_IN_METADATA, "minecraft")));
|
||||
// add tags and loot tables for unit tests
|
||||
RegistryAccess.Frozen registry = RegistryAccess.builtinCopy().freeze();
|
||||
+ // Paper start
|
||||
+ try {
|
||||
+ java.lang.reflect.Field field = io.papermc.paper.registry.PaperRegistry.class.getDeclaredField("REGISTRY_ACCESS");
|
||||
+ field.trySetAccessible();
|
||||
+ field.set(null, com.google.common.base.Suppliers.ofInstance(registry));
|
||||
+ } catch (ReflectiveOperationException ex) {
|
||||
+ throw new IllegalStateException("Could not reflectively set RegistryAccess in PaperRegistry", ex);
|
||||
+ }
|
||||
+ // Paper end
|
||||
// Register vanilla pack
|
||||
DATA_PACK = ReloadableServerResources.loadResources(resourceManager, registry, Commands.CommandSelection.DEDICATED, 0, MoreExecutors.directExecutor(), MoreExecutors.directExecutor()).join();
|
||||
// Bind tags
|
|
@ -1,31 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: dfsek <dfsek@protonmail.com>
|
||||
Date: Wed, 16 Sep 2020 01:12:29 -0700
|
||||
Subject: [PATCH] Add StructureLocateEvent
|
||||
|
||||
|
||||
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
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
@@ -0,0 +0,0 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
|
||||
|
||||
@Nullable
|
||||
public Pair<BlockPos, Holder<ConfiguredStructureFeature<?, ?>>> findNearestMapFeature(ServerLevel worldserver, HolderSet<ConfiguredStructureFeature<?, ?>> holderset, BlockPos center, int radius, boolean skipExistingChunks) {
|
||||
+ // Paper start
|
||||
+ /*org.bukkit.World world1 = worldserver.getWorld();
|
||||
+ org.bukkit.Location originLocation = new org.bukkit.Location(world1, center.getX(), center.getY(), center.getZ());
|
||||
+ io.papermc.paper.event.world.StructureLocateEvent event = new io.papermc.paper.event.world.StructureLocateEvent(world1, originLocation, org.bukkit.StructureType.getStructureTypes().get(structureFeature.getFeatureName()), radius, skipExistingChunks);
|
||||
+ if(!event.callEvent()) return null;
|
||||
+ // If event call set a final location, skip structure finding and just return set result.
|
||||
+ if(event.getResult() != null) return new BlockPos(event.getResult().getBlockX(), event.getResult().getBlockY(), event.getResult().getBlockZ());
|
||||
+ // Get origin location (re)defined by event call.
|
||||
+ center = new BlockPos(event.getOrigin().getBlockX(), event.getOrigin().getBlockY(), event.getOrigin().getBlockZ());
|
||||
+ // Get radius and whether to find unexplored structures (re)defined by event call.
|
||||
+ radius = event.getRadius();
|
||||
+ skipExistingChunks = event.shouldFindUnexplored();
|
||||
+ structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(event.getType().getName());*/
|
||||
+ // Paper end
|
||||
Set<Holder<Biome>> set = (Set) holderset.stream().flatMap((holder) -> {
|
||||
return ((ConfiguredStructureFeature) holder.value()).biomes().stream();
|
||||
}).collect(Collectors.toSet());
|
224
patches/server/Add-StructuresLocateEvent.patch
Normal file
224
patches/server/Add-StructuresLocateEvent.patch
Normal file
|
@ -0,0 +1,224 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: dfsek <dfsek@protonmail.com>
|
||||
Date: Wed, 16 Sep 2020 01:12:29 -0700
|
||||
Subject: [PATCH] Add StructuresLocateEvent
|
||||
|
||||
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/registry/RegistryKey.java b/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
||||
+++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
||||
@@ -0,0 +0,0 @@
|
||||
package io.papermc.paper.registry;
|
||||
|
||||
+import io.papermc.paper.world.structure.ConfiguredStructure;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
+import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||
import org.bukkit.Keyed;
|
||||
|
||||
public record RegistryKey<API extends Keyed, MINECRAFT>(Class<API> apiClass, ResourceKey<? extends Registry<MINECRAFT>> resourceKey) {
|
||||
+
|
||||
+ public static final RegistryKey<ConfiguredStructure, ConfiguredStructureFeature<?, ?>> CONFIGURED_STRUCTURE_REGISTRY = new RegistryKey<>(ConfiguredStructure.class, Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY);
|
||||
+
|
||||
}
|
||||
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 io.papermc.paper.registry.PaperRegistry;
|
||||
+import io.papermc.paper.registry.RegistryKey;
|
||||
+import net.minecraft.core.Registry;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||
+import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||
+import org.bukkit.NamespacedKey;
|
||||
+import org.bukkit.StructureType;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+import java.util.Objects;
|
||||
+import java.util.function.Supplier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class PaperConfiguredStructure {
|
||||
+
|
||||
+ private PaperConfiguredStructure() {
|
||||
+ }
|
||||
+
|
||||
+ public static void init() {
|
||||
+ new ConfiguredStructureRegistry().register();
|
||||
+ }
|
||||
+
|
||||
+ static final class ConfiguredStructureRegistry extends PaperRegistry<ConfiguredStructure, ConfiguredStructureFeature<?, ?>> {
|
||||
+
|
||||
+ private static final Supplier<Registry<StructureFeature<?>>> STRUCTURE_FEATURE_REGISTRY = registryFor(Registry.STRUCTURE_FEATURE_REGISTRY);
|
||||
+
|
||||
+ public ConfiguredStructureRegistry() {
|
||||
+ super(RegistryKey.CONFIGURED_STRUCTURE_REGISTRY);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ConfiguredStructure convertToApi(NamespacedKey key, ConfiguredStructureFeature<?, ?> nms) {
|
||||
+ final ResourceLocation structureFeatureLoc = Objects.requireNonNull(STRUCTURE_FEATURE_REGISTRY.get().getKey(nms.feature));
|
||||
+ final StructureType structureType = Objects.requireNonNull(StructureType.getStructureTypes().get(structureFeatureLoc.getPath()), structureFeatureLoc + " could not be converted to an API type");
|
||||
+ return new ConfiguredStructure(key, structureType);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.packRepository.setSelected(dataPacks);
|
||||
this.worldData.setDataPackConfig(MinecraftServer.getSelectedPacks(this.packRepository));
|
||||
this.resources.managers.updateRegistryTags(this.registryAccess());
|
||||
- io.papermc.paper.PaperRegistry.clearCaches(); // Paper
|
||||
+ io.papermc.paper.registry.PaperRegistry.clearCaches(); // Paper
|
||||
new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper
|
||||
if (Thread.currentThread() != this.serverThread) return; // Paper
|
||||
//this.getPlayerList().saveAll(); // Paper - we don't need to do this
|
||||
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
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
@@ -0,0 +0,0 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
|
||||
|
||||
@Nullable
|
||||
public Pair<BlockPos, Holder<ConfiguredStructureFeature<?, ?>>> findNearestMapFeature(ServerLevel worldserver, HolderSet<ConfiguredStructureFeature<?, ?>> holderset, BlockPos center, int radius, boolean skipExistingChunks) {
|
||||
+ // Paper start - StructureLocateEvent
|
||||
+ final org.bukkit.World world = worldserver.getWorld();
|
||||
+ final org.bukkit.Location origin = net.minecraft.server.MCUtil.toLocation(worldserver, center);
|
||||
+ final var paperRegistry = io.papermc.paper.registry.PaperRegistry.getRegistry(io.papermc.paper.registry.RegistryKey.CONFIGURED_STRUCTURE_REGISTRY);
|
||||
+ final List<io.papermc.paper.world.structure.ConfiguredStructure> configuredStructures = new ArrayList<>();
|
||||
+ for (Holder<net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature<?, ?>> holder : holderset) {
|
||||
+ configuredStructures.add(paperRegistry.convertToApi(holder));
|
||||
+ }
|
||||
+ final io.papermc.paper.event.world.StructuresLocateEvent event = new io.papermc.paper.event.world.StructuresLocateEvent(world, origin, configuredStructures, radius, skipExistingChunks);
|
||||
+ if (!event.callEvent()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ if (event.getResult() != null) {
|
||||
+ return Pair.of(net.minecraft.server.MCUtil.toBlockPosition(event.getResult().position()), paperRegistry.getMinecraftHolder(event.getResult().configuredStructure()));
|
||||
+ }
|
||||
+ center = net.minecraft.server.MCUtil.toBlockPosition(event.getOrigin());
|
||||
+ radius = event.getRadius();
|
||||
+ skipExistingChunks = event.shouldFindUnexplored();
|
||||
+ holderset = HolderSet.direct(paperRegistry::getMinecraftHolder, event.getConfiguredStructures());
|
||||
+ // Paper end
|
||||
Set<Holder<Biome>> set = (Set) holderset.stream().flatMap((holder) -> {
|
||||
return ((ConfiguredStructureFeature) holder.value()).biomes().stream();
|
||||
}).collect(Collectors.toSet());
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/ConfiguredStructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/ConfiguredStructureFeature.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/ConfiguredStructureFeature.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/ConfiguredStructureFeature.java
|
||||
@@ -0,0 +0,0 @@ public class ConfiguredStructureFeature<FC extends FeatureConfiguration, F exten
|
||||
public final HolderSet<Biome> biomes;
|
||||
public final Map<MobCategory, StructureSpawnOverride> spawnOverrides;
|
||||
public final boolean adaptNoise;
|
||||
+ static { io.papermc.paper.world.structure.PaperConfiguredStructure.init(); } // Paper
|
||||
|
||||
public ConfiguredStructureFeature(F feature, FC config, HolderSet<Biome> biomes, boolean bl, Map<MobCategory, StructureSpawnOverride> map) {
|
||||
this.feature = feature;
|
||||
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.data.BuiltinRegistries;
|
||||
+import net.minecraft.resources.ResourceKey;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.server.Bootstrap;
|
||||
+import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||
+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.AfterClass;
|
||||
+import org.junit.BeforeClass;
|
||||
+import org.junit.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.Assert.assertEquals;
|
||||
+import static org.junit.Assert.assertNotNull;
|
||||
+import static org.junit.Assert.assertTrue;
|
||||
+
|
||||
+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;
|
||||
+
|
||||
+ @BeforeClass
|
||||
+ 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() {
|
||||
+ assertEquals("configured structure maps should be the same size", BUILT_IN_STRUCTURES.size(), BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE.size());
|
||||
+
|
||||
+ Map<ResourceLocation, ConfiguredStructureFeature<?, ?>> missing = new LinkedHashMap<>();
|
||||
+ for (ConfiguredStructureFeature<?, ?> feature : BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE) {
|
||||
+ final ResourceLocation key = BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE.getKey(feature);
|
||||
+ assertNotNull("Missing built-in registry key", key);
|
||||
+ if (DEFAULT_CONFIGURED_STRUCTURES.get(CraftNamespacedKey.fromMinecraft(key)) == null) {
|
||||
+ missing.put(key, feature);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ assertTrue(printMissing(missing), missing.isEmpty());
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testApiToMinecraft() {
|
||||
+ for (NamespacedKey apiKey : DEFAULT_CONFIGURED_STRUCTURES.keySet()) {
|
||||
+ assertTrue(apiKey + " does not have a minecraft counterpart", BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE.containsKey(CraftNamespacedKey.toMinecraft(apiKey)));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static String printMissing(Map<ResourceLocation, ConfiguredStructureFeature<?, ?>> 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();
|
||||
+ }
|
||||
+
|
||||
+ @AfterClass
|
||||
+ public static void after() {
|
||||
+ System.setOut(out);
|
||||
+ }
|
||||
+}
|
|
@ -28,9 +28,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.packRepository.setSelected(dataPacks);
|
||||
this.worldData.setDataPackConfig(MinecraftServer.getSelectedPacks(this.packRepository));
|
||||
this.resources.managers.updateRegistryTags(this.registryAccess());
|
||||
io.papermc.paper.registry.PaperRegistry.clearCaches(); // Paper
|
||||
+ net.minecraft.world.item.alchemy.PotionBrewing.reload(); // Paper
|
||||
new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper
|
||||
if (Thread.currentThread() != this.serverThread) return; // Paper
|
||||
|
|
|
@ -11,8 +11,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.worldData.setDataPackConfig(MinecraftServer.getSelectedPacks(this.packRepository));
|
||||
this.resources.managers.updateRegistryTags(this.registryAccess());
|
||||
io.papermc.paper.registry.PaperRegistry.clearCaches(); // Paper
|
||||
net.minecraft.world.item.alchemy.PotionBrewing.reload(); // Paper
|
||||
+ // Paper start - clear cache cause datapacks can add more configured structures
|
||||
+ for (ServerLevel level : this.levels.values()) {
|
||||
|
|
|
@ -9,8 +9,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
public int nextEntityId() {
|
||||
return net.minecraft.world.entity.Entity.nextEntityId();
|
||||
public <T extends org.bukkit.Keyed> Registry<T> registryFor(Class<T> classOfT) {
|
||||
return io.papermc.paper.registry.PaperRegistry.getRegistry(classOfT);
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
|
|
Loading…
Reference in a new issue