mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-26 12:36:07 +01:00
225 lines
12 KiB
Diff
225 lines
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..cbff75f19e54b37c762b209b04f6d4799152cf5b 100644
|
|
--- a/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
|
+++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
|
@@ -1,8 +1,13 @@
|
|
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..41f6c2e1e60fc32e6393097711412ca2ad643e57
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java
|
|
@@ -0,0 +1,42 @@
|
|
+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 9941456a019a34384f892c44df3c73f9416bd560..d109ef77109fbeb710eafb55a38c803b9bb37d73 100644
|
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
@@ -2032,7 +2032,7 @@ 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 fff5c9d40a0bab8642376db3ec25cc1e8d666fa6..a3af8b892a01756addc8c24e0726b5a8a700cbba 100644
|
|
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
|
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
|
@@ -302,6 +302,26 @@ 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 af9ef29f5c5a600e4544ba735c833699cc93f93a..473a54963fbe08beeff26a828827f9f72d8a29b8 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
|
|
@@ -38,6 +38,7 @@ 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..29c0209327374d5a4dad4e3bacdba7fa56d80749
|
|
--- /dev/null
|
|
+++ b/src/test/java/io/papermc/paper/world/structure/ConfiguredStructureTest.java
|
|
@@ -0,0 +1,89 @@
|
|
+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);
|
|
+ }
|
|
+}
|