From 867ce6cc0a30073e2716ca6f85e318caed023f89 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Wed, 22 Nov 2023 20:56:28 -0800 Subject: [PATCH] Code Generation for TypedKeys (#9233) Currently includes generated key holder classes for types used in the Registry Modification API --- .editorconfig | 3 + .gitignore | 1 + paper-api-generator/build.gradle.kts | 28 + .../paper/registry/keys/BiomeKeys.java | 490 ++++++++++++++++++ .../paper/registry/keys/GameEventKeys.java | 462 +++++++++++++++++ .../registry/keys/StructureTypeKeys.java | 147 ++++++ .../paper/registry/keys/TrimMaterialKeys.java | 112 ++++ .../paper/registry/keys/TrimPatternKeys.java | 154 ++++++ .../main/java/io/papermc/generator/Main.java | 85 +++ .../papermc/generator/types/Annotations.java | 24 + .../generator/types/GeneratedKeyType.java | 205 ++++++++ .../generator/types/SourceGenerator.java | 11 + .../generator/utils/CollectingContext.java | 28 + paper-api-generator/wideners.at | 6 + patches/api/Code-Generation.patch | 251 +++++++++ patches/server/Test-changes.patch | 39 ++ settings.gradle.kts | 20 +- 17 files changed, 2061 insertions(+), 5 deletions(-) create mode 100644 paper-api-generator/build.gradle.kts create mode 100644 paper-api-generator/generated/io/papermc/paper/registry/keys/BiomeKeys.java create mode 100644 paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java create mode 100644 paper-api-generator/generated/io/papermc/paper/registry/keys/StructureTypeKeys.java create mode 100644 paper-api-generator/generated/io/papermc/paper/registry/keys/TrimMaterialKeys.java create mode 100644 paper-api-generator/generated/io/papermc/paper/registry/keys/TrimPatternKeys.java create mode 100644 paper-api-generator/src/main/java/io/papermc/generator/Main.java create mode 100644 paper-api-generator/src/main/java/io/papermc/generator/types/Annotations.java create mode 100644 paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java create mode 100644 paper-api-generator/src/main/java/io/papermc/generator/types/SourceGenerator.java create mode 100644 paper-api-generator/src/main/java/io/papermc/generator/utils/CollectingContext.java create mode 100644 paper-api-generator/wideners.at create mode 100644 patches/api/Code-Generation.patch diff --git a/.editorconfig b/.editorconfig index df706b347c..2874476cf4 100644 --- a/.editorconfig +++ b/.editorconfig @@ -35,3 +35,6 @@ ij_java_use_fq_class_names = false [Paper-Server/src/main/resources/data/**/*.json] indent_size = 2 + +[paper-api-generator/generated/**/*.java] +ij_java_imports_layout = $*,|,* diff --git a/.gitignore b/.gitignore index 29fc656b7d..71fa37fc83 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,4 @@ paperclip.properties !gradle/wrapper/gradle-wrapper.jar test-plugin.settings.gradle.kts +paper-api-generator.settings.gradle.kts diff --git a/paper-api-generator/build.gradle.kts b/paper-api-generator/build.gradle.kts new file mode 100644 index 0000000000..50cc3c1e59 --- /dev/null +++ b/paper-api-generator/build.gradle.kts @@ -0,0 +1,28 @@ +import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform + +plugins { + java + id("org.spongepowered.gradle.vanilla") version "0.2.1-SNAPSHOT" +} + +minecraft { + version(property("mcVersion").toString()) + platform(MinecraftPlatform.SERVER) + + runs { + server("generate") { + mainClass("io.papermc.generator.Main") + accessWideners(projectDir.toPath().resolve("wideners.at")) + args(projectDir.toPath().resolve("generated").toString()) + } + } +} + +dependencies { + implementation("com.squareup:javapoet:1.13.0") + implementation(project(":paper-api")) +} + +group = "io.papermc.paper" +version = "1.0-SNAPSHOT" + diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/BiomeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/BiomeKeys.java new file mode 100644 index 0000000000..84e6385588 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/BiomeKeys.java @@ -0,0 +1,490 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.block.Biome; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Vanilla keys for {@link RegistryKey#BIOME}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.20.2") +@ApiStatus.Experimental +public final class BiomeKeys { + /** + * {@code minecraft:badlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BADLANDS = create(key("badlands")); + + /** + * {@code minecraft:bamboo_jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAMBOO_JUNGLE = create(key("bamboo_jungle")); + + /** + * {@code minecraft:basalt_deltas} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BASALT_DELTAS = create(key("basalt_deltas")); + + /** + * {@code minecraft:beach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BEACH = create(key("beach")); + + /** + * {@code minecraft:birch_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BIRCH_FOREST = create(key("birch_forest")); + + /** + * {@code minecraft:cherry_grove} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHERRY_GROVE = create(key("cherry_grove")); + + /** + * {@code minecraft:cold_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COLD_OCEAN = create(key("cold_ocean")); + + /** + * {@code minecraft:crimson_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRIMSON_FOREST = create(key("crimson_forest")); + + /** + * {@code minecraft:dark_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARK_FOREST = create(key("dark_forest")); + + /** + * {@code minecraft:deep_cold_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEP_COLD_OCEAN = create(key("deep_cold_ocean")); + + /** + * {@code minecraft:deep_dark} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEP_DARK = create(key("deep_dark")); + + /** + * {@code minecraft:deep_frozen_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEP_FROZEN_OCEAN = create(key("deep_frozen_ocean")); + + /** + * {@code minecraft:deep_lukewarm_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEP_LUKEWARM_OCEAN = create(key("deep_lukewarm_ocean")); + + /** + * {@code minecraft:deep_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEEP_OCEAN = create(key("deep_ocean")); + + /** + * {@code minecraft:desert} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DESERT = create(key("desert")); + + /** + * {@code minecraft:dripstone_caves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRIPSTONE_CAVES = create(key("dripstone_caves")); + + /** + * {@code minecraft:end_barrens} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_BARRENS = create(key("end_barrens")); + + /** + * {@code minecraft:end_highlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_HIGHLANDS = create(key("end_highlands")); + + /** + * {@code minecraft:end_midlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_MIDLANDS = create(key("end_midlands")); + + /** + * {@code minecraft:eroded_badlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ERODED_BADLANDS = create(key("eroded_badlands")); + + /** + * {@code minecraft:flower_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLOWER_FOREST = create(key("flower_forest")); + + /** + * {@code minecraft:forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FOREST = create(key("forest")); + + /** + * {@code minecraft:frozen_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROZEN_OCEAN = create(key("frozen_ocean")); + + /** + * {@code minecraft:frozen_peaks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROZEN_PEAKS = create(key("frozen_peaks")); + + /** + * {@code minecraft:frozen_river} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROZEN_RIVER = create(key("frozen_river")); + + /** + * {@code minecraft:grove} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GROVE = create(key("grove")); + + /** + * {@code minecraft:ice_spikes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ICE_SPIKES = create(key("ice_spikes")); + + /** + * {@code minecraft:jagged_peaks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JAGGED_PEAKS = create(key("jagged_peaks")); + + /** + * {@code minecraft:jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE = create(key("jungle")); + + /** + * {@code minecraft:lukewarm_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LUKEWARM_OCEAN = create(key("lukewarm_ocean")); + + /** + * {@code minecraft:lush_caves} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LUSH_CAVES = create(key("lush_caves")); + + /** + * {@code minecraft:mangrove_swamp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MANGROVE_SWAMP = create(key("mangrove_swamp")); + + /** + * {@code minecraft:meadow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MEADOW = create(key("meadow")); + + /** + * {@code minecraft:mushroom_fields} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MUSHROOM_FIELDS = create(key("mushroom_fields")); + + /** + * {@code minecraft:nether_wastes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_WASTES = create(key("nether_wastes")); + + /** + * {@code minecraft:ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OCEAN = create(key("ocean")); + + /** + * {@code minecraft:old_growth_birch_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OLD_GROWTH_BIRCH_FOREST = create(key("old_growth_birch_forest")); + + /** + * {@code minecraft:old_growth_pine_taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OLD_GROWTH_PINE_TAIGA = create(key("old_growth_pine_taiga")); + + /** + * {@code minecraft:old_growth_spruce_taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OLD_GROWTH_SPRUCE_TAIGA = create(key("old_growth_spruce_taiga")); + + /** + * {@code minecraft:plains} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAINS = create(key("plains")); + + /** + * {@code minecraft:river} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RIVER = create(key("river")); + + /** + * {@code minecraft:savanna} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SAVANNA = create(key("savanna")); + + /** + * {@code minecraft:savanna_plateau} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SAVANNA_PLATEAU = create(key("savanna_plateau")); + + /** + * {@code minecraft:small_end_islands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMALL_END_ISLANDS = create(key("small_end_islands")); + + /** + * {@code minecraft:snowy_beach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOWY_BEACH = create(key("snowy_beach")); + + /** + * {@code minecraft:snowy_plains} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOWY_PLAINS = create(key("snowy_plains")); + + /** + * {@code minecraft:snowy_slopes} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOWY_SLOPES = create(key("snowy_slopes")); + + /** + * {@code minecraft:snowy_taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOWY_TAIGA = create(key("snowy_taiga")); + + /** + * {@code minecraft:soul_sand_valley} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_SAND_VALLEY = create(key("soul_sand_valley")); + + /** + * {@code minecraft:sparse_jungle} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPARSE_JUNGLE = create(key("sparse_jungle")); + + /** + * {@code minecraft:stony_peaks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONY_PEAKS = create(key("stony_peaks")); + + /** + * {@code minecraft:stony_shore} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STONY_SHORE = create(key("stony_shore")); + + /** + * {@code minecraft:sunflower_plains} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SUNFLOWER_PLAINS = create(key("sunflower_plains")); + + /** + * {@code minecraft:swamp} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWAMP = create(key("swamp")); + + /** + * {@code minecraft:taiga} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TAIGA = create(key("taiga")); + + /** + * {@code minecraft:the_end} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey THE_END = create(key("the_end")); + + /** + * {@code minecraft:the_void} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey THE_VOID = create(key("the_void")); + + /** + * {@code minecraft:warm_ocean} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARM_OCEAN = create(key("warm_ocean")); + + /** + * {@code minecraft:warped_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARPED_FOREST = create(key("warped_forest")); + + /** + * {@code minecraft:windswept_forest} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WINDSWEPT_FOREST = create(key("windswept_forest")); + + /** + * {@code minecraft:windswept_gravelly_hills} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WINDSWEPT_GRAVELLY_HILLS = create(key("windswept_gravelly_hills")); + + /** + * {@code minecraft:windswept_hills} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WINDSWEPT_HILLS = create(key("windswept_hills")); + + /** + * {@code minecraft:windswept_savanna} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WINDSWEPT_SAVANNA = create(key("windswept_savanna")); + + /** + * {@code minecraft:wooded_badlands} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOODED_BADLANDS = create(key("wooded_badlands")); + + private BiomeKeys() { + } + + /** + * Creates a key for {@link Biome} in a registry. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static @NotNull TypedKey create(final @NotNull Key key) { + return TypedKey.create(RegistryKey.BIOME, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java new file mode 100644 index 0000000000..978ed4aed5 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java @@ -0,0 +1,462 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.GameEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Vanilla keys for {@link RegistryKey#GAME_EVENT}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.20.2") +@ApiStatus.Experimental +public final class GameEventKeys { + /** + * {@code minecraft:block_activate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ACTIVATE = create(key("block_activate")); + + /** + * {@code minecraft:block_attach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_ATTACH = create(key("block_attach")); + + /** + * {@code minecraft:block_change} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CHANGE = create(key("block_change")); + + /** + * {@code minecraft:block_close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_CLOSE = create(key("block_close")); + + /** + * {@code minecraft:block_deactivate} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DEACTIVATE = create(key("block_deactivate")); + + /** + * {@code minecraft:block_destroy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DESTROY = create(key("block_destroy")); + + /** + * {@code minecraft:block_detach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_DETACH = create(key("block_detach")); + + /** + * {@code minecraft:block_open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_OPEN = create(key("block_open")); + + /** + * {@code minecraft:block_place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLOCK_PLACE = create(key("block_place")); + + /** + * {@code minecraft:container_close} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CONTAINER_CLOSE = create(key("container_close")); + + /** + * {@code minecraft:container_open} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CONTAINER_OPEN = create(key("container_open")); + + /** + * {@code minecraft:drink} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRINK = create(key("drink")); + + /** + * {@code minecraft:eat} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EAT = create(key("eat")); + + /** + * {@code minecraft:elytra_glide} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ELYTRA_GLIDE = create(key("elytra_glide")); + + /** + * {@code minecraft:entity_damage} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DAMAGE = create(key("entity_damage")); + + /** + * {@code minecraft:entity_die} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DIE = create(key("entity_die")); + + /** + * {@code minecraft:entity_dismount} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_DISMOUNT = create(key("entity_dismount")); + + /** + * {@code minecraft:entity_interact} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_INTERACT = create(key("entity_interact")); + + /** + * {@code minecraft:entity_mount} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_MOUNT = create(key("entity_mount")); + + /** + * {@code minecraft:entity_place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_PLACE = create(key("entity_place")); + + /** + * {@code minecraft:entity_action} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ENTITY_ACTION = create(key("entity_action")); + + /** + * {@code minecraft:equip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EQUIP = create(key("equip")); + + /** + * {@code minecraft:explode} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPLODE = create(key("explode")); + + /** + * {@code minecraft:flap} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLAP = create(key("flap")); + + /** + * {@code minecraft:fluid_pickup} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLUID_PICKUP = create(key("fluid_pickup")); + + /** + * {@code minecraft:fluid_place} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLUID_PLACE = create(key("fluid_place")); + + /** + * {@code minecraft:hit_ground} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HIT_GROUND = create(key("hit_ground")); + + /** + * {@code minecraft:instrument_play} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INSTRUMENT_PLAY = create(key("instrument_play")); + + /** + * {@code minecraft:item_interact_finish} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_INTERACT_FINISH = create(key("item_interact_finish")); + + /** + * {@code minecraft:item_interact_start} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ITEM_INTERACT_START = create(key("item_interact_start")); + + /** + * {@code minecraft:jukebox_play} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUKEBOX_PLAY = create(key("jukebox_play")); + + /** + * {@code minecraft:jukebox_stop_play} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUKEBOX_STOP_PLAY = create(key("jukebox_stop_play")); + + /** + * {@code minecraft:lightning_strike} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHTNING_STRIKE = create(key("lightning_strike")); + + /** + * {@code minecraft:note_block_play} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NOTE_BLOCK_PLAY = create(key("note_block_play")); + + /** + * {@code minecraft:prime_fuse} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PRIME_FUSE = create(key("prime_fuse")); + + /** + * {@code minecraft:projectile_land} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PROJECTILE_LAND = create(key("projectile_land")); + + /** + * {@code minecraft:projectile_shoot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PROJECTILE_SHOOT = create(key("projectile_shoot")); + + /** + * {@code minecraft:sculk_sensor_tendrils_clicking} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SCULK_SENSOR_TENDRILS_CLICKING = create(key("sculk_sensor_tendrils_clicking")); + + /** + * {@code minecraft:shear} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHEAR = create(key("shear")); + + /** + * {@code minecraft:shriek} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHRIEK = create(key("shriek")); + + /** + * {@code minecraft:splash} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPLASH = create(key("splash")); + + /** + * {@code minecraft:step} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STEP = create(key("step")); + + /** + * {@code minecraft:swim} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWIM = create(key("swim")); + + /** + * {@code minecraft:teleport} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TELEPORT = create(key("teleport")); + + /** + * {@code minecraft:unequip} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UNEQUIP = create(key("unequip")); + + /** + * {@code minecraft:resonate_1} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_1 = create(key("resonate_1")); + + /** + * {@code minecraft:resonate_2} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_2 = create(key("resonate_2")); + + /** + * {@code minecraft:resonate_3} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_3 = create(key("resonate_3")); + + /** + * {@code minecraft:resonate_4} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_4 = create(key("resonate_4")); + + /** + * {@code minecraft:resonate_5} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_5 = create(key("resonate_5")); + + /** + * {@code minecraft:resonate_6} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_6 = create(key("resonate_6")); + + /** + * {@code minecraft:resonate_7} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_7 = create(key("resonate_7")); + + /** + * {@code minecraft:resonate_8} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_8 = create(key("resonate_8")); + + /** + * {@code minecraft:resonate_9} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_9 = create(key("resonate_9")); + + /** + * {@code minecraft:resonate_10} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_10 = create(key("resonate_10")); + + /** + * {@code minecraft:resonate_11} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_11 = create(key("resonate_11")); + + /** + * {@code minecraft:resonate_12} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_12 = create(key("resonate_12")); + + /** + * {@code minecraft:resonate_13} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_13 = create(key("resonate_13")); + + /** + * {@code minecraft:resonate_14} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_14 = create(key("resonate_14")); + + /** + * {@code minecraft:resonate_15} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESONATE_15 = create(key("resonate_15")); + + private GameEventKeys() { + } + + /** + * Creates a key for {@link GameEvent} in a registry. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static @NotNull TypedKey create(final @NotNull Key key) { + return TypedKey.create(RegistryKey.GAME_EVENT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/StructureTypeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/StructureTypeKeys.java new file mode 100644 index 0000000000..03fc2b494f --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/StructureTypeKeys.java @@ -0,0 +1,147 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.generator.structure.StructureType; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Vanilla keys for {@link RegistryKey#STRUCTURE_TYPE}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.20.2") +@ApiStatus.Experimental +public final class StructureTypeKeys { + /** + * {@code minecraft:buried_treasure} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BURIED_TREASURE = create(key("buried_treasure")); + + /** + * {@code minecraft:desert_pyramid} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DESERT_PYRAMID = create(key("desert_pyramid")); + + /** + * {@code minecraft:end_city} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey END_CITY = create(key("end_city")); + + /** + * {@code minecraft:fortress} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FORTRESS = create(key("fortress")); + + /** + * {@code minecraft:igloo} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IGLOO = create(key("igloo")); + + /** + * {@code minecraft:jigsaw} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JIGSAW = create(key("jigsaw")); + + /** + * {@code minecraft:jungle_temple} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUNGLE_TEMPLE = create(key("jungle_temple")); + + /** + * {@code minecraft:mineshaft} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MINESHAFT = create(key("mineshaft")); + + /** + * {@code minecraft:nether_fossil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHER_FOSSIL = create(key("nether_fossil")); + + /** + * {@code minecraft:ocean_monument} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OCEAN_MONUMENT = create(key("ocean_monument")); + + /** + * {@code minecraft:ocean_ruin} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OCEAN_RUIN = create(key("ocean_ruin")); + + /** + * {@code minecraft:ruined_portal} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RUINED_PORTAL = create(key("ruined_portal")); + + /** + * {@code minecraft:shipwreck} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHIPWRECK = create(key("shipwreck")); + + /** + * {@code minecraft:stronghold} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRONGHOLD = create(key("stronghold")); + + /** + * {@code minecraft:swamp_hut} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWAMP_HUT = create(key("swamp_hut")); + + /** + * {@code minecraft:woodland_mansion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOODLAND_MANSION = create(key("woodland_mansion")); + + private StructureTypeKeys() { + } + + private static @NotNull TypedKey create(final @NotNull Key key) { + return TypedKey.create(RegistryKey.STRUCTURE_TYPE, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimMaterialKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimMaterialKeys.java new file mode 100644 index 0000000000..bb54110ab1 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimMaterialKeys.java @@ -0,0 +1,112 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.inventory.meta.trim.TrimMaterial; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Vanilla keys for {@link RegistryKey#TRIM_MATERIAL}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.20.2") +@ApiStatus.Experimental +public final class TrimMaterialKeys { + /** + * {@code minecraft:amethyst} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AMETHYST = create(key("amethyst")); + + /** + * {@code minecraft:copper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COPPER = create(key("copper")); + + /** + * {@code minecraft:diamond} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DIAMOND = create(key("diamond")); + + /** + * {@code minecraft:emerald} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EMERALD = create(key("emerald")); + + /** + * {@code minecraft:gold} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GOLD = create(key("gold")); + + /** + * {@code minecraft:iron} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IRON = create(key("iron")); + + /** + * {@code minecraft:lapis} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAPIS = create(key("lapis")); + + /** + * {@code minecraft:netherite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NETHERITE = create(key("netherite")); + + /** + * {@code minecraft:quartz} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUARTZ = create(key("quartz")); + + /** + * {@code minecraft:redstone} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REDSTONE = create(key("redstone")); + + private TrimMaterialKeys() { + } + + /** + * Creates a key for {@link TrimMaterial} in a registry. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static @NotNull TypedKey create(final @NotNull Key key) { + return TypedKey.create(RegistryKey.TRIM_MATERIAL, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimPatternKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimPatternKeys.java new file mode 100644 index 0000000000..8576ff1669 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/TrimPatternKeys.java @@ -0,0 +1,154 @@ +package io.papermc.paper.registry.keys; + +import static net.kyori.adventure.key.Key.key; + +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import net.kyori.adventure.key.Key; +import org.bukkit.inventory.meta.trim.TrimPattern; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Vanilla keys for {@link RegistryKey#TRIM_PATTERN}. + * + * @apiNote The fields provided here are a direct representation of + * what is available from the vanilla game source. They may be + * changed (including removals) on any Minecraft version + * bump, so cross-version compatibility is not provided on the + * same level as it is on most of the other API. + */ +@SuppressWarnings({ + "unused", + "SpellCheckingInspection" +}) +@GeneratedFrom("1.20.2") +@ApiStatus.Experimental +public final class TrimPatternKeys { + /** + * {@code minecraft:coast} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey COAST = create(key("coast")); + + /** + * {@code minecraft:dune} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DUNE = create(key("dune")); + + /** + * {@code minecraft:eye} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EYE = create(key("eye")); + + /** + * {@code minecraft:host} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HOST = create(key("host")); + + /** + * {@code minecraft:raiser} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RAISER = create(key("raiser")); + + /** + * {@code minecraft:rib} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RIB = create(key("rib")); + + /** + * {@code minecraft:sentry} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SENTRY = create(key("sentry")); + + /** + * {@code minecraft:shaper} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHAPER = create(key("shaper")); + + /** + * {@code minecraft:silence} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SILENCE = create(key("silence")); + + /** + * {@code minecraft:snout} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOUT = create(key("snout")); + + /** + * {@code minecraft:spire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPIRE = create(key("spire")); + + /** + * {@code minecraft:tide} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TIDE = create(key("tide")); + + /** + * {@code minecraft:vex} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VEX = create(key("vex")); + + /** + * {@code minecraft:ward} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WARD = create(key("ward")); + + /** + * {@code minecraft:wayfinder} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WAYFINDER = create(key("wayfinder")); + + /** + * {@code minecraft:wild} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WILD = create(key("wild")); + + private TrimPatternKeys() { + } + + /** + * Creates a key for {@link TrimPattern} in a registry. + * + * @param key the value's key in the registry + * @return a new typed key + */ + @ApiStatus.Experimental + public static @NotNull TypedKey create(final @NotNull Key key) { + return TypedKey.create(RegistryKey.TRIM_PATTERN, key); + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/Main.java b/paper-api-generator/src/main/java/io/papermc/generator/Main.java new file mode 100644 index 0000000000..6e02e0b48f --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/Main.java @@ -0,0 +1,85 @@ +package io.papermc.generator; + +import com.mojang.logging.LogUtils; +import io.papermc.generator.types.GeneratedKeyType; +import io.papermc.generator.types.SourceGenerator; +import io.papermc.paper.registry.RegistryKey; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import net.kyori.adventure.key.Keyed; +import net.minecraft.SharedConstants; +import net.minecraft.core.LayeredRegistryAccess; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.RegistryDataLoader; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.Bootstrap; +import net.minecraft.server.RegistryLayer; +import net.minecraft.server.WorldLoader; +import net.minecraft.server.packs.PackType; +import net.minecraft.server.packs.repository.Pack; +import net.minecraft.server.packs.repository.PackRepository; +import net.minecraft.server.packs.repository.ServerPacksSource; +import net.minecraft.server.packs.resources.MultiPackResourceManager; +import org.apache.commons.io.file.PathUtils; +import org.bukkit.GameEvent; +import org.bukkit.block.Biome; +import org.bukkit.generator.structure.StructureType; +import org.bukkit.inventory.meta.trim.TrimMaterial; +import org.bukkit.inventory.meta.trim.TrimPattern; +import org.slf4j.Logger; + +public final class Main { + + private static final Logger LOGGER = LogUtils.getLogger(); + public static final RegistryAccess.Frozen REGISTRY_ACCESS; + + static { + SharedConstants.tryDetectVersion(); + Bootstrap.bootStrap(); + final PackRepository resourceRepository = ServerPacksSource.createVanillaTrustedRepository(); + resourceRepository.reload(); + final MultiPackResourceManager resourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, resourceRepository.getAvailablePacks().stream().map(Pack::open).toList()); + LayeredRegistryAccess layers = RegistryLayer.createRegistryAccess(); + layers = WorldLoader.loadAndReplaceLayer(resourceManager, layers, RegistryLayer.WORLDGEN, RegistryDataLoader.WORLDGEN_REGISTRIES); + REGISTRY_ACCESS = layers.compositeAccess().freeze(); + } + + private static final List GENERATORS = List.of( + simpleKey("GameEventKeys", GameEvent.class, Registries.GAME_EVENT, RegistryKey.GAME_EVENT, true), + simpleKey("BiomeKeys", Biome.class, Registries.BIOME, RegistryKey.BIOME, true), + simpleKey("TrimMaterialKeys", TrimMaterial.class, Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL, true), + simpleKey("TrimPatternKeys", TrimPattern.class, Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN, true), + simpleKey("StructureTypeKeys", StructureType.class, Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE, false) + ); + + private static SourceGenerator simpleKey(final String className, final Class apiType, final ResourceKey> registryKey, final RegistryKey apiRegistryKey, final boolean publicCreateKeyMethod) { + return new GeneratedKeyType<>(className, apiType, "io.papermc.paper.registry.keys", registryKey, apiRegistryKey, publicCreateKeyMethod); + } + + private Main() { + } + + public static void main(final String[] args) { + final Path output = Paths.get(args[0]); + try { + if (Files.exists(output)) { + PathUtils.deleteDirectory(output); + } + Files.createDirectories(output); + + for (final SourceGenerator generator : GENERATORS) { + generator.writeToFile(output); + } + + LOGGER.info("Files written to {}", output.toAbsolutePath()); + } catch (final Exception ex) { + throw new RuntimeException(ex); + } + } + + +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/Annotations.java b/paper-api-generator/src/main/java/io/papermc/generator/types/Annotations.java new file mode 100644 index 0000000000..342d80454b --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/types/Annotations.java @@ -0,0 +1,24 @@ +package io.papermc.generator.types; + +import com.squareup.javapoet.AnnotationSpec; +import java.util.List; +import org.bukkit.MinecraftExperimental; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +public final class Annotations { + + public static final List EXPERIMENTAL_ANNOTATIONS = List.of( + AnnotationSpec.builder(ApiStatus.Experimental.class).build(), + AnnotationSpec.builder(MinecraftExperimental.class) + .addMember("value", "$S", "update 1.20") + .build() + ); + + @ApiStatus.Experimental + public static final AnnotationSpec EXPERIMENTAL_API_ANNOTATION = AnnotationSpec.builder(ApiStatus.Experimental.class).build(); + public static final AnnotationSpec NOT_NULL = AnnotationSpec.builder(NotNull.class).build(); + + private Annotations() { + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java b/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java new file mode 100644 index 0000000000..2af1bc8fb6 --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java @@ -0,0 +1,205 @@ +package io.papermc.generator.types; + +import com.squareup.javapoet.AnnotationSpec; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import io.papermc.generator.Main; +import io.papermc.generator.utils.CollectingContext; +import io.papermc.paper.generated.GeneratedFrom; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.TypedKey; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import net.kyori.adventure.key.Key; +import net.minecraft.SharedConstants; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistrySetBuilder; +import net.minecraft.resources.ResourceKey; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.DefaultQualifier; + +import static com.squareup.javapoet.TypeSpec.classBuilder; +import static io.papermc.generator.types.Annotations.EXPERIMENTAL_ANNOTATIONS; +import static io.papermc.generator.types.Annotations.EXPERIMENTAL_API_ANNOTATION; +import static io.papermc.generator.types.Annotations.NOT_NULL; +import static java.util.Objects.requireNonNull; +import static javax.lang.model.element.Modifier.FINAL; +import static javax.lang.model.element.Modifier.PRIVATE; +import static javax.lang.model.element.Modifier.PUBLIC; +import static javax.lang.model.element.Modifier.STATIC; + +@DefaultQualifier(NonNull.class) +public class GeneratedKeyType implements SourceGenerator { + + // don't exist anymore + // private static final Map>, RegistrySetBuilder.RegistryBootstrap> EXPERIMENTAL_REGISTRY_ENTRIES = UpdateOneTwentyRegistries.BUILDER.entries.stream() + // .collect(Collectors.toMap(RegistrySetBuilder.RegistryStub::key, RegistrySetBuilder.RegistryStub::bootstrap)); + private static final Map>, RegistrySetBuilder.RegistryBootstrap> EXPERIMENTAL_REGISTRY_ENTRIES = Collections.emptyMap(); + + private static final Map, String> REGISTRY_KEY_FIELD_NAMES; + static { + final Map, String> map = new HashMap<>(); + try { + for (final Field field : RegistryKey.class.getFields()) { + if (!Modifier.isStatic(field.getModifiers()) || !Modifier.isFinal(field.getModifiers()) || field.getType() != RegistryKey.class) { + continue; + } + map.put((RegistryKey) field.get(null), field.getName()); + } + REGISTRY_KEY_FIELD_NAMES = Map.copyOf(map); + } catch (final ReflectiveOperationException ex) { + throw new RuntimeException(ex); + } + } + + private static final AnnotationSpec SUPPRESS_WARNINGS = AnnotationSpec.builder(SuppressWarnings.class) + .addMember("value", "$S", "unused") + .addMember("value", "$S", "SpellCheckingInspection") + .build(); + private static final AnnotationSpec GENERATED_FROM = AnnotationSpec.builder(GeneratedFrom.class) + .addMember("value", "$S", SharedConstants.getCurrentVersion().getName()) + .build(); + private static final String TYPE_JAVADOC = """ + Vanilla keys for {@link $T#$L}. + + @apiNote The fields provided here are a direct representation of + what is available from the vanilla game source. They may be + changed (including removals) on any Minecraft version + bump, so cross-version compatibility is not provided on the + same level as it is on most of the other API. + """; + private static final String FIELD_JAVADOC = """ + {@code $L} + + @apiNote This field is version-dependant and may be removed in future Minecraft versions + """; + private static final String CREATE_JAVADOC = """ + Creates a key for {@link $T} in a registry. + + @param key the value's key in the registry + @return a new typed key + """; + + private final String keysClassName; + private final Class apiType; + private final String pkg; + private final ResourceKey> registryKey; + private final RegistryKey apiRegistryKey; + private final boolean publicCreateKeyMethod; + + public GeneratedKeyType(final String keysClassName, final Class apiType, final String pkg, final ResourceKey> registryKey, final RegistryKey apiRegistryKey, final boolean publicCreateKeyMethod) { + this.keysClassName = keysClassName; + this.apiType = apiType; + this.pkg = pkg; + this.registryKey = registryKey; + this.apiRegistryKey = apiRegistryKey; + this.publicCreateKeyMethod = publicCreateKeyMethod; + } + + private MethodSpec.Builder createMethod(final TypeName returnType) { + final TypeName keyType = TypeName.get(Key.class).annotated(NOT_NULL); + + final ParameterSpec keyParam = ParameterSpec.builder(keyType, "key", FINAL).build(); + final MethodSpec.Builder create = MethodSpec.methodBuilder("create") + .addModifiers(this.publicCreateKeyMethod ? PUBLIC : PRIVATE, STATIC) + .addParameter(keyParam) + .addCode("return $T.create($T.$L, $N);", TypedKey.class, RegistryKey.class, requireNonNull(REGISTRY_KEY_FIELD_NAMES.get(this.apiRegistryKey), "Missing field for " + this.apiRegistryKey), keyParam) + .returns(returnType.annotated(NOT_NULL)); + if (this.publicCreateKeyMethod) { + create.addAnnotation(EXPERIMENTAL_API_ANNOTATION); // TODO remove once not experimental + create.addJavadoc(CREATE_JAVADOC, this.apiType); + } + return create; + } + + private TypeSpec.Builder keyHolderType() { + return classBuilder(this.keysClassName) + .addModifiers(PUBLIC, FINAL) + .addJavadoc(TYPE_JAVADOC, RegistryKey.class, REGISTRY_KEY_FIELD_NAMES.get(this.apiRegistryKey)) + .addAnnotation(SUPPRESS_WARNINGS).addAnnotation(GENERATED_FROM) + .addMethod(MethodSpec.constructorBuilder() + .addModifiers(PRIVATE) + .build() + ); + } + + protected TypeSpec createTypeSpec() { + final TypeName typedKey = ParameterizedTypeName.get(TypedKey.class, this.apiType); + + final TypeSpec.Builder typeBuilder = this.keyHolderType(); + typeBuilder.addAnnotation(EXPERIMENTAL_API_ANNOTATION); // TODO experimental API + final MethodSpec.Builder createMethod = this.createMethod(typedKey); + + final Registry registry = Main.REGISTRY_ACCESS.registryOrThrow(this.registryKey); + final List> experimental = this.collectExperimentalKeys(registry); + + boolean allExperimental = true; + for (final T value : registry) { + final ResourceKey key = registry.getResourceKey(value).orElseThrow(); + final String keyPath = key.location().getPath(); + final String fieldName = keyPath.toUpperCase(Locale.ENGLISH).replaceAll("[.-/]", "_"); // replace invalid field name chars + final FieldSpec.Builder fieldBuilder = FieldSpec.builder(typedKey, fieldName, PUBLIC, STATIC, FINAL) + .initializer("$N(key($S))", createMethod.build(), keyPath) + .addJavadoc(FIELD_JAVADOC, key.location().toString()); + if (experimental.contains(key)) { + fieldBuilder.addAnnotations(EXPERIMENTAL_ANNOTATIONS); + } else { + allExperimental = false; + } + typeBuilder.addField(fieldBuilder.build()); + } + if (allExperimental) { + typeBuilder.addAnnotations(EXPERIMENTAL_ANNOTATIONS); + createMethod.addAnnotations(EXPERIMENTAL_ANNOTATIONS); + } + return typeBuilder.addMethod(createMethod.build()).build(); + } + + @SuppressWarnings("unchecked") + private List> collectExperimentalKeys(final Registry registry) { + final RegistrySetBuilder.@Nullable RegistryBootstrap registryBootstrap = (RegistrySetBuilder.RegistryBootstrap) EXPERIMENTAL_REGISTRY_ENTRIES.get(this.registryKey); + if (registryBootstrap == null) { + return Collections.emptyList(); + } + final List> experimental = new ArrayList<>(); + final CollectingContext context = new CollectingContext<>(experimental, registry); + registryBootstrap.run(context); + return experimental; + } + + protected JavaFile createFile() { + return JavaFile.builder(this.pkg, this.createTypeSpec()) + .skipJavaLangImports(true) + .addStaticImport(Key.class, "key") + .indent(" ") + .build(); + } + + @Override + public final String outputString() { + return this.createFile().toString(); + } + + @Override + public void writeToFile(final Path parent) throws IOException { + final Path pkgDir = parent.resolve(this.pkg.replace('.', '/')); + Files.createDirectories(pkgDir); + Files.writeString(pkgDir.resolve(this.keysClassName + ".java"), this.outputString(), StandardCharsets.UTF_8); + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/SourceGenerator.java b/paper-api-generator/src/main/java/io/papermc/generator/types/SourceGenerator.java new file mode 100644 index 0000000000..50d176e9ea --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/types/SourceGenerator.java @@ -0,0 +1,11 @@ +package io.papermc.generator.types; + +import java.io.IOException; +import java.nio.file.Path; + +public interface SourceGenerator { + + String outputString(); + + void writeToFile(Path parent) throws IOException; +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/utils/CollectingContext.java b/paper-api-generator/src/main/java/io/papermc/generator/utils/CollectingContext.java new file mode 100644 index 0000000000..98f707846e --- /dev/null +++ b/paper-api-generator/src/main/java/io/papermc/generator/utils/CollectingContext.java @@ -0,0 +1,28 @@ +package io.papermc.generator.utils; + +import com.mojang.serialization.Lifecycle; +import io.papermc.generator.Main; +import java.util.List; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderGetter; +import net.minecraft.core.Registry; +import net.minecraft.data.worldgen.BootstapContext; +import net.minecraft.resources.ResourceKey; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; + +@DefaultQualifier(NonNull.class) +public record CollectingContext(List> registered, + Registry registry) implements BootstapContext { + + @Override + public Holder.Reference register(final ResourceKey resourceKey, final @NonNull T t, final Lifecycle lifecycle) { + this.registered.add(resourceKey); + return Holder.Reference.createStandAlone(this.registry.holderOwner(), resourceKey); + } + + @Override + public HolderGetter lookup(final ResourceKey> resourceKey) { + return Main.REGISTRY_ACCESS.registryOrThrow(resourceKey).asLookup(); + } +} diff --git a/paper-api-generator/wideners.at b/paper-api-generator/wideners.at new file mode 100644 index 0000000000..cc899edd9d --- /dev/null +++ b/paper-api-generator/wideners.at @@ -0,0 +1,6 @@ +accessWidener v1 named +accessible method net/minecraft/server/WorldLoader loadAndReplaceLayer (Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/server/RegistryLayer;Ljava/util/List;)Lnet/minecraft/core/LayeredRegistryAccess; + +# for auto-marking experimental stuff +accessible field net/minecraft/core/RegistrySetBuilder entries Ljava/util/List; +accessible class net/minecraft/core/RegistrySetBuilder$RegistryStub diff --git a/patches/api/Code-Generation.patch b/patches/api/Code-Generation.patch new file mode 100644 index 0000000000..e1696eb316 --- /dev/null +++ b/patches/api/Code-Generation.patch @@ -0,0 +1,251 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Fri, 26 May 2023 18:14:44 -0700 +Subject: [PATCH] Code Generation + +Currently includes generated key holder classes for types +used in the Registry Modification API + +diff --git a/build.gradle.kts b/build.gradle.kts +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ + plugins { + `java-library` + `maven-publish` ++ idea // Paper + } + + java { +@@ -0,0 +0,0 @@ dependencies { + testImplementation("org.ow2.asm:asm-tree:9.5") + } + ++// Paper start ++val generatedApiPath: java.nio.file.Path = rootProject.projectDir.toPath().resolve("paper-api-generator/generated") ++idea { ++ module { ++ generatedSourceDirs.add(generatedApiPath.toFile()) ++ } ++} ++sourceSets { ++ main { ++ java { ++ srcDir(generatedApiPath) ++ } ++ } ++} ++// Paper end ++ + configure { + publications.create("maven") { + from(components["java"]) +@@ -0,0 +0,0 @@ tasks.check { + dependsOn(scanJar) + } + // Paper end ++// Paper start ++val scanJarForOldGeneratedCode = tasks.register("scanJarForOldGeneratedCode", io.papermc.paperweight.tasks.ScanJarForOldGeneratedCode::class) { ++ mcVersion.set(providers.gradleProperty("mcVersion")) ++ annotation.set("Lio/papermc/paper/generated/GeneratedFrom;") ++ jarToScan.set(tasks.jar.flatMap { it.archiveFile }) ++ classpath.from(configurations.compileClasspath) ++} ++tasks.check { ++ dependsOn(scanJarForOldGeneratedCode) ++} ++// Paper end +diff --git a/src/main/java/io/papermc/paper/generated/GeneratedFrom.java b/src/main/java/io/papermc/paper/generated/GeneratedFrom.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/generated/GeneratedFrom.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.generated; ++ ++import java.lang.annotation.Documented; ++import java.lang.annotation.ElementType; ++import java.lang.annotation.Retention; ++import java.lang.annotation.RetentionPolicy; ++import java.lang.annotation.Target; ++import org.jetbrains.annotations.ApiStatus; ++ ++/** ++ * Used to mark classes which are generated from ++ * a specific version of minecraft. ++ */ ++@ApiStatus.Internal ++@Documented ++@Retention(RetentionPolicy.RUNTIME) ++@Target(ElementType.TYPE) ++public @interface GeneratedFrom { ++ ++ String value(); ++} +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.kyori.adventure.key.Keyed; ++import org.bukkit.GameEvent; ++import org.bukkit.block.Biome; ++import org.bukkit.generator.structure.StructureType; ++import org.bukkit.inventory.meta.trim.TrimMaterial; ++import org.bukkit.inventory.meta.trim.TrimPattern; ++import org.jetbrains.annotations.ApiStatus; ++ ++import static io.papermc.paper.registry.RegistryKeyImpl.create; ++ ++/** ++ * Identifier for a specific registry. For use with ++ * {@link TypedKey} and the registry modification API. ++ *

++ * There are 2 types of registries, identified as "built-in" ++ * or "data-driven". The former are not changeable by datapacks (which ++ * doesn't necessarily mean they aren't changeable in the API) and ++ * are loaded first. "Data-driven" registries are all created by ++ * reading in data from the vanilla and other datapacks. ++ * ++ * @param the value type ++ */ ++@SuppressWarnings("unused") ++@ApiStatus.Experimental ++public sealed interface RegistryKey extends Keyed permits RegistryKeyImpl { ++ ++ /* ******************* * ++ * Built-in Registries * ++ * ******************* */ ++ /** ++ * Built-in registry for game events ++ * @see io.papermc.paper.registry.keys.GameEventKeys ++ */ ++ RegistryKey GAME_EVENT = create("game_event"); ++ /** ++ * Built-in registry for structure types. ++ * @see io.papermc.paper.registry.keys.StructureTypeKeys ++ */ ++ RegistryKey STRUCTURE_TYPE = create("worldgen/structure_type"); ++ ++ /* ********************** * ++ * Data-driven Registries * ++ * ********************** */ ++ /** ++ * Data-driven registry for structure types. ++ * @see io.papermc.paper.registry.keys.BiomeKeys ++ */ ++ RegistryKey BIOME = create("worldgen/biome"); ++ /** ++ * Data-driven registry for structure types. ++ * @see io.papermc.paper.registry.keys.TrimMaterialKeys ++ */ ++ RegistryKey TRIM_MATERIAL = create("trim_material"); ++ /** ++ * Data-driven registry for structure types. ++ * @see io.papermc.paper.registry.keys.TrimPatternKeys ++ */ ++ RegistryKey TRIM_PATTERN = create("trim_pattern"); ++} +diff --git a/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import com.google.common.collect.Sets; ++import java.util.Set; ++import net.kyori.adventure.key.Key; ++import org.intellij.lang.annotations.Subst; ++import org.jetbrains.annotations.NotNull; ++ ++record RegistryKeyImpl(@NotNull Key key) implements RegistryKey { ++ ++ static final Set> REGISTRY_KEYS = Sets.newIdentityHashSet(); ++ ++ static RegistryKey create(@Subst("some_key") final String key) { ++ final RegistryKey registryKey = new RegistryKeyImpl<>(Key.key(Key.MINECRAFT_NAMESPACE, key)); ++ REGISTRY_KEYS.add(registryKey); ++ return registryKey; ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/registry/TypedKey.java b/src/main/java/io/papermc/paper/registry/TypedKey.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/TypedKey.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.key.Keyed; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Represents a key for a value in a specific registry. ++ * ++ * @param the value type for the registry ++ */ ++@ApiStatus.Experimental ++public sealed interface TypedKey extends Keyed permits TypedKeyImpl { ++ ++ /** ++ * Gets the key for the value in the registry. ++ * ++ * @return the value's key ++ */ ++ @Override ++ @NotNull Key key(); ++ ++ /** ++ * Gets the registry key for the value this key ++ * represents. ++ * ++ * @return the registry key ++ */ ++ @NotNull RegistryKey registryKey(); ++ ++ /** ++ * Create a typed key from a key and a registry key. ++ * ++ * @param registryKey the registry this key is for ++ * @param key the key for the value in the registry ++ * @param value type ++ * @return a new key for the value key and registry key ++ */ ++ @ApiStatus.Experimental ++ static @NotNull TypedKey create(final @NotNull RegistryKey registryKey, final @NotNull Key key) { ++ return new TypedKeyImpl<>(key, registryKey); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.key.Keyed; ++import org.jetbrains.annotations.NotNull; ++ ++record TypedKeyImpl(@NotNull Key key, @NotNull RegistryKey registryKey) implements TypedKey { ++} +diff --git a/src/main/java/org/bukkit/MinecraftExperimental.java b/src/main/java/org/bukkit/MinecraftExperimental.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/MinecraftExperimental.java ++++ b/src/main/java/org/bukkit/MinecraftExperimental.java +@@ -0,0 +0,0 @@ import org.jetbrains.annotations.ApiStatus; + }) + @ApiStatus.Internal + public @interface MinecraftExperimental { ++ String value() default ""; // Paper + } diff --git a/patches/server/Test-changes.patch b/patches/server/Test-changes.patch index b97f51695f..2c05e96619 100644 --- a/patches/server/Test-changes.patch +++ b/patches/server/Test-changes.patch @@ -21,6 +21,45 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 publishing { publications.create("maven") { artifact(tasks.shadowJar) +diff --git a/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java b/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import java.util.Optional; ++import java.util.stream.Stream; ++import net.minecraft.core.Registry; ++import net.minecraft.resources.ResourceKey; ++import net.minecraft.resources.ResourceLocation; ++import org.bukkit.support.AbstractTestingBase; ++import org.junit.jupiter.api.BeforeAll; ++import org.junit.jupiter.params.ParameterizedTest; ++import org.junit.jupiter.params.provider.MethodSource; ++ ++import static org.junit.jupiter.api.Assertions.assertTrue; ++ ++class RegistryKeyTest extends AbstractTestingBase { ++ ++ @BeforeAll ++ static void before() throws ClassNotFoundException { ++ Class.forName(RegistryKey.class.getName()); // load all keys so they are found for the test ++ } ++ ++ static Stream> data() { ++ return RegistryKeyImpl.REGISTRY_KEYS.stream(); ++ } ++ ++ @ParameterizedTest ++ @MethodSource("data") ++ void testApiRegistryKeysExist(final RegistryKey key) { ++ final Optional> registry = AbstractTestingBase.REGISTRY_CUSTOM.registry(ResourceKey.createRegistryKey(new ResourceLocation(key.key().asString()))); ++ assertTrue(registry.isPresent(), "Missing vanilla registry for " + key.key().asString()); ++ ++ } ++} diff --git a/src/test/java/io/papermc/paper/util/EmptyTag.java b/src/test/java/io/papermc/paper/util/EmptyTag.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 diff --git a/settings.gradle.kts b/settings.gradle.kts index e8d0e3de4c..f6aac1f56c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,9 +39,19 @@ for (name in listOf("Paper-API", "Paper-Server", "Paper-MojangAPI")) { findProject(":$projName")!!.projectDir = file(name) } -val testPlugin = file("test-plugin.settings.gradle.kts") -if (testPlugin.exists()) { - apply(from = testPlugin) -} else { - testPlugin.writeText("// Uncomment to enable the test plugin module\n//include(\":test-plugin\")\n") +mapOf("test-plugin.settings.gradle.kts" to """ + // Uncomment to enable the test plugin module + // include(":test-plugin") + """.trimIndent(), + "paper-api-generator.settings.gradle.kts" to """ + // Uncomment to enable the api generator module + // include(":paper-api-generator") + """.trimIndent() +).forEach { (fileName, text) -> + val settingsFile = file(fileName) + if (settingsFile.exists()) { + apply(from = settingsFile) + } else { + settingsFile.writeText(text + "\n") + } }