dcc290167f
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: dea9ce0a SPIGOT-7198: Add Sittable interface to Camel CraftBukkit Changes: eecb4c0dc SPIGOT-7196: Exception loading alternate worlds 0ff61e8fa SPIGOT-7198: Add Sittable interface to Camel 676441aac PR-1121: Handle additional missing SpawnEggs in MetaSpawnEgg e85280e02 Handle missing SpawnEggs in MetaSpawnEgg Spigot Changes: d90018e0 SPIGOT-7199: NPE loading or creating world with custom chunk generator
231 Zeilen
12 KiB
Diff
231 Zeilen
12 KiB
Diff
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 6f39e343147803e15e7681c993b8797a629702e7..3a643d57b646c83974b5157b9cbb2a9f42e9bd59 100644
|
|
--- a/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
|
+++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
|
@@ -1,8 +1,14 @@
|
|
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..16996c743b169e625ec810523c1d59a305e1d159
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java
|
|
@@ -0,0 +1,44 @@
|
|
+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.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.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)
|
|
+public final class PaperConfiguredStructure {
|
|
+
|
|
+ private PaperConfiguredStructure() {
|
|
+ }
|
|
+
|
|
+ public static void init() {
|
|
+ new ConfiguredStructureRegistry().register();
|
|
+ }
|
|
+
|
|
+ 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) {
|
|
+ final ResourceLocation structureTypeLoc = Objects.requireNonNull(BuiltInRegistries.STRUCTURE_TYPE.getKey(nms.type()), "unexpected structure type " + nms.type());
|
|
+ final @Nullable StructureType structureType = StructureType.getStructureTypes().get(structureTypeLoc.getPath());
|
|
+ return structureType == null ? null : new ConfiguredStructure(key, structureType);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
|
index b6df6077107759963ee8205dddb90501d5ccb4d6..29032374f0e71a41a2de260d402b6fbff68288cc 100644
|
|
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
|
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
|
@@ -121,6 +121,26 @@ public abstract class ChunkGenerator {
|
|
|
|
@Nullable
|
|
public Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel world, HolderSet<Structure> structures, BlockPos center, int radius, boolean skipReferencedStructures) {
|
|
+ // Paper start - StructureLocateEvent
|
|
+ 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);
|
|
+ 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()));
|
|
+ }
|
|
+ center = io.papermc.paper.util.MCUtil.toBlockPosition(event.getOrigin());
|
|
+ radius = event.getRadius();
|
|
+ skipReferencedStructures = event.shouldFindUnexplored();
|
|
+ structures = HolderSet.direct(paperRegistry::getMinecraftHolder, event.getConfiguredStructures());
|
|
+ }
|
|
+ // 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/net/minecraft/world/level/levelgen/structure/Structure.java b/src/main/java/net/minecraft/world/level/levelgen/structure/Structure.java
|
|
index 8eaa1a57e904fe7e540b311c6c5c36b755f021fc..92730afcda6f779d0c440c7a8d50bb792b57d2d3 100644
|
|
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/Structure.java
|
|
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/Structure.java
|
|
@@ -42,6 +42,7 @@ public abstract class Structure {
|
|
public static final Codec<Structure> DIRECT_CODEC = BuiltInRegistries.STRUCTURE_TYPE.byNameCodec().dispatch(Structure::type, StructureType::codec);
|
|
public static final Codec<Holder<Structure>> CODEC = RegistryFileCodec.create(Registries.STRUCTURE, DIRECT_CODEC);
|
|
protected final Structure.StructureSettings settings;
|
|
+ static { io.papermc.paper.world.structure.PaperConfiguredStructure.init(); } // Paper
|
|
|
|
public static <S extends Structure> RecordCodecBuilder<S, Structure.StructureSettings> settingsCodec(RecordCodecBuilder.Instance<S> instance) {
|
|
return Structure.StructureSettings.CODEC.forGetter((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..61efebe1d363b34e2043ccc4c6e28bb714c2fa31
|
|
--- /dev/null
|
|
+++ b/src/test/java/io/papermc/paper/world/structure/ConfiguredStructureTest.java
|
|
@@ -0,0 +1,92 @@
|
|
+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.structure.Structure;
|
|
+import net.minecraft.world.level.levelgen.structure.BuiltinStructures;
|
|
+import org.bukkit.NamespacedKey;
|
|
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
|
+import org.bukkit.support.AbstractTestingBase;
|
|
+import org.junit.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.STRUCTURES.size());
|
|
+
|
|
+ Map<ResourceLocation, Structure> missing = new LinkedHashMap<>();
|
|
+ for (Structure feature : BuiltinRegistries.STRUCTURES) {
|
|
+ final ResourceLocation key = BuiltinRegistries.STRUCTURES.getKey(feature);
|
|
+ assertNotNull("Missing built-in registry key", key);
|
|
+ if (key.equals(BuiltinStructures.ANCIENT_CITY.location())) {
|
|
+ continue; // TODO remove when upstream adds "jigsaw" StructureType
|
|
+ }
|
|
+ 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.STRUCTURES.containsKey(CraftNamespacedKey.toMinecraft(apiKey)));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static String printMissing(Map<ResourceLocation, Structure> 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);
|
|
+ }
|
|
+}
|
|
diff --git a/src/test/java/org/bukkit/support/AbstractTestingBase.java b/src/test/java/org/bukkit/support/AbstractTestingBase.java
|
|
index 084c48ffabac2cd753609add745203e8a55bc09e..6c4689545b30d172850436a73eee58f9b8b49240 100644
|
|
--- a/src/test/java/org/bukkit/support/AbstractTestingBase.java
|
|
+++ b/src/test/java/org/bukkit/support/AbstractTestingBase.java
|
|
@@ -51,7 +51,7 @@ public abstract class AbstractTestingBase {
|
|
REGISTRY_CUSTOM = layers.compositeAccess().freeze();
|
|
// Paper start
|
|
try {
|
|
- java.lang.reflect.Field field = io.papermc.paper.registry.PaperRegistry.class.getDeclaredField("REGISTRY_ACCESS");
|
|
+ java.lang.reflect.Field field = io.papermc.paper.registry.PaperRegistry.class.getDeclaredField("REGISTRgY_ACCESS");
|
|
field.trySetAccessible();
|
|
field.set(null, com.google.common.base.Suppliers.ofInstance(REGISTRY_CUSTOM));
|
|
} catch (ReflectiveOperationException ex) {
|