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>
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
2023-10-03 13:55:12 +02:00
index 0000000000000000000000000000000000000000..2667067fd13f61e0464ba88ae4e4a7078351d1a8
2022-03-04 09:09:43 +01:00
--- /dev/null
+++ b/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java
2023-02-28 17:36:01 +01:00
@@ -0,0 +1,35 @@
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() {
+ }
+
2023-02-28 17:36:01 +01:00
+ @Deprecated(forRemoval = true)
+ public static final class LegacyRegistry extends CraftRegistry<ConfiguredStructure, Structure> {
2022-03-04 09:09:43 +01:00
+
2023-02-28 17:36:01 +01:00
+ public LegacyRegistry(final Registry<Structure> minecraftRegistry) {
2023-10-03 13:55:12 +02:00
+ super(ConfiguredStructure.class, minecraftRegistry, LegacyRegistry::minecraftToBukkit);
2022-03-04 09:09:43 +01:00
+ }
+
2023-02-28 17:36:01 +01:00
+ private static @Nullable ConfiguredStructure minecraftToBukkit(NamespacedKey key, Structure nms) {
2022-12-08 05:24:59 +01:00
+ final ResourceLocation structureTypeLoc = Objects.requireNonNull(BuiltInRegistries.STRUCTURE_TYPE.getKey(nms.type()), "unexpected structure type " + nms.type());
2022-06-08 21:00:19 +02:00
+ 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-23 19:02:08 +02:00
index 4a731b9170222a5a2b0089ef5e9527dbd46a9ad5..edd968686292237e95afdf99a291f501386144ef 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
2023-02-28 17:36:01 +01:00
@@ -121,6 +121,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();
2023-02-28 17:36:01 +01:00
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
Updated Upstream (Bukkit/CraftBukkit) (#10242)
* Updated Upstream (Bukkit/CraftBukkit)
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:
a6a9d2a4 Remove some old ApiStatus.Experimental annotations
be72314c SPIGOT-7300, PR-829: Add new DamageSource API providing enhanced information about entity damage
b252cf05 SPIGOT-7576, PR-970: Add methods in MushroomCow to change stew effects
b1c689bd PR-902: Add Server#isLoggingIPs to get log-ips configuration
08f86d1c PR-971: Add Player methods for client-side potion effects
2e3024a9 PR-963: Add API for in-world structures
a23292a7 SPIGOT-7530, PR-948: Improve Resource Pack API with new 1.20.3 functionality
1851857b SPIGOT-3071, PR-969: Add entity spawn method with spawn reason
cde4c52a SPIGOT-5553, PR-964: Add EntityKnockbackEvent
CraftBukkit Changes:
38fd4bd50 Fix accidentally renamed internal damage method
80f0ce4be SPIGOT-7300, PR-1180: Add new DamageSource API providing enhanced information about entity damage
7e43f3b16 SPIGOT-7581: Fix typo in BlockMushroom
ea14b7d90 SPIGOT-7576, PR-1347: Add methods in MushroomCow to change stew effects
4c687f243 PR-1259: Add Server#isLoggingIPs to get log-ips configuration
22a541a29 Improve support for per-world game rules
cb7dccce2 PR-1348: Add Player methods for client-side potion effects
b8d6109f0 PR-1335: Add API for in-world structures
4398a1b5b SPIGOT-7577: Make CraftWindCharge#explode discard the entity
e74107678 Fix Crafter maximum stack size
0bb0f4f6a SPIGOT-7530, PR-1314: Improve Resource Pack API with new 1.20.3 functionality
4949f556d SPIGOT-3071, PR-1345: Add entity spawn method with spawn reason
20ac73ca2 PR-1353: Fix Structure#place not working as documented with 0 palette
3c1b77871 SPIGOT-6911, PR-1349: Change max book length in CraftMetaBook
333701839 SPIGOT-7572: Bee nests generated without bees
f48f4174c SPIGOT-5553, PR-1336: Add EntityKnockbackEvent
2024-02-11 22:28:00 +01:00
index 110987de809339b4ce14eaf377782ebf3460164a..b12b99253543445475b73a1d3d7c6364856b49e8 100644
2023-02-28 17:36:01 +01:00
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
Updated Upstream (Bukkit/CraftBukkit) (#10242)
* Updated Upstream (Bukkit/CraftBukkit)
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:
a6a9d2a4 Remove some old ApiStatus.Experimental annotations
be72314c SPIGOT-7300, PR-829: Add new DamageSource API providing enhanced information about entity damage
b252cf05 SPIGOT-7576, PR-970: Add methods in MushroomCow to change stew effects
b1c689bd PR-902: Add Server#isLoggingIPs to get log-ips configuration
08f86d1c PR-971: Add Player methods for client-side potion effects
2e3024a9 PR-963: Add API for in-world structures
a23292a7 SPIGOT-7530, PR-948: Improve Resource Pack API with new 1.20.3 functionality
1851857b SPIGOT-3071, PR-969: Add entity spawn method with spawn reason
cde4c52a SPIGOT-5553, PR-964: Add EntityKnockbackEvent
CraftBukkit Changes:
38fd4bd50 Fix accidentally renamed internal damage method
80f0ce4be SPIGOT-7300, PR-1180: Add new DamageSource API providing enhanced information about entity damage
7e43f3b16 SPIGOT-7581: Fix typo in BlockMushroom
ea14b7d90 SPIGOT-7576, PR-1347: Add methods in MushroomCow to change stew effects
4c687f243 PR-1259: Add Server#isLoggingIPs to get log-ips configuration
22a541a29 Improve support for per-world game rules
cb7dccce2 PR-1348: Add Player methods for client-side potion effects
b8d6109f0 PR-1335: Add API for in-world structures
4398a1b5b SPIGOT-7577: Make CraftWindCharge#explode discard the entity
e74107678 Fix Crafter maximum stack size
0bb0f4f6a SPIGOT-7530, PR-1314: Improve Resource Pack API with new 1.20.3 functionality
4949f556d SPIGOT-3071, PR-1345: Add entity spawn method with spawn reason
20ac73ca2 PR-1353: Fix Structure#place not working as documented with 0 palette
3c1b77871 SPIGOT-6911, PR-1349: Change max book length in CraftMetaBook
333701839 SPIGOT-7572: Bee nests generated without bees
f48f4174c SPIGOT-5553, PR-1336: Add EntityKnockbackEvent
2024-02-11 22:28:00 +01:00
@@ -120,6 +120,11 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return new CraftRegistry<>(DamageType.class, registryHolder.registryOrThrow(Registries.DAMAGE_TYPE), CraftDamageType::new);
2023-02-28 17:36:01 +01:00
}
// 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
2023-02-16 00:00:22 +01:00
2023-02-28 17:36:01 +01:00
return null;
}
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
index 4e4ea083063daf22f1bb785ef212958ea889c43b..1c4966520b6401e6571aa44d5934dfa280bc80e3 100644
--- 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;
}
+ if (object instanceof io.papermc.paper.world.structure.PaperConfiguredStructure.LegacyRegistry) continue; // Paper - skip
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
index 4adaafafb7140e983a4e90f0ff0deaaf0887a9a5..65cc33c45553e755371ec4313dd38bb61eb7d61c 100644
--- a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
+++ b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
@@ -23,6 +23,7 @@ public class RegistryArgumentAddedTest extends AbstractTestingBase {
Set<Class<?>> loadedRegistries = new HashSet<>(DummyServer.registers.keySet());
Set<Class<?>> notFound = new HashSet<>();
+ loadedRegistries.remove(io.papermc.paper.world.structure.ConfiguredStructure.class); // Paper - ignore
RegistriesArgumentProvider
.getData()