Replace ConfiguredStructure api with Structure (#8642)

This commit is contained in:
Jake Potrebic 2023-02-28 08:36:01 -08:00
parent 81f79b407d
commit f8ba85ffbf
12 changed files with 139 additions and 342 deletions

View File

@ -90,23 +90,3 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ 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
}

View File

@ -176,17 +176,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@
+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.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.jetbrains.annotations.UnmodifiableView;
+
+/**
+ * Called <b>before</b> a set of configured structures is located.
@ -206,15 +210,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ private final Location origin;
+ private Result result;
+ private List<ConfiguredStructure> configuredStructures;
+ private List<Structure> structures;
+ private List<ConfiguredStructure> legacy$structures;
+ 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) {
+ public StructuresLocateEvent(@NotNull World world, @NotNull Location origin, @NotNull List<Structure> structures, int radius, boolean findUnexplored) {
+ super(world);
+ this.origin = origin;
+ this.configuredStructures = configuredStructures;
+ this.setStructures(structures);
+ this.radius = radius;
+ this.findUnexplored = findUnexplored;
+ }
@ -229,23 +234,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ /**
+ * Gets the {@link Location} and {@link ConfiguredStructure} set as the result, if it was defined.
+ * 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. null if it has not.
+ * @see World#locateNearestStructure(Location, org.bukkit.StructureType, int, boolean)
+ * @see World#locateNearestStructure(Location, org.bukkit.generator.structure.StructureType, int, boolean)
+ */
+ public @Nullable Result getResult() {
+ return this.result;
+ }
+
+ /**
+ * Sets the result {@link Location} and {@link ConfiguredStructure}. This causes the search to be
+ * 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 ConfiguredStructure} of the search.
+ * @param result the {@link Location} and {@link Structure} of the search.
+ */
+ public void setResult(@Nullable Result result) {
+ this.result = result;
@ -255,18 +260,41 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * Gets a mutable list of ConfiguredStructures that are valid targets for the search.
+ *
+ * @return a mutable list of ConfiguredStructures
+ * @deprecated use {@link #getStructures()}
+ */
+ @Deprecated(forRemoval = true)
+ public @NotNull List<ConfiguredStructure> getConfiguredStructures() {
+ return this.configuredStructures;
+ 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.configuredStructures = new ArrayList<>(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);
+ }
+
+ /**
@ -274,7 +302,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * <p>
+ * This radius may not always be obeyed during the structure search!
+ *
+ * @return the search radius.
+ * @return the search radius (in chunks)
+ */
+ public int getRadius() {
+ return this.radius;
@ -285,7 +313,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * <p>
+ * This radius may not always be obeyed during the structure search!
+ *
+ * @param radius the search radius.
+ * @param radius the search radius (in chunks)
+ */
+ public void setRadius(int radius) {
+ this.radius = radius;
@ -335,7 +363,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ /**
+ * Result for {@link StructuresLocateEvent}.
+ */
+ public record Result(@NotNull Location position, @NotNull ConfiguredStructure configuredStructure) {
+ 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
@ -347,19 +391,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+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 java.util.Objects;
+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)
+public final class ConfiguredStructure implements Keyed {
+
+ public static final Reference<ConfiguredStructure> PILLAGER_OUTPOST = create("pillager_outpost");
@ -441,6 +489,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private static @NotNull Reference<ConfiguredStructure> create(@NotNull String name) {
+ return Reference.create(Registry.CONFIGURED_STRUCTURE, NamespacedKey.minecraft(name));
+ }
+
+ @ApiStatus.Internal
+ public @NotNull Structure toModern() {
+ return Objects.requireNonNull(Registry.STRUCTURE.get(this.key));
+ }
+
+ @ApiStatus.Internal
+ public static @Nullable ConfiguredStructure fromModern(@NotNull Structure structure) {
+ return Registry.CONFIGURED_STRUCTURE.get(structure.getKey());
+ }
+}
diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -454,7 +512,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ /**
+ * Configured structures.
+ * @see io.papermc.paper.world.structure.ConfiguredStructure
+ * @deprecated use {@link #STRUCTURE}
+ */
+ @Deprecated(forRemoval = true)
+ Registry<io.papermc.paper.world.structure.ConfiguredStructure> CONFIGURED_STRUCTURE = Bukkit.getRegistry(io.papermc.paper.world.structure.ConfiguredStructure.class);
+ // Paper end

View File

@ -82,9 +82,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 {
* @throws IllegalArgumentException if there isn't a registry for that type
* Use this when sending custom packets, so that there are no collisions on the client or server.
*/
<T extends Keyed> @org.jetbrains.annotations.NotNull Registry<T> registryFor(Class<T> classOfT);
public int nextEntityId();
+
+ /**
+ * Just don't use it.

View File

@ -9,9 +9,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/Registry.java
+++ b/src/main/java/org/bukkit/Registry.java
@@ -0,0 +0,0 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* @see io.papermc.paper.world.structure.ConfiguredStructure
*/
@Deprecated(forRemoval = true)
Registry<io.papermc.paper.world.structure.ConfiguredStructure> CONFIGURED_STRUCTURE = Bukkit.getRegistry(io.papermc.paper.world.structure.ConfiguredStructure.class);
+
+ /**
+ * Potion effect types.
+ *

View File

@ -1,242 +0,0 @@
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.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
+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 ConcurrentHashMap<>();
+ private final Map<NamespacedKey, ResourceKey<MINECRAFT>> resourceKeyCache = new ConcurrentHashMap<>();
+
+ 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 @Nullable API convertToApi(NamespacedKey key, MINECRAFT nms);
+
+ public API convertToApiOrThrow(ResourceLocation resourceLocation, MINECRAFT nms) {
+ return Objects.requireNonNull(this.convertToApi(resourceLocation, nms), resourceLocation + " has a null api representation");
+ }
+
+ public @Nullable API convertToApi(ResourceLocation resourceLocation, MINECRAFT nms) {
+ return this.convertToApi(CraftNamespacedKey.fromMinecraft(resourceLocation), nms);
+ }
+
+ public API convertToApiOrThrow(Holder<MINECRAFT> nmsHolder) {
+ return Objects.requireNonNull(this.convertToApi(nmsHolder), nmsHolder + " has a null api representation");
+ }
+
+ public @Nullable 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 void convertToApi(Iterable<Holder<MINECRAFT>> holders, Consumer<API> apiConsumer, boolean throwOnNull) {
+ for (Holder<MINECRAFT> holder : holders) {
+ final @Nullable API api = this.convertToApi(holder);
+ if (api == null && throwOnNull) {
+ throw new NullPointerException(holder + " has a null api representation");
+ } else if (api != null) {
+ apiConsumer.accept(api);
+ }
+ }
+ }
+
+ 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(this.resourceKeyCache.computeIfAbsent(apiValue.getKey(), key -> ResourceKey.create(this.registryKey.resourceKey(), CraftNamespacedKey.toMinecraft(key))));
+ }
+
+ @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.worldData.setDataConfiguration(worlddataconfiguration);
this.resources.managers.updateRegistryTags(this.registryAccess());
+ io.papermc.paper.registry.PaperRegistry.clearCaches(); // Paper
new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper
// Paper start
if (Thread.currentThread() != this.serverThread) {
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 {
layers = WorldLoader.loadAndReplaceLayer(resourceManager, layers, RegistryLayer.WORLDGEN, RegistryDataLoader.WORLDGEN_REGISTRIES);
REGISTRY_CUSTOM = layers.compositeAccess().freeze();
io.papermc.paper.testing.DummyServer.setup(); // Paper
+ // 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_CUSTOM));
+ } 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_CUSTOM, FeatureFlags.REGISTRY.allFlags(), Commands.CommandSelection.DEDICATED, 0, MoreExecutors.directExecutor(), MoreExecutors.directExecutor()).join();
// Bind tags

View File

@ -5,25 +5,6 @@ Subject: [PATCH] Add StructuresLocateEvent
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/io/papermc/paper/registry/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.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
+import net.minecraft.world.level.levelgen.structure.Structure;
import org.bukkit.Keyed;
public record RegistryKey<API extends Keyed, MINECRAFT>(Class<API> apiClass, ResourceKey<? extends Registry<MINECRAFT>> resourceKey) {
+
+ public static final RegistryKey<ConfiguredStructure, Structure> CONFIGURED_STRUCTURE_REGISTRY = new RegistryKey<>(ConfiguredStructure.class, Registries.STRUCTURE);
+
}
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
@ -32,42 +13,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@
+package io.papermc.paper.world.structure;
+
+import io.papermc.paper.registry.PaperRegistry;
+import io.papermc.paper.registry.RegistryKey;
+import java.util.Objects;
+import net.minecraft.core.Registry;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.core.registries.Registries;
+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;
+
+import java.util.Objects;
+import java.util.function.Supplier;
+
+@DefaultQualifier(NonNull.class)
+@Deprecated(forRemoval = true)
+public final class PaperConfiguredStructure {
+
+ private PaperConfiguredStructure() {
+ }
+
+ public static void init() {
+ new ConfiguredStructureRegistry().register();
+ @Deprecated(forRemoval = true)
+ public static final class LegacyRegistry extends CraftRegistry<ConfiguredStructure, Structure> {
+
+ public LegacyRegistry(final Registry<Structure> minecraftRegistry) {
+ super(minecraftRegistry, LegacyRegistry::minecraftToBukkit);
+ }
+
+ static final class ConfiguredStructureRegistry extends PaperRegistry<ConfiguredStructure, Structure> {
+
+ private static final Supplier<Registry<Structure>> STRUCTURE_FEATURE_REGISTRY = registryFor(Registries.STRUCTURE);
+
+ public ConfiguredStructureRegistry() {
+ super(RegistryKey.CONFIGURED_STRUCTURE_REGISTRY);
+ }
+
+ @Override
+ public @Nullable ConfiguredStructure convertToApi(NamespacedKey key, Structure nms) {
+ private 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);
@ -82,41 +54,43 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Nullable
public Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel world, HolderSet<Structure> structures, BlockPos center, int radius, boolean skipReferencedStructures) {
+ // Paper start - StructureLocateEvent
+ // Paper start - StructuresLocateEvent
+ final org.bukkit.World bukkitWorld = world.getWorld();
+ final org.bukkit.Location origin = io.papermc.paper.util.MCUtil.toLocation(world, 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<>();
+ paperRegistry.convertToApi(structures, configuredStructures::add, false); // gracefully handle missing api, use tests to check (or exclude)
+ if (!configuredStructures.isEmpty()) {
+ final io.papermc.paper.event.world.StructuresLocateEvent event = new io.papermc.paper.event.world.StructuresLocateEvent(bukkitWorld, origin, configuredStructures, radius, skipReferencedStructures);
+ final List<org.bukkit.generator.structure.Structure> apiStructures = structures.stream().map(Holder::value).map(nms -> org.bukkit.craftbukkit.generator.strucutre.CraftStructure.minecraftToBukkit(nms, world.registryAccess())).toList();
+ if (!apiStructures.isEmpty()) {
+ final io.papermc.paper.event.world.StructuresLocateEvent event = new io.papermc.paper.event.world.StructuresLocateEvent(bukkitWorld, origin, apiStructures, radius, skipReferencedStructures);
+ if (!event.callEvent()) {
+ return null;
+ }
+ if (event.getResult() != null) {
+ return Pair.of(io.papermc.paper.util.MCUtil.toBlockPosition(event.getResult().position()), paperRegistry.getMinecraftHolder(event.getResult().configuredStructure()));
+ return Pair.of(io.papermc.paper.util.MCUtil.toBlockPos(event.getResult().pos()), world.registryAccess().registryOrThrow(Registries.STRUCTURE).wrapAsHolder(org.bukkit.craftbukkit.generator.strucutre.CraftStructure.bukkitToMinecraft(event.getResult().structure())));
+ }
+ center = io.papermc.paper.util.MCUtil.toBlockPosition(event.getOrigin());
+ radius = event.getRadius();
+ skipReferencedStructures = event.shouldFindUnexplored();
+ structures = HolderSet.direct(paperRegistry::getMinecraftHolder, event.getConfiguredStructures());
+ structures = HolderSet.direct(api -> world.registryAccess().registryOrThrow(Registries.STRUCTURE).wrapAsHolder(org.bukkit.craftbukkit.generator.strucutre.CraftStructure.bukkitToMinecraft(api)), event.getStructures());
+ }
+ // Paper end
ChunkGeneratorStructureState chunkgeneratorstructurestate = world.getChunkSource().getGeneratorState();
Map<StructurePlacement, Set<Holder<Structure>>> map = new Object2ObjectArrayMap();
Iterator iterator = structures.iterator();
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
this.structureManager = new CraftStructureManager(console.getStructureManager());
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
@@ -0,0 +0,0 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return new CraftRegistry<>(BuiltInRegistries.STRUCTURE_TYPE, CraftStructureType::new);
}
// TODO registry modification API
+ // Paper start - remove this after a while along with all ConfiguredStructure stuff
+ if (bukkitClass == io.papermc.paper.world.structure.ConfiguredStructure.class) {
+ return new io.papermc.paper.world.structure.PaperConfiguredStructure.LegacyRegistry(registryHolder.registryOrThrow(Registries.STRUCTURE));
+ }
+ // Paper end
Bukkit.setServer(this);
+ io.papermc.paper.world.structure.PaperConfiguredStructure.init(); // Paper
// Register all the Enchantments and PotionTypes now so we can stop new registration immediately after
Enchantments.SHARPNESS.getClass();
return null;
}
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
@ -151,6 +125,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@Deprecated(forRemoval = true)
+public class ConfiguredStructureTest extends AbstractTestingBase {
+
+ private static final Map<ResourceLocation, String> BUILT_IN_STRUCTURES = new LinkedHashMap<>();

View File

@ -574,8 +574,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import com.destroystokyo.paper.profile.CraftPlayerProfile;
+import com.destroystokyo.paper.profile.PlayerProfile;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.papermc.paper.math.Position;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
@@ -0,0 +0,0 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;

View File

@ -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.worldData.setDataConfiguration(worlddataconfiguration);
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
// Paper start

View File

@ -71,8 +71,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 <T extends org.bukkit.Keyed> Registry<T> registryFor(Class<T> classOfT) {
return io.papermc.paper.registry.PaperRegistry.getRegistry(classOfT);
public int nextEntityId() {
return net.minecraft.world.entity.Entity.nextEntityId();
}
+
+ @Override

View File

@ -3470,6 +3470,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+package io.papermc.paper.util;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.papermc.paper.math.Position;
+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet;
+import java.lang.ref.Cleaner;
+import net.minecraft.core.BlockPos;
@ -3933,6 +3934,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
+ }
+
+ public static BlockPos toBlockPos(Position pos) {
+ return new BlockPos(pos.blockX(), pos.blockY(), pos.blockZ());
+ }
+
+ public static boolean isEdgeOfChunk(BlockPos pos) {
+ final int modX = pos.getX() & 15;
+ final int modZ = pos.getZ() & 15;

View File

@ -11847,10 +11847,10 @@ diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/io/papermc/paper/util/MCUtil.java
+++ b/src/main/java/io/papermc/paper/util/MCUtil.java
@@ -0,0 +0,0 @@
package io.papermc.paper.util;
@@ -0,0 +0,0 @@ package io.papermc.paper.util;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.papermc.paper.math.Position;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.internal.Streams;

View File

@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 27 Feb 2023 18:28:39 -0800
Subject: [PATCH] TODO Registry Modification API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
@@ -0,0 +0,0 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
if (bukkitClass == StructureType.class) {
return new CraftRegistry<>(BuiltInRegistries.STRUCTURE_TYPE, CraftStructureType::new);
}
+ // TODO registry modification API
return null;
}