2022-03-04 09:09:43 +01:00
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>
2024-05-04 20:22:35 +02:00
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
2024-05-11 23:48:37 +02:00
index 4f4595356f2d17c261a84e13d37351f06433177b..3aa5aec0b17cbdff922009b940d49bb06945c2c6 100644
2024-05-04 20:22:35 +02:00
--- a/src/main/java/io/papermc/paper/registry/PaperRegistries.java
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
2024-05-11 23:48:37 +02:00
@@ -45,6 +45,12 @@ import static io.papermc.paper.registry.entry.RegistryEntry.entry;
2024-05-04 20:22:35 +02:00
@DefaultQualifier(NonNull.class)
public final class PaperRegistries {
+ @Deprecated(forRemoval = true)
+ @org.jetbrains.annotations.VisibleForTesting
+ public static final RegistryKey<io.papermc.paper.world.structure.ConfiguredStructure> CONFIGURED_STRUCTURE_REGISTRY_KEY = RegistryKeyImpl.createInternal("worldgen/structure");
+ @Deprecated(forRemoval = true)
+ static final RegistryEntry<Structure, io.papermc.paper.world.structure.ConfiguredStructure, ?> CONFIGURED_STRUCTURE_REGISTRY_ENTRY = entry(Registries.STRUCTURE, CONFIGURED_STRUCTURE_REGISTRY_KEY, io.papermc.paper.world.structure.ConfiguredStructure.class, io.papermc.paper.world.structure.PaperConfiguredStructure::minecraftToBukkit).delayed();
+
static final List<RegistryEntry<?, ?, ?>> REGISTRY_ENTRIES;
private static final Map<RegistryKey<?>, RegistryEntry<?, ?, ?>> BY_REGISTRY_KEY;
private static final Map<ResourceKey<?>, RegistryEntry<?, ?, ?>> BY_RESOURCE_KEY;
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
index 9f2bcfe0d9e479466a1e46e503071d1151310e6a..7aa1a29e93b787e1167169bc7d6e9563daf6241e 100644
--- a/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
@@ -45,8 +45,13 @@ public class PaperRegistryAccess implements RegistryAccess {
public <T extends Keyed> @Nullable Registry<T> getRegistry(final Class<T> type) {
final RegistryKey<T> registryKey;
final @Nullable RegistryEntry<?, T, ?> entry;
- registryKey = requireNonNull(byType(type), () -> type + " is not a valid registry type");
- entry = PaperRegistries.getEntry(registryKey);
+ if (type == io.papermc.paper.world.structure.ConfiguredStructure.class) { // manually handle "duplicate" registries to avoid polluting maps in PaperRegistries
+ registryKey = (RegistryKey<T>) PaperRegistries.CONFIGURED_STRUCTURE_REGISTRY_KEY;
+ entry = (RegistryEntry<?, T, ?>) PaperRegistries.CONFIGURED_STRUCTURE_REGISTRY_ENTRY;
+ } else {
+ registryKey = requireNonNull(byType(type), () -> type + " is not a valid registry type");
+ entry = PaperRegistries.getEntry(registryKey);
+ }
final @Nullable RegistryHolder<T> registry = (RegistryHolder<T>) this.registries.get(registryKey);
if (registry != null) {
// if the registry exists, return right away. Since this is the "legacy" method, we return DelayedRegistry
2022-03-04 09:09:43 +01:00
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
2024-05-04 20:22:35 +02:00
index 0000000000000000000000000000000000000000..013d614a1cf1ab2b5a6ec190c2b4ba7753268731
2022-03-04 09:09:43 +01:00
--- /dev/null
+++ b/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java
2024-05-04 20:22:35 +02:00
@@ -0,0 +1,27 @@
2022-03-04 09:09:43 +01:00
+package io.papermc.paper.world.structure;
+
2023-02-28 17:36:01 +01:00
+import java.util.Objects;
2022-03-04 09:09:43 +01:00
+import net.minecraft.core.Registry;
2022-12-08 05:24:59 +01:00
+import net.minecraft.core.registries.BuiltInRegistries;
2022-03-04 09:09:43 +01:00
+import net.minecraft.resources.ResourceLocation;
2022-06-08 09:30:41 +02:00
+import net.minecraft.world.level.levelgen.structure.Structure;
2022-03-04 09:09:43 +01:00
+import org.bukkit.NamespacedKey;
+import org.bukkit.StructureType;
2023-02-28 17:36:01 +01:00
+import org.bukkit.craftbukkit.CraftRegistry;
2022-03-04 09:09:43 +01:00
+import org.checkerframework.checker.nullness.qual.NonNull;
2022-06-08 21:00:19 +02:00
+import org.checkerframework.checker.nullness.qual.Nullable;
2022-03-04 09:09:43 +01:00
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+@DefaultQualifier(NonNull.class)
2023-02-28 17:36:01 +01:00
+@Deprecated(forRemoval = true)
2022-03-04 09:09:43 +01:00
+public final class PaperConfiguredStructure {
+
+ private PaperConfiguredStructure() {
+ }
+
2024-05-04 20:22:35 +02:00
+ public static @Nullable ConfiguredStructure minecraftToBukkit(NamespacedKey key, Structure nms) {
+ final ResourceLocation structureTypeLoc = Objects.requireNonNull(BuiltInRegistries.STRUCTURE_TYPE.getKey(nms.type()), "unexpected structure type " + nms.type());
+ final @Nullable StructureType structureType = StructureType.getStructureTypes().get(structureTypeLoc.getPath());
+ return structureType == null ? null : new ConfiguredStructure(key, structureType);
2022-03-04 09:09:43 +01:00
+ }
+}
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
2024-04-24 15:46:45 +02:00
index 7cdb59cd2f2ffe1195d21519ef97dae0e430285b..a8768f1925d5824ca985be1b53694ee233273758 100644
2022-03-04 09:09:43 +01:00
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
2024-04-24 15:46:45 +02:00
@@ -127,6 +127,24 @@ public abstract class ChunkGenerator {
2022-03-04 09:09:43 +01:00
@Nullable
2022-06-08 09:30:41 +02:00
public Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel world, HolderSet<Structure> structures, BlockPos center, int radius, boolean skipReferencedStructures) {
2023-02-28 17:36:01 +01:00
+ // Paper start - StructuresLocateEvent
2022-06-08 09:30:41 +02:00
+ final org.bukkit.World bukkitWorld = world.getWorld();
2022-10-24 21:43:46 +02:00
+ final org.bukkit.Location origin = io.papermc.paper.util.MCUtil.toLocation(world, center);
2023-12-25 23:51:56 +01:00
+ final List<org.bukkit.generator.structure.Structure> apiStructures = structures.stream().map(Holder::value).map(nms -> org.bukkit.craftbukkit.generator.structure.CraftStructure.minecraftToBukkit(nms)).toList();
2023-02-28 17:36:01 +01:00
+ if (!apiStructures.isEmpty()) {
+ final io.papermc.paper.event.world.StructuresLocateEvent event = new io.papermc.paper.event.world.StructuresLocateEvent(bukkitWorld, origin, apiStructures, radius, skipReferencedStructures);
2022-06-08 22:42:54 +02:00
+ if (!event.callEvent()) {
+ return null;
+ }
+ if (event.getResult() != null) {
2023-06-08 21:35:20 +02:00
+ return Pair.of(io.papermc.paper.util.MCUtil.toBlockPos(event.getResult().pos()), world.registryAccess().registryOrThrow(Registries.STRUCTURE).wrapAsHolder(org.bukkit.craftbukkit.generator.structure.CraftStructure.bukkitToMinecraft(event.getResult().structure())));
2022-06-08 22:42:54 +02:00
+ }
2022-10-24 21:43:46 +02:00
+ center = io.papermc.paper.util.MCUtil.toBlockPosition(event.getOrigin());
2022-06-08 22:42:54 +02:00
+ radius = event.getRadius();
+ skipReferencedStructures = event.shouldFindUnexplored();
2023-06-08 21:35:20 +02:00
+ structures = HolderSet.direct(api -> world.registryAccess().registryOrThrow(Registries.STRUCTURE).wrapAsHolder(org.bukkit.craftbukkit.generator.structure.CraftStructure.bukkitToMinecraft(api)), event.getStructures());
2022-03-04 09:09:43 +01:00
+ }
+ // Paper end
2022-12-07 21:16:54 +01:00
ChunkGeneratorStructureState chunkgeneratorstructurestate = world.getChunkSource().getGeneratorState();
2022-06-08 09:30:41 +02:00
Map<StructurePlacement, Set<Holder<Structure>>> map = new Object2ObjectArrayMap();
Iterator iterator = structures.iterator();
2022-03-04 09:09:43 +01:00
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
2023-12-08 21:07:56 +01:00
index 0000000000000000000000000000000000000000..9178fe0d01b998ca1442bf2511f8fc00db9388ba
2022-03-04 09:09:43 +01:00
--- /dev/null
+++ b/src/test/java/io/papermc/paper/world/structure/ConfiguredStructureTest.java
2023-02-28 17:36:01 +01:00
@@ -0,0 +1,96 @@
2022-03-04 09:09:43 +01:00
+package io.papermc.paper.world.structure;
+
+import io.papermc.paper.registry.Reference;
2022-12-08 19:23:12 +01:00
+import net.minecraft.core.Registry;
+import net.minecraft.core.registries.Registries;
2022-03-04 09:09:43 +01:00
+import net.minecraft.resources.ResourceKey;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.server.Bootstrap;
2022-06-08 09:30:41 +02:00
+import net.minecraft.world.level.levelgen.structure.Structure;
2022-03-04 09:09:43 +01:00
+import net.minecraft.world.level.levelgen.structure.BuiltinStructures;
+import org.bukkit.NamespacedKey;
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
+import org.bukkit.support.AbstractTestingBase;
2023-09-24 09:16:58 +02:00
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
2022-03-04 09:09:43 +01:00
+
+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;
+
2023-09-24 09:16:58 +02:00
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
2022-03-04 09:09:43 +01:00
+
2023-02-28 17:36:01 +01:00
+@Deprecated(forRemoval = true)
2022-03-04 09:09:43 +01:00
+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;
+
2023-09-24 09:16:58 +02:00
+ @BeforeAll
2022-03-04 09:09:43 +01:00
+ 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() {
2022-12-08 19:23:12 +01:00
+ Registry<Structure> structureRegistry = AbstractTestingBase.REGISTRY_CUSTOM.registryOrThrow(Registries.STRUCTURE);
2023-09-24 09:16:58 +02:00
+ assertEquals(BUILT_IN_STRUCTURES.size(), structureRegistry.size(), "configured structure maps should be the same size");
2022-03-04 09:09:43 +01:00
+
2022-06-08 09:30:41 +02:00
+ Map<ResourceLocation, Structure> missing = new LinkedHashMap<>();
2022-12-08 19:23:12 +01:00
+ for (Structure feature : structureRegistry) {
+ final ResourceLocation key = structureRegistry.getKey(feature);
2023-09-24 09:16:58 +02:00
+ assertNotNull(key, "Missing built-in registry key");
2023-12-08 21:07:56 +01:00
+ if (key.equals(BuiltinStructures.ANCIENT_CITY.location()) || key.equals(BuiltinStructures.TRAIL_RUINS.location()) || key.equals(BuiltinStructures.TRIAL_CHAMBERS.location())) {
2022-06-08 21:00:19 +02:00
+ continue; // TODO remove when upstream adds "jigsaw" StructureType
+ }
2022-03-04 09:09:43 +01:00
+ if (DEFAULT_CONFIGURED_STRUCTURES.get(CraftNamespacedKey.fromMinecraft(key)) == null) {
+ missing.put(key, feature);
+ }
+ }
+
2023-09-24 09:16:58 +02:00
+ assertTrue(missing.isEmpty(), printMissing(missing));
2022-03-04 09:09:43 +01:00
+ }
+
+ @Test
+ public void testApiToMinecraft() {
2022-12-08 19:23:12 +01:00
+ Registry<Structure> structureRegistry = AbstractTestingBase.REGISTRY_CUSTOM.registryOrThrow(Registries.STRUCTURE);
2022-03-04 09:09:43 +01:00
+ for (NamespacedKey apiKey : DEFAULT_CONFIGURED_STRUCTURES.keySet()) {
2023-09-24 09:16:58 +02:00
+ assertTrue(structureRegistry.containsKey(CraftNamespacedKey.toMinecraft(apiKey)), apiKey + " does not have a minecraft counterpart");
2022-03-04 09:09:43 +01:00
+ }
+ }
+
2022-06-08 09:30:41 +02:00
+ private static String printMissing(Map<ResourceLocation, Structure> missing) {
2022-03-04 09:09:43 +01:00
+ 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();
+ }
+
2023-09-24 09:16:58 +02:00
+ @AfterAll
2022-03-04 09:09:43 +01:00
+ public static void after() {
+ System.setOut(out);
+ }
+}
2024-01-26 20:17:06 +01:00
diff --git a/src/test/java/org/bukkit/registry/PerRegistryTest.java b/src/test/java/org/bukkit/registry/PerRegistryTest.java
2024-05-04 20:22:35 +02:00
index 4e4ea083063daf22f1bb785ef212958ea889c43b..523b4b208e05c6b70014440200e3196cc84f36cc 100644
2024-01-26 20:17:06 +01:00
--- a/src/test/java/org/bukkit/registry/PerRegistryTest.java
+++ b/src/test/java/org/bukkit/registry/PerRegistryTest.java
@@ -36,6 +36,7 @@ public class PerRegistryTest extends AbstractTestingBase {
2023-09-25 01:05:05 +02:00
if (!(object instanceof CraftRegistry<?, ?> registry)) {
continue;
}
2024-05-04 20:22:35 +02:00
+ if (object == Registry.CONFIGURED_STRUCTURE) continue; // Paper - skip
2023-09-25 01:05:05 +02:00
data.add(Arguments.of(registry));
} catch (ReflectiveOperationException e) {
2024-01-26 20:17:06 +01:00
diff --git a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
2024-05-04 20:22:35 +02:00
index 0dd775ad1bd0bf9ba7ea05255d543a9df8b5fcfd..c1e51d104c52dd3f3e48d651b0ff1f00ae9bf96d 100644
2024-01-26 20:17:06 +01:00
--- a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
+++ b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
2024-05-04 20:22:35 +02:00
@@ -26,6 +26,7 @@ public class RegistryArgumentAddedTest extends AbstractTestingBase {
loadedRegistries.addAll(io.papermc.paper.registry.PaperRegistryAccess.instance().getLoadedServerBackedRegistries());
// Paper end
Set<io.papermc.paper.registry.RegistryKey<?>> notFound = new HashSet<>(); // Paper
+ loadedRegistries.remove(io.papermc.paper.registry.PaperRegistries.CONFIGURED_STRUCTURE_REGISTRY_KEY); // Paper - ignore
2024-01-26 20:17:06 +01:00
RegistriesArgumentProvider
.getData()