diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/DamageTypeKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/DamageTypeKeys.java new file mode 100644 index 0000000000..ed52d2393e --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/DamageTypeKeys.java @@ -0,0 +1,367 @@ +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.MinecraftExperimental; +import org.bukkit.damage.DamageType; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Vanilla keys for {@link RegistryKey#DAMAGE_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.6") +@ApiStatus.Experimental +public final class DamageTypeKeys { + /** + * {@code minecraft:arrow} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ARROW = create(key("arrow")); + + /** + * {@code minecraft:bad_respawn_point} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAD_RESPAWN_POINT = create(key("bad_respawn_point")); + + /** + * {@code minecraft:cactus} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CACTUS = create(key("cactus")); + + /** + * {@code minecraft:cramming} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CRAMMING = create(key("cramming")); + + /** + * {@code minecraft:dragon_breath} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRAGON_BREATH = create(key("dragon_breath")); + + /** + * {@code minecraft:drown} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DROWN = create(key("drown")); + + /** + * {@code minecraft:dry_out} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DRY_OUT = create(key("dry_out")); + + /** + * {@code minecraft:explosion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EXPLOSION = create(key("explosion")); + + /** + * {@code minecraft:fall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FALL = create(key("fall")); + + /** + * {@code minecraft:falling_anvil} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FALLING_ANVIL = create(key("falling_anvil")); + + /** + * {@code minecraft:falling_block} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FALLING_BLOCK = create(key("falling_block")); + + /** + * {@code minecraft:falling_stalactite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FALLING_STALACTITE = create(key("falling_stalactite")); + + /** + * {@code minecraft:fireball} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIREBALL = create(key("fireball")); + + /** + * {@code minecraft:fireworks} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIREWORKS = create(key("fireworks")); + + /** + * {@code minecraft:fly_into_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLY_INTO_WALL = create(key("fly_into_wall")); + + /** + * {@code minecraft:freeze} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FREEZE = create(key("freeze")); + + /** + * {@code minecraft:generic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GENERIC = create(key("generic")); + + /** + * {@code minecraft:generic_kill} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GENERIC_KILL = create(key("generic_kill")); + + /** + * {@code minecraft:hot_floor} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HOT_FLOOR = create(key("hot_floor")); + + /** + * {@code minecraft:in_fire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IN_FIRE = create(key("in_fire")); + + /** + * {@code minecraft:in_wall} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IN_WALL = create(key("in_wall")); + + /** + * {@code minecraft:indirect_magic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INDIRECT_MAGIC = create(key("indirect_magic")); + + /** + * {@code minecraft:lava} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LAVA = create(key("lava")); + + /** + * {@code minecraft:lightning_bolt} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LIGHTNING_BOLT = create(key("lightning_bolt")); + + /** + * {@code minecraft:magic} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MAGIC = create(key("magic")); + + /** + * {@code minecraft:mob_attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOB_ATTACK = create(key("mob_attack")); + + /** + * {@code minecraft:mob_attack_no_aggro} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOB_ATTACK_NO_AGGRO = create(key("mob_attack_no_aggro")); + + /** + * {@code minecraft:mob_projectile} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MOB_PROJECTILE = create(key("mob_projectile")); + + /** + * {@code minecraft:on_fire} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ON_FIRE = create(key("on_fire")); + + /** + * {@code minecraft:out_of_world} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OUT_OF_WORLD = create(key("out_of_world")); + + /** + * {@code minecraft:outside_border} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey OUTSIDE_BORDER = create(key("outside_border")); + + /** + * {@code minecraft:player_attack} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAYER_ATTACK = create(key("player_attack")); + + /** + * {@code minecraft:player_explosion} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PLAYER_EXPLOSION = create(key("player_explosion")); + + /** + * {@code minecraft:sonic_boom} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SONIC_BOOM = create(key("sonic_boom")); + + /** + * {@code minecraft:spit} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPIT = create(key("spit")); + + /** + * {@code minecraft:stalagmite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STALAGMITE = create(key("stalagmite")); + + /** + * {@code minecraft:starve} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STARVE = create(key("starve")); + + /** + * {@code minecraft:sting} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STING = create(key("sting")); + + /** + * {@code minecraft:sweet_berry_bush} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWEET_BERRY_BUSH = create(key("sweet_berry_bush")); + + /** + * {@code minecraft:thorns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey THORNS = create(key("thorns")); + + /** + * {@code minecraft:thrown} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey THROWN = create(key("thrown")); + + /** + * {@code minecraft:trident} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey TRIDENT = create(key("trident")); + + /** + * {@code minecraft:unattributed_fireball} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UNATTRIBUTED_FIREBALL = create(key("unattributed_fireball")); + + /** + * {@code minecraft:wind_charge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.UPDATE_1_21) + public static final TypedKey WIND_CHARGE = create(key("wind_charge")); + + /** + * {@code minecraft:wither} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER = create(key("wither")); + + /** + * {@code minecraft:wither_skull} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER_SKULL = create(key("wither_skull")); + + private DamageTypeKeys() { + } + + /** + * Creates a key for {@link DamageType} 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.DAMAGE_TYPE, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/EnchantmentKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/EnchantmentKeys.java new file mode 100644 index 0000000000..3c64bc0790 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/EnchantmentKeys.java @@ -0,0 +1,336 @@ +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.MinecraftExperimental; +import org.bukkit.enchantments.Enchantment; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Vanilla keys for {@link RegistryKey#ENCHANTMENT}. + * + * @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.6") +@ApiStatus.Experimental +public final class EnchantmentKeys { + /** + * {@code minecraft:aqua_affinity} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey AQUA_AFFINITY = create(key("aqua_affinity")); + + /** + * {@code minecraft:bane_of_arthropods} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BANE_OF_ARTHROPODS = create(key("bane_of_arthropods")); + + /** + * {@code minecraft:binding_curse} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BINDING_CURSE = create(key("binding_curse")); + + /** + * {@code minecraft:blast_protection} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLAST_PROTECTION = create(key("blast_protection")); + + /** + * {@code minecraft:breach} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.UPDATE_1_21) + public static final TypedKey BREACH = create(key("breach")); + + /** + * {@code minecraft:channeling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHANNELING = create(key("channeling")); + + /** + * {@code minecraft:density} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.UPDATE_1_21) + public static final TypedKey DENSITY = create(key("density")); + + /** + * {@code minecraft:depth_strider} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DEPTH_STRIDER = create(key("depth_strider")); + + /** + * {@code minecraft:efficiency} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey EFFICIENCY = create(key("efficiency")); + + /** + * {@code minecraft:feather_falling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FEATHER_FALLING = create(key("feather_falling")); + + /** + * {@code minecraft:fire_aspect} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_ASPECT = create(key("fire_aspect")); + + /** + * {@code minecraft:fire_protection} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_PROTECTION = create(key("fire_protection")); + + /** + * {@code minecraft:flame} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FLAME = create(key("flame")); + + /** + * {@code minecraft:fortune} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FORTUNE = create(key("fortune")); + + /** + * {@code minecraft:frost_walker} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FROST_WALKER = create(key("frost_walker")); + + /** + * {@code minecraft:impaling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey IMPALING = create(key("impaling")); + + /** + * {@code minecraft:infinity} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INFINITY = create(key("infinity")); + + /** + * {@code minecraft:knockback} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey KNOCKBACK = create(key("knockback")); + + /** + * {@code minecraft:looting} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LOOTING = create(key("looting")); + + /** + * {@code minecraft:loyalty} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LOYALTY = create(key("loyalty")); + + /** + * {@code minecraft:luck_of_the_sea} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LUCK_OF_THE_SEA = create(key("luck_of_the_sea")); + + /** + * {@code minecraft:lure} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LURE = create(key("lure")); + + /** + * {@code minecraft:mending} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MENDING = create(key("mending")); + + /** + * {@code minecraft:multishot} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MULTISHOT = create(key("multishot")); + + /** + * {@code minecraft:piercing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PIERCING = create(key("piercing")); + + /** + * {@code minecraft:power} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POWER = create(key("power")); + + /** + * {@code minecraft:projectile_protection} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PROJECTILE_PROTECTION = create(key("projectile_protection")); + + /** + * {@code minecraft:protection} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PROTECTION = create(key("protection")); + + /** + * {@code minecraft:punch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PUNCH = create(key("punch")); + + /** + * {@code minecraft:quick_charge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey QUICK_CHARGE = create(key("quick_charge")); + + /** + * {@code minecraft:respiration} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESPIRATION = create(key("respiration")); + + /** + * {@code minecraft:riptide} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RIPTIDE = create(key("riptide")); + + /** + * {@code minecraft:sharpness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SHARPNESS = create(key("sharpness")); + + /** + * {@code minecraft:silk_touch} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SILK_TOUCH = create(key("silk_touch")); + + /** + * {@code minecraft:smite} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SMITE = create(key("smite")); + + /** + * {@code minecraft:soul_speed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SOUL_SPEED = create(key("soul_speed")); + + /** + * {@code minecraft:sweeping_edge} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWEEPING_EDGE = create(key("sweeping_edge")); + + /** + * {@code minecraft:swift_sneak} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SWIFT_SNEAK = create(key("swift_sneak")); + + /** + * {@code minecraft:thorns} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey THORNS = create(key("thorns")); + + /** + * {@code minecraft:unbreaking} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UNBREAKING = create(key("unbreaking")); + + /** + * {@code minecraft:vanishing_curse} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey VANISHING_CURSE = create(key("vanishing_curse")); + + /** + * {@code minecraft:wind_burst} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.UPDATE_1_21) + public static final TypedKey WIND_BURST = create(key("wind_burst")); + + private EnchantmentKeys() { + } + + private static @NotNull TypedKey create(final @NotNull Key key) { + return TypedKey.create(RegistryKey.ENCHANTMENT, 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 index f220c63b8a..6d228f2f02 100644 --- a/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java @@ -449,14 +449,7 @@ public final class GameEventKeys { 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) { + private 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/InstrumentKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/InstrumentKeys.java new file mode 100644 index 0000000000..0cddaa1936 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/InstrumentKeys.java @@ -0,0 +1,91 @@ +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.MusicInstrument; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Vanilla keys for {@link RegistryKey#INSTRUMENT}. + * + * @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.6") +@ApiStatus.Experimental +public final class InstrumentKeys { + /** + * {@code minecraft:admire_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ADMIRE_GOAT_HORN = create(key("admire_goat_horn")); + + /** + * {@code minecraft:call_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CALL_GOAT_HORN = create(key("call_goat_horn")); + + /** + * {@code minecraft:dream_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DREAM_GOAT_HORN = create(key("dream_goat_horn")); + + /** + * {@code minecraft:feel_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FEEL_GOAT_HORN = create(key("feel_goat_horn")); + + /** + * {@code minecraft:ponder_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PONDER_GOAT_HORN = create(key("ponder_goat_horn")); + + /** + * {@code minecraft:seek_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SEEK_GOAT_HORN = create(key("seek_goat_horn")); + + /** + * {@code minecraft:sing_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SING_GOAT_HORN = create(key("sing_goat_horn")); + + /** + * {@code minecraft:yearn_goat_horn} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey YEARN_GOAT_HORN = create(key("yearn_goat_horn")); + + private InstrumentKeys() { + } + + private static @NotNull TypedKey create(final @NotNull Key key) { + return TypedKey.create(RegistryKey.INSTRUMENT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/MobEffectKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/MobEffectKeys.java new file mode 100644 index 0000000000..83835bd7ff --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/MobEffectKeys.java @@ -0,0 +1,321 @@ +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.MinecraftExperimental; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Vanilla keys for {@link RegistryKey#MOB_EFFECT}. + * + * @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.6") +@ApiStatus.Experimental +public final class MobEffectKeys { + /** + * {@code minecraft:absorption} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ABSORPTION = create(key("absorption")); + + /** + * {@code minecraft:bad_omen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BAD_OMEN = create(key("bad_omen")); + + /** + * {@code minecraft:blindness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLINDNESS = create(key("blindness")); + + /** + * {@code minecraft:conduit_power} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CONDUIT_POWER = create(key("conduit_power")); + + /** + * {@code minecraft:darkness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DARKNESS = create(key("darkness")); + + /** + * {@code minecraft:dolphins_grace} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey DOLPHINS_GRACE = create(key("dolphins_grace")); + + /** + * {@code minecraft:fire_resistance} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey FIRE_RESISTANCE = create(key("fire_resistance")); + + /** + * {@code minecraft:glowing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey GLOWING = create(key("glowing")); + + /** + * {@code minecraft:haste} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HASTE = create(key("haste")); + + /** + * {@code minecraft:health_boost} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HEALTH_BOOST = create(key("health_boost")); + + /** + * {@code minecraft:hero_of_the_village} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HERO_OF_THE_VILLAGE = create(key("hero_of_the_village")); + + /** + * {@code minecraft:hunger} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey HUNGER = create(key("hunger")); + + /** + * {@code minecraft:infested} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.UPDATE_1_21) + public static final TypedKey INFESTED = create(key("infested")); + + /** + * {@code minecraft:instant_damage} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INSTANT_DAMAGE = create(key("instant_damage")); + + /** + * {@code minecraft:instant_health} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INSTANT_HEALTH = create(key("instant_health")); + + /** + * {@code minecraft:invisibility} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey INVISIBILITY = create(key("invisibility")); + + /** + * {@code minecraft:jump_boost} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey JUMP_BOOST = create(key("jump_boost")); + + /** + * {@code minecraft:levitation} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LEVITATION = create(key("levitation")); + + /** + * {@code minecraft:luck} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey LUCK = create(key("luck")); + + /** + * {@code minecraft:mining_fatigue} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey MINING_FATIGUE = create(key("mining_fatigue")); + + /** + * {@code minecraft:nausea} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NAUSEA = create(key("nausea")); + + /** + * {@code minecraft:night_vision} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey NIGHT_VISION = create(key("night_vision")); + + /** + * {@code minecraft:oozing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.UPDATE_1_21) + public static final TypedKey OOZING = create(key("oozing")); + + /** + * {@code minecraft:poison} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey POISON = create(key("poison")); + + /** + * {@code minecraft:raid_omen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.UPDATE_1_21) + public static final TypedKey RAID_OMEN = create(key("raid_omen")); + + /** + * {@code minecraft:regeneration} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey REGENERATION = create(key("regeneration")); + + /** + * {@code minecraft:resistance} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RESISTANCE = create(key("resistance")); + + /** + * {@code minecraft:saturation} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SATURATION = create(key("saturation")); + + /** + * {@code minecraft:slow_falling} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SLOW_FALLING = create(key("slow_falling")); + + /** + * {@code minecraft:slowness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SLOWNESS = create(key("slowness")); + + /** + * {@code minecraft:speed} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPEED = create(key("speed")); + + /** + * {@code minecraft:strength} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRENGTH = create(key("strength")); + + /** + * {@code minecraft:trial_omen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.UPDATE_1_21) + public static final TypedKey TRIAL_OMEN = create(key("trial_omen")); + + /** + * {@code minecraft:unluck} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey UNLUCK = create(key("unluck")); + + /** + * {@code minecraft:water_breathing} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WATER_BREATHING = create(key("water_breathing")); + + /** + * {@code minecraft:weakness} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WEAKNESS = create(key("weakness")); + + /** + * {@code minecraft:weaving} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.UPDATE_1_21) + public static final TypedKey WEAVING = create(key("weaving")); + + /** + * {@code minecraft:wind_charged} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + @ApiStatus.Experimental + @MinecraftExperimental(MinecraftExperimental.Requires.UPDATE_1_21) + public static final TypedKey WIND_CHARGED = create(key("wind_charged")); + + /** + * {@code minecraft:wither} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WITHER = create(key("wither")); + + private MobEffectKeys() { + } + + private static @NotNull TypedKey create(final @NotNull Key key) { + return TypedKey.create(RegistryKey.MOB_EFFECT, key); + } +} diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/WolfVariantKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/WolfVariantKeys.java new file mode 100644 index 0000000000..5ae854aba8 --- /dev/null +++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/WolfVariantKeys.java @@ -0,0 +1,105 @@ +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.entity.Wolf; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Vanilla keys for {@link RegistryKey#WOLF_VARIANT}. + * + * @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.6") +@ApiStatus.Experimental +public final class WolfVariantKeys { + /** + * {@code minecraft:ashen} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey ASHEN = create(key("ashen")); + + /** + * {@code minecraft:black} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey BLACK = create(key("black")); + + /** + * {@code minecraft:chestnut} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey CHESTNUT = create(key("chestnut")); + + /** + * {@code minecraft:pale} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey PALE = create(key("pale")); + + /** + * {@code minecraft:rusty} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey RUSTY = create(key("rusty")); + + /** + * {@code minecraft:snowy} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SNOWY = create(key("snowy")); + + /** + * {@code minecraft:spotted} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey SPOTTED = create(key("spotted")); + + /** + * {@code minecraft:striped} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey STRIPED = create(key("striped")); + + /** + * {@code minecraft:woods} + * + * @apiNote This field is version-dependant and may be removed in future Minecraft versions + */ + public static final TypedKey WOODS = create(key("woods")); + + private WolfVariantKeys() { + } + + /** + * Creates a key for {@link Wolf.Variant} 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.WOLF_VARIANT, key); + } +} diff --git a/paper-api-generator/src/main/java/io/papermc/generator/Generators.java b/paper-api-generator/src/main/java/io/papermc/generator/Generators.java index ac62e26e93..4afed26dd5 100644 --- a/paper-api-generator/src/main/java/io/papermc/generator/Generators.java +++ b/paper-api-generator/src/main/java/io/papermc/generator/Generators.java @@ -8,21 +8,31 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import org.bukkit.GameEvent; +import org.bukkit.MusicInstrument; import org.bukkit.block.Biome; +import org.bukkit.damage.DamageType; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Wolf; import org.bukkit.generator.structure.Structure; import org.bukkit.generator.structure.StructureType; import org.bukkit.inventory.meta.trim.TrimMaterial; import org.bukkit.inventory.meta.trim.TrimPattern; +import org.bukkit.potion.PotionEffectType; public interface Generators { SourceGenerator[] API = { - simpleKey("GameEventKeys", GameEvent.class, Registries.GAME_EVENT, RegistryKey.GAME_EVENT, true), + simpleKey("GameEventKeys", GameEvent.class, Registries.GAME_EVENT, RegistryKey.GAME_EVENT, false), 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("StructureKeys", Structure.class, Registries.STRUCTURE, RegistryKey.STRUCTURE, true), simpleKey("StructureTypeKeys", StructureType.class, Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE, false), + simpleKey("InstrumentKeys", MusicInstrument.class, Registries.INSTRUMENT, RegistryKey.INSTRUMENT, false), + simpleKey("EnchantmentKeys", Enchantment.class, Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, false), + simpleKey("MobEffectKeys", PotionEffectType.class, Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT, false), + simpleKey("DamageTypeKeys", DamageType.class, Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE, true), + simpleKey("WolfVariantKeys", Wolf.Variant.class, Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT, true), new MobGoalGenerator("VanillaGoal", "com.destroystokyo.paper.entity.ai") }; 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 index 66c4a4b14f..8307fcad4c 100644 --- 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 @@ -25,11 +25,14 @@ import java.util.Set; import java.util.stream.Collectors; import net.kyori.adventure.key.Key; import net.minecraft.core.Holder; +import net.minecraft.core.HolderLookup; import net.minecraft.core.Registry; import net.minecraft.core.RegistrySetBuilder; import net.minecraft.data.registries.UpdateOneTwentyOneRegistries; import net.minecraft.data.registries.VanillaRegistries; import net.minecraft.resources.ResourceKey; +import net.minecraft.world.flag.FeatureElement; +import net.minecraft.world.flag.FeatureFlags; import org.bukkit.MinecraftExperimental; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -151,8 +154,23 @@ public class GeneratedKeyType extends SimpleGenerator { return typeBuilder.addMethod(createMethod.build()).build(); } - @SuppressWarnings("unchecked") private Set> collectExperimentalKeys(final Registry registry) { + if (FeatureElement.FILTERED_REGISTRIES.contains(registry.key())) { + return this.collectExperimentalKeysBuiltIn(registry); + } else { + return this.collectExperimentalKeysDataDriven(registry); + } + } + + private Set> collectExperimentalKeysBuiltIn(final Registry registry) { + final HolderLookup.RegistryLookup filteredLookup = registry.asLookup().filterElements(v -> { + return ((FeatureElement) v).requiredFeatures().contains(FeatureFlags.UPDATE_1_21); + }); + return filteredLookup.listElementIds().collect(Collectors.toUnmodifiableSet()); + } + + @SuppressWarnings("unchecked") + private Set> collectExperimentalKeysDataDriven(final Registry registry) { final RegistrySetBuilder.@Nullable RegistryBootstrap experimentalBootstrap = (RegistrySetBuilder.RegistryBootstrap) EXPERIMENTAL_REGISTRY_ENTRIES.get(this.registryKey); if (experimentalBootstrap == null) { return Collections.emptySet(); diff --git a/patches/api/Add-PaperRegistry.patch b/patches/api/Add-PaperRegistry.patch deleted file mode 100644 index dbc8697ebd..0000000000 --- a/patches/api/Add-PaperRegistry.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Mar 2022 13:36:21 -0800 -Subject: [PATCH] Add PaperRegistry - - -diff --git a/src/main/java/io/papermc/paper/registry/Reference.java b/src/main/java/io/papermc/paper/registry/Reference.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/registry/Reference.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.registry; -+ -+import org.bukkit.Keyed; -+import org.bukkit.NamespacedKey; -+import org.bukkit.Registry; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+/** -+ * Represents a reference to a server-backed registry value that may -+ * change. -+ * -+ * @param type of the value -+ */ -+public interface Reference extends Keyed { -+ -+ /** -+ * Gets the value from the registry with the key. -+ * -+ * @return the value -+ * @throws java.util.NoSuchElementException if there is no value with this key -+ */ -+ @NotNull T value(); -+ -+ /** -+ * Gets the value from the registry with the key. -+ * -+ * @return the value or null if it doesn't exist -+ */ -+ @Nullable T valueOrNull(); -+ -+ /** -+ * Creates a reference to a registered value. -+ * -+ * @param registry the registry the value is located in -+ * @param key the key to the value -+ * @param the type of the value -+ * @return a reference -+ */ -+ static @NotNull Reference create(@NotNull Registry registry, @NotNull NamespacedKey key) { -+ return new ReferenceImpl<>(registry, key); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/registry/ReferenceImpl.java b/src/main/java/io/papermc/paper/registry/ReferenceImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/registry/ReferenceImpl.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.registry; -+ -+import org.bukkit.Keyed; -+import org.bukkit.NamespacedKey; -+import org.bukkit.Registry; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import java.util.NoSuchElementException; -+ -+record ReferenceImpl(@NotNull Registry registry, @NotNull NamespacedKey key) implements Reference { -+ -+ @Override -+ public @NotNull T value() { -+ final T value = this.registry.get(this.key); -+ if (value == null) { -+ throw new NoSuchElementException("No such value with key " + this.key); -+ } -+ return value; -+ } -+ -+ @Override -+ public @Nullable T valueOrNull() { -+ return this.registry.get(this.key); -+ } -+ -+ @Override -+ public @NotNull NamespacedKey getKey() { -+ return this.key; -+ } -+} diff --git a/patches/api/Add-RegistryAccess-for-managing-registries.patch b/patches/api/Add-RegistryAccess-for-managing-registries.patch new file mode 100644 index 0000000000..3965dd7f1d --- /dev/null +++ b/patches/api/Add-RegistryAccess-for-managing-registries.patch @@ -0,0 +1,394 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 2 Mar 2022 13:36:21 -0800 +Subject: [PATCH] Add RegistryAccess for managing registries + + +diff --git a/src/main/java/io/papermc/paper/registry/Reference.java b/src/main/java/io/papermc/paper/registry/Reference.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/Reference.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import org.bukkit.Keyed; ++import org.bukkit.NamespacedKey; ++import org.bukkit.Registry; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Represents a reference to a server-backed registry value that may ++ * change. ++ * ++ * @param type of the value ++ */ ++@Deprecated(forRemoval = true, since = "1.20.6") ++public interface Reference extends Keyed { ++ ++ /** ++ * Gets the value from the registry with the key. ++ * ++ * @return the value ++ * @throws java.util.NoSuchElementException if there is no value with this key ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.6") ++ @NotNull T value(); ++ ++ /** ++ * Gets the value from the registry with the key. ++ * ++ * @return the value or null if it doesn't exist ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.6") ++ @Nullable T valueOrNull(); ++ ++ /** ++ * Creates a reference to a registered value. ++ * ++ * @param registry the registry the value is located in ++ * @param key the key to the value ++ * @param the type of the value ++ * @return a reference ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.6") ++ static @NotNull Reference create(@NotNull Registry registry, @NotNull NamespacedKey key) { ++ return new ReferenceImpl<>(registry, key); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/ReferenceImpl.java b/src/main/java/io/papermc/paper/registry/ReferenceImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/ReferenceImpl.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import org.bukkit.Keyed; ++import org.bukkit.NamespacedKey; ++import org.bukkit.Registry; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.NoSuchElementException; ++ ++record ReferenceImpl(@NotNull Registry registry, @NotNull NamespacedKey key) implements Reference { ++ ++ @Override ++ public @NotNull T value() { ++ final T value = this.registry.get(this.key); ++ if (value == null) { ++ throw new NoSuchElementException("No such value with key " + this.key); ++ } ++ return value; ++ } ++ ++ @Override ++ public @Nullable T valueOrNull() { ++ return this.registry.get(this.key); ++ } ++ ++ @Override ++ public @NotNull NamespacedKey getKey() { ++ return this.key; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/RegistryAccess.java b/src/main/java/io/papermc/paper/registry/RegistryAccess.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/RegistryAccess.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import org.bukkit.Keyed; ++import org.bukkit.Registry; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Used for accessing different {@link Registry} instances ++ * by a {@link RegistryKey}. Get the main instance of {@link RegistryAccess} ++ * with {@link RegistryAccess#registryAccess()}. ++ */ ++@ApiStatus.NonExtendable ++public interface RegistryAccess { ++ ++ /** ++ * Get the {@link RegistryAccess} instance for the server. ++ * ++ * @return the RegistryAccess instance ++ */ ++ static @NotNull RegistryAccess registryAccess() { ++ return RegistryAccessHolder.INSTANCE.orElseThrow(() -> new IllegalStateException("No RegistryAccess implementation found")); ++ } ++ ++ /** ++ * Gets the registry based on the type. ++ * ++ * @param type the type ++ * @return the registry or null if none found ++ * @param the type ++ * @deprecated use {@link #getRegistry(RegistryKey)} with keys from {@link RegistryKey} ++ */ ++ @Deprecated(since = "1.20.6", forRemoval = true) ++ @Nullable Registry getRegistry(@NotNull Class type); ++ ++ /** ++ * Gets the registry with the specified key. ++ * ++ * @param registryKey the key ++ * @return the registry ++ * @param the type ++ * @throws java.util.NoSuchElementException if no registry with the key is found ++ * @throws IllegalArgumentException if the registry is not available yet ++ */ ++ // Future note: We should have no trouble removing this generic qualifier when ++ // registry types no longer have to be "keyed" as it shouldn't break ABI or API. ++ @NotNull Registry getRegistry(@NotNull RegistryKey registryKey); ++} +diff --git a/src/main/java/io/papermc/paper/registry/RegistryAccessHolder.java b/src/main/java/io/papermc/paper/registry/RegistryAccessHolder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/RegistryAccessHolder.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import java.util.Optional; ++import java.util.ServiceLoader; ++ ++final class RegistryAccessHolder { ++ ++ static final Optional INSTANCE = ServiceLoader.load(RegistryAccess.class).findFirst(); ++ ++ private RegistryAccessHolder() { ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java ++++ b/src/main/java/io/papermc/paper/registry/RegistryKeyImpl.java +@@ -0,0 +0,0 @@ record RegistryKeyImpl(@NotNull Key key) implements RegistryKey { + + static final Set> REGISTRY_KEYS = Sets.newIdentityHashSet(); + ++ // override equals and hashCode to this can be used to simulate an "identity" hashmap ++ @Override ++ public boolean equals(final Object obj) { ++ return obj == this; ++ } ++ ++ @Override ++ public int hashCode() { ++ return System.identityHashCode(this); ++ } ++ + static RegistryKey create(@Subst("some_key") final String key) { + final RegistryKey registryKey = createInternal(key); + REGISTRY_KEYS.add(registryKey); +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -0,0 +0,0 @@ public final class Bukkit { + * @param tClass of the registry to get + * @param type of the registry + * @return the corresponding registry or null if not present ++ * @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} ++ * with keys from {@link io.papermc.paper.registry.RegistryKey} + */ + @Nullable ++ @Deprecated(since = "1.20.6") + public static Registry getRegistry(@NotNull Class tClass) { + return server.getRegistry(tClass); + } +diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/Registry.java ++++ b/src/main/java/org/bukkit/Registry.java +@@ -0,0 +0,0 @@ public interface Registry extends Iterable { + * + * @see Enchantment + */ +- Registry ENCHANTMENT = Objects.requireNonNull(Bukkit.getRegistry(Enchantment.class), "No registry present for Enchantment. This is a bug."); ++ Registry ENCHANTMENT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.ENCHANTMENT); // Paper + /** + * Server entity types. + * +@@ -0,0 +0,0 @@ public interface Registry extends Iterable { + * + * @see MusicInstrument + */ +- Registry INSTRUMENT = Objects.requireNonNull(Bukkit.getRegistry(MusicInstrument.class), "No registry present for MusicInstrument. This is a bug."); ++ Registry INSTRUMENT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.INSTRUMENT); // Paper + /** + * Default server loot tables. + * +@@ -0,0 +0,0 @@ public interface Registry extends Iterable { + * + * @see PotionEffectType + */ +- Registry EFFECT = Objects.requireNonNull(Bukkit.getRegistry(PotionEffectType.class), "No registry present for PotionEffectType. This is a bug."); ++ Registry EFFECT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.MOB_EFFECT); // Paper + /** + * Server particles. + * +@@ -0,0 +0,0 @@ public interface Registry extends Iterable { + * Server structures. + * + * @see Structure ++ * @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#STRUCTURE} + */ +- Registry STRUCTURE = Bukkit.getRegistry(Structure.class); ++ @Deprecated(since = "1.20.6") // Paper ++ Registry STRUCTURE = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(Structure.class), "No registry present for Structure. This is a bug."); // Paper + /** + * Server structure types. + * + * @see StructureType + */ +- Registry STRUCTURE_TYPE = Bukkit.getRegistry(StructureType.class); ++ Registry STRUCTURE_TYPE = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.STRUCTURE_TYPE); // Paper + /** + * Sound keys. + * +@@ -0,0 +0,0 @@ public interface Registry extends Iterable { + * Trim materials. + * + * @see TrimMaterial ++ * @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#TRIM_MATERIAL} + */ +- Registry TRIM_MATERIAL = Bukkit.getRegistry(TrimMaterial.class); ++ @Deprecated(since = "1.20.6") // Paper ++ Registry TRIM_MATERIAL = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(TrimMaterial.class), "No registry present for TrimMaterial. This is a bug."); // Paper + /** + * Trim patterns. + * + * @see TrimPattern ++ * @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#TRIM_PATTERN} + */ +- Registry TRIM_PATTERN = Bukkit.getRegistry(TrimPattern.class); ++ @Deprecated(since = "1.20.6") ++ Registry TRIM_PATTERN = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(TrimPattern.class), "No registry present for TrimPattern. This is a bug."); // Paper + /** + * Damage types. + * + * @see DamageType ++ * @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#DAMAGE_TYPE} + */ +- @ApiStatus.Experimental +- Registry DAMAGE_TYPE = Objects.requireNonNull(Bukkit.getRegistry(DamageType.class), "No registry present for DamageType. This is a bug."); ++ @Deprecated(since = "1.20.6") ++ Registry DAMAGE_TYPE = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(DamageType.class), "No registry present for DamageType. This is a bug."); // Paper + /** + * Villager profession. + * +@@ -0,0 +0,0 @@ public interface Registry extends Iterable { + * Wolf variants. + * + * @see Wolf.Variant ++ * @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#WOLF_VARIANT} + */ +- Registry WOLF_VARIANT = Objects.requireNonNull(Bukkit.getRegistry(Wolf.Variant.class), "No registry present for Wolf Variant. This is a bug."); ++ @Deprecated(since = "1.20.6") ++ Registry WOLF_VARIANT = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(Wolf.Variant.class), "No registry present for Wolf$Variant. This is a bug."); // Paper + /** + * Map cursor types. + * +@@ -0,0 +0,0 @@ public interface Registry extends Iterable { + * + * @see GameEvent + */ +- Registry GAME_EVENT = Objects.requireNonNull(Bukkit.getRegistry(GameEvent.class), "No registry present for GameEvent. This is a bug."); ++ Registry GAME_EVENT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.GAME_EVENT); // Paper + /** + * Get the object by its key. + * +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -0,0 +0,0 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + * @param tClass of the registry to get + * @param type of the registry + * @return the corresponding registry or null if not present ++ * @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} ++ * with keys from {@link io.papermc.paper.registry.RegistryKey} + */ + @Nullable ++ @Deprecated(since = "1.20.6") // Paper + Registry getRegistry(@NotNull Class tClass); + + /** +diff --git a/src/test/java/io/papermc/paper/registry/TestRegistryAccess.java b/src/test/java/io/papermc/paper/registry/TestRegistryAccess.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/registry/TestRegistryAccess.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import org.bukkit.Keyed; ++import org.bukkit.Registry; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++public class TestRegistryAccess implements RegistryAccess { ++ ++ @Override ++ @Deprecated(since = "1.20.6", forRemoval = true) ++ public @Nullable Registry getRegistry(final @NotNull Class type) { ++ throw new UnsupportedOperationException("Not supported"); ++ } ++ ++ @Override ++ public @NotNull Registry getRegistry(final @NotNull RegistryKey registryKey) { ++ throw new UnsupportedOperationException("Not supported"); ++ } ++} +diff --git a/src/test/java/org/bukkit/support/TestServer.java b/src/test/java/org/bukkit/support/TestServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/support/TestServer.java ++++ b/src/test/java/org/bukkit/support/TestServer.java +@@ -0,0 +0,0 @@ public final class TestServer { + + when(instance.getBukkitVersion()).thenReturn("BukkitVersion_" + TestServer.class.getPackage().getImplementationVersion()); + +- Map, Registry> registers = new HashMap<>(); +- when(instance.getRegistry(any())).then(invocationOnMock -> registers.computeIfAbsent(invocationOnMock.getArgument(0), aClass -> new Registry() { +- private final Map cache = new HashMap<>(); +- +- @Override +- public Keyed get(NamespacedKey key) { +- return cache.computeIfAbsent(key, key2 -> mock(aClass, withSettings().stubOnly())); +- } +- +- @NotNull +- @Override +- public Stream stream() { +- throw new UnsupportedOperationException("Not supported"); +- } +- +- @Override +- public Iterator iterator() { +- throw new UnsupportedOperationException("Not supported"); +- } +- })); ++ // Paper start - RegistryAccess ++ when(instance.getRegistry(any())).then(invocationOnMock -> { ++ return io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(((Class)invocationOnMock.getArgument(0))); ++ }); ++ // Paper end - RegistryAccess + + UnsafeValues unsafeValues = mock(withSettings().stubOnly()); + when(instance.getUnsafe()).thenReturn(unsafeValues); +diff --git a/src/test/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess b/src/test/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/test/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess +@@ -0,0 +1 @@ ++io.papermc.paper.registry.TestRegistryAccess diff --git a/patches/api/Add-StructuresLocateEvent.patch b/patches/api/Add-StructuresLocateEvent.patch index e67d4f1dbb..b9c4a511c1 100644 --- a/patches/api/Add-StructuresLocateEvent.patch +++ b/patches/api/Add-StructuresLocateEvent.patch @@ -519,18 +519,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public interface Registry extends Iterable { * @see GameEvent */ - Registry GAME_EVENT = Objects.requireNonNull(Bukkit.getRegistry(GameEvent.class), "No registry present for GameEvent. This is a bug."); -+ + Registry GAME_EVENT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.GAME_EVENT); // Paper + // Paper start + /** + * Configured structures. + * @see io.papermc.paper.world.structure.ConfiguredStructure -+ * @deprecated use {@link #STRUCTURE} ++ * @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#STRUCTURE} + */ + @Deprecated(forRemoval = true) -+ Registry CONFIGURED_STRUCTURE = Bukkit.getRegistry(io.papermc.paper.world.structure.ConfiguredStructure.class); ++ Registry CONFIGURED_STRUCTURE = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.world.structure.ConfiguredStructure.class), "No registry present for ConfiguredStructure. This is a bug."); + // Paper end -+ /** * Get the object by its key. * diff --git a/patches/api/Code-Generation.patch b/patches/api/Code-Generation.patch index 402fca8f0b..787a87fe49 100644 --- a/patches/api/Code-Generation.patch +++ b/patches/api/Code-Generation.patch @@ -92,13 +92,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package io.papermc.paper.registry; + +import net.kyori.adventure.key.Keyed; ++import org.bukkit.Art; ++import org.bukkit.Fluid; +import org.bukkit.GameEvent; ++import org.bukkit.MusicInstrument; ++import org.bukkit.Particle; ++import org.bukkit.Sound; ++import org.bukkit.attribute.Attribute; +import org.bukkit.block.Biome; ++import org.bukkit.block.banner.PatternType; ++import org.bukkit.damage.DamageType; ++import org.bukkit.enchantments.Enchantment; ++import org.bukkit.entity.Cat; ++import org.bukkit.entity.EntityType; ++import org.bukkit.entity.Frog; ++import org.bukkit.entity.Villager; ++import org.bukkit.entity.Wolf; ++import org.bukkit.entity.memory.MemoryKey; +import org.bukkit.generator.structure.Structure; +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 org.bukkit.map.MapCursor; ++import org.bukkit.potion.PotionEffectType; ++import org.bukkit.potion.PotionType; + +import static io.papermc.paper.registry.RegistryKeyImpl.create; + @@ -115,7 +132,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @param the value type + */ +@SuppressWarnings("unused") -+@ApiStatus.Experimental +public sealed interface RegistryKey extends Keyed permits RegistryKeyImpl { + + /* ******************* * @@ -131,6 +147,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @see io.papermc.paper.registry.keys.StructureTypeKeys + */ + RegistryKey STRUCTURE_TYPE = create("worldgen/structure_type"); ++ /** ++ * Built-in registry for instruments. ++ * @see io.papermc.paper.registry.keys.InstrumentKeys ++ */ ++ RegistryKey INSTRUMENT = create("instrument"); ++ /** ++ * Built-in registry for enchantments. ++ * @see io.papermc.paper.registry.keys.EnchantmentKeys ++ */ ++ RegistryKey ENCHANTMENT = create("enchantment"); ++ /** ++ * Built-in registry for potion effect types (mob effects). ++ * @see io.papermc.paper.registry.keys.MobEffectKeys ++ */ ++ RegistryKey MOB_EFFECT = create("mob_effect"); ++ + + /* ********************** * + * Data-driven Registries * @@ -155,6 +187,35 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @see io.papermc.paper.registry.keys.TrimPatternKeys + */ + RegistryKey TRIM_PATTERN = create("trim_pattern"); ++ /** ++ * Data-driven registry for damage types. ++ * @see io.papermc.paper.registry.keys.DamageTypeKeys ++ */ ++ RegistryKey DAMAGE_TYPE = create("damage_type"); ++ /** ++ * Data-driven registry for wolf variants ++ * @see io.papermc.paper.registry.keys.WolfVariantKeys ++ */ ++ RegistryKey WOLF_VARIANT = create("wolf_variant"); ++ ++ ++ /* ******************* * ++ * API-only Registries * ++ * ******************* */ ++ RegistryKey PAINTING_VARIANT = create("painting_variant"); ++ RegistryKey ATTRIBUTE = create("attribute"); ++ RegistryKey BANNER_PATTERN = create("banner_pattern"); ++ RegistryKey CAT_VARIANT = create("cat_variant"); ++ RegistryKey ENTITY_TYPE = create("entity_type"); ++ RegistryKey PARTICLE_TYPE = create("particle_type"); ++ RegistryKey POTION = create("potion"); ++ RegistryKey SOUND_EVENT = create("sound_event"); ++ RegistryKey VILLAGER_PROFESSION = create("villager_profession"); ++ RegistryKey VILLAGER_TYPE = create("villager_type"); ++ RegistryKey> MEMORY_MODULE_TYPE = create("memory_module_type"); ++ RegistryKey FLUID = create("fluid"); ++ RegistryKey FROG_VARIANT = create("frog_variant"); ++ RegistryKey MAP_DECORATION_TYPE = create("map_decoration_type"); +} 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 @@ -175,11 +236,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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)); ++ final RegistryKey registryKey = createInternal(key); + REGISTRY_KEYS.add(registryKey); + return registryKey; + } + ++ // creates the key without adding to the internal set of keys ++ static RegistryKey createInternal(@Subst("some_key") final String key) { ++ return new RegistryKeyImpl<>(Key.key(Key.MINECRAFT_NAMESPACE, key)); ++ } ++ +} 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 @@ -227,7 +293,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @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) { ++ static @NotNull TypedKey create(final @NotNull RegistryKey registryKey, final @NotNull Key key) { + return new TypedKeyImpl<>(key, registryKey); + } +} @@ -243,7 +309,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import net.kyori.adventure.key.Keyed; +import org.jetbrains.annotations.NotNull; + -+record TypedKeyImpl(@NotNull Key key, @NotNull RegistryKey registryKey) implements TypedKey { ++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 diff --git a/patches/api/More-PotionEffectType-API.patch b/patches/api/More-PotionEffectType-API.patch index 464fc89fe7..af0bd7e71f 100644 --- a/patches/api/More-PotionEffectType-API.patch +++ b/patches/api/More-PotionEffectType-API.patch @@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public interface Registry extends Iterable { */ @Deprecated(forRemoval = true) - Registry CONFIGURED_STRUCTURE = Bukkit.getRegistry(io.papermc.paper.world.structure.ConfiguredStructure.class); + Registry CONFIGURED_STRUCTURE = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.world.structure.ConfiguredStructure.class), "No registry present for ConfiguredStructure. This is a bug."); + + /** + * Potion effect types. @@ -38,8 +38,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }; // Paper end - /** + * Get the object by its key. diff --git a/src/main/java/org/bukkit/potion/PotionEffectType.java b/src/main/java/org/bukkit/potion/PotionEffectType.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/potion/PotionEffectType.java diff --git a/patches/server/Add-RegistryAccess-for-managing-Registries.patch b/patches/server/Add-RegistryAccess-for-managing-Registries.patch new file mode 100644 index 0000000000..a0a71ec078 --- /dev/null +++ b/patches/server/Add-RegistryAccess-for-managing-Registries.patch @@ -0,0 +1,1026 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Mon, 27 Feb 2023 18:28:39 -0800 +Subject: [PATCH] Add RegistryAccess for managing Registries + +RegistryAccess is independant from CraftServer and +doesn't require one to be created allowing the +org.bukkit.Registry class to be loaded earlier. + +== AT == +public net.minecraft.server.RegistryLayer STATIC_ACCESS + +diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/src/main/java/io/papermc/paper/registry/PaperRegistries.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/PaperRegistries.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import io.papermc.paper.registry.entry.RegistryEntry; ++import java.util.Collections; ++import java.util.IdentityHashMap; ++import java.util.List; ++import java.util.Map; ++import net.minecraft.core.Registry; ++import net.minecraft.core.registries.Registries; ++import net.minecraft.resources.ResourceKey; ++import net.minecraft.world.item.enchantment.Enchantment; ++import net.minecraft.world.level.levelgen.structure.Structure; ++import org.bukkit.GameEvent; ++import org.bukkit.Keyed; ++import org.bukkit.MusicInstrument; ++import org.bukkit.craftbukkit.CraftGameEvent; ++import org.bukkit.craftbukkit.CraftMusicInstrument; ++import org.bukkit.craftbukkit.damage.CraftDamageType; ++import org.bukkit.craftbukkit.enchantments.CraftEnchantment; ++import org.bukkit.craftbukkit.entity.CraftWolf; ++import org.bukkit.craftbukkit.generator.structure.CraftStructure; ++import org.bukkit.craftbukkit.generator.structure.CraftStructureType; ++import org.bukkit.craftbukkit.inventory.trim.CraftTrimMaterial; ++import org.bukkit.craftbukkit.inventory.trim.CraftTrimPattern; ++import org.bukkit.craftbukkit.potion.CraftPotionEffectType; ++import org.bukkit.damage.DamageType; ++import org.bukkit.entity.Wolf; ++import org.bukkit.entity.memory.MemoryKey; ++import org.bukkit.generator.structure.StructureType; ++import org.bukkit.inventory.meta.trim.TrimMaterial; ++import org.bukkit.inventory.meta.trim.TrimPattern; ++import org.bukkit.potion.PotionEffectType; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++import org.checkerframework.framework.qual.DefaultQualifier; ++ ++import static io.papermc.paper.registry.entry.RegistryEntry.apiOnly; ++import static io.papermc.paper.registry.entry.RegistryEntry.entry; ++ ++@DefaultQualifier(NonNull.class) ++public final class PaperRegistries { ++ ++ static final List> REGISTRY_ENTRIES; ++ private static final Map, RegistryEntry> BY_REGISTRY_KEY; ++ private static final Map, RegistryEntry> BY_RESOURCE_KEY; ++ static { ++ REGISTRY_ENTRIES = List.of( ++ // built-ins ++ entry(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, Enchantment.class, CraftEnchantment::new), ++ entry(Registries.GAME_EVENT, RegistryKey.GAME_EVENT, GameEvent.class, CraftGameEvent::new), ++ entry(Registries.INSTRUMENT, RegistryKey.INSTRUMENT, MusicInstrument.class, CraftMusicInstrument::new), ++ entry(Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT, PotionEffectType.class, CraftPotionEffectType::new), ++ entry(Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE, StructureType.class, CraftStructureType::new), ++ ++ // data-drivens ++ entry(Registries.STRUCTURE, RegistryKey.STRUCTURE, Structure.class, CraftStructure::new).delayed(), ++ entry(Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL, TrimMaterial.class, CraftTrimMaterial::new).delayed(), ++ entry(Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN, TrimPattern.class, CraftTrimPattern::new).delayed(), ++ entry(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE, DamageType.class, CraftDamageType::new).delayed(), ++ entry(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT, Wolf.Variant.class, CraftWolf.CraftVariant::new).delayed(), ++ ++ // api-only ++ apiOnly(Registries.BIOME, RegistryKey.BIOME, () -> org.bukkit.Registry.BIOME), ++ apiOnly(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT, () -> org.bukkit.Registry.ART), ++ apiOnly(Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE, () -> org.bukkit.Registry.ATTRIBUTE), ++ apiOnly(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN, () -> org.bukkit.Registry.BANNER_PATTERN), ++ apiOnly(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT, () -> org.bukkit.Registry.CAT_VARIANT), ++ apiOnly(Registries.ENTITY_TYPE, RegistryKey.ENTITY_TYPE, () -> org.bukkit.Registry.ENTITY_TYPE), ++ apiOnly(Registries.PARTICLE_TYPE, RegistryKey.PARTICLE_TYPE, () -> org.bukkit.Registry.PARTICLE_TYPE), ++ apiOnly(Registries.POTION, RegistryKey.POTION, () -> org.bukkit.Registry.POTION), ++ apiOnly(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT, () -> org.bukkit.Registry.SOUNDS), ++ apiOnly(Registries.VILLAGER_PROFESSION, RegistryKey.VILLAGER_PROFESSION, () -> org.bukkit.Registry.VILLAGER_PROFESSION), ++ apiOnly(Registries.VILLAGER_TYPE, RegistryKey.VILLAGER_TYPE, () -> org.bukkit.Registry.VILLAGER_TYPE), ++ apiOnly(Registries.MEMORY_MODULE_TYPE, RegistryKey.MEMORY_MODULE_TYPE, () -> (org.bukkit.Registry>) (org.bukkit.Registry) org.bukkit.Registry.MEMORY_MODULE_TYPE), ++ apiOnly(Registries.FLUID, RegistryKey.FLUID, () -> org.bukkit.Registry.FLUID), ++ apiOnly(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT, () -> org.bukkit.Registry.FROG_VARIANT), ++ apiOnly(Registries.MAP_DECORATION_TYPE, RegistryKey.MAP_DECORATION_TYPE, () -> org.bukkit.Registry.MAP_DECORATION_TYPE) ++ ); ++ final Map, RegistryEntry> byRegistryKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size()); ++ final Map, RegistryEntry> byResourceKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size()); ++ for (final RegistryEntry entry : REGISTRY_ENTRIES) { ++ byRegistryKey.put(entry.apiKey(), entry); ++ byResourceKey.put(entry.mcKey(), entry); ++ } ++ BY_REGISTRY_KEY = Collections.unmodifiableMap(byRegistryKey); ++ BY_RESOURCE_KEY = Collections.unmodifiableMap(byResourceKey); ++ } ++ ++ @SuppressWarnings("unchecked") ++ public static > @Nullable RegistryEntry getEntry(final ResourceKey> resourceKey) { ++ return (RegistryEntry) BY_RESOURCE_KEY.get(resourceKey); ++ } ++ ++ @SuppressWarnings("unchecked") ++ public static > @Nullable RegistryEntry getEntry(final RegistryKey registryKey) { ++ return (RegistryEntry) BY_REGISTRY_KEY.get(registryKey); ++ } ++ ++ private PaperRegistries() { ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import io.papermc.paper.registry.entry.ApiRegistryEntry; ++import io.papermc.paper.registry.entry.RegistryEntry; ++import io.papermc.paper.registry.legacy.DelayedRegistry; ++import io.papermc.paper.registry.legacy.DelayedRegistryEntry; ++import io.papermc.paper.registry.legacy.LegacyRegistryIdentifiers; ++import java.util.Map; ++import java.util.NoSuchElementException; ++import java.util.Set; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.stream.Collectors; ++import net.minecraft.resources.ResourceKey; ++import org.bukkit.Keyed; ++import org.bukkit.Registry; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++import org.checkerframework.framework.qual.DefaultQualifier; ++import org.jetbrains.annotations.VisibleForTesting; ++ ++import static java.util.Objects.requireNonNull; ++ ++@DefaultQualifier(NonNull.class) ++public class PaperRegistryAccess implements RegistryAccess { ++ ++ // We store the API registries in a memoized supplier, so they can be created on-demand. ++ // These suppliers are added to this map right after the instance of nms.Registry is created before it is loaded. ++ // We want to do registration there, so we have access to the nms.Registry instance in order to wrap it in a CraftRegistry instance. ++ // The memoized Supplier is needed because we *can't* instantiate any CraftRegistry class until **all** the BuiltInRegistries have been added ++ // to this map because that would class-load org.bukkit.Registry which would query this map. ++ private final Map, RegistryHolder> registries = new ConcurrentHashMap<>(); // is "identity" because RegistryKey overrides equals and hashCode ++ ++ public static PaperRegistryAccess instance() { ++ return (PaperRegistryAccess) RegistryAccessHolder.INSTANCE.orElseThrow(() -> new IllegalStateException("No RegistryAccess implementation found")); ++ } ++ ++ @VisibleForTesting ++ public Set> getLoadedServerBackedRegistries() { ++ return this.registries.keySet().stream().filter(registryHolder -> !(PaperRegistries.getEntry(registryHolder) instanceof ApiRegistryEntry)).collect(Collectors.toUnmodifiableSet()); ++ } ++ ++ @SuppressWarnings("unchecked") ++ @Deprecated(forRemoval = true) ++ @Override ++ public @Nullable Registry getRegistry(final Class type) { ++ final RegistryKey registryKey; ++ final @Nullable RegistryEntry entry; ++ registryKey = requireNonNull(byType(type), () -> type + " is not a valid registry type"); ++ entry = PaperRegistries.getEntry(registryKey); ++ final @Nullable RegistryHolder registry = (RegistryHolder) this.registries.get(registryKey); ++ if (registry != null) { ++ // if the registry exists, return right away. Since this is the "legacy" method, we return DelayedRegistry ++ // for the non-builtin Registry instances stored as fields in Registry. ++ return registry.get(); ++ } else if (entry instanceof DelayedRegistryEntry) { ++ // if the registry doesn't exist and the entry is marked as "delayed", we create a registry holder that is empty ++ // which will later be filled with the actual registry. This is so the fields on org.bukkit.Registry can be populated with ++ // registries that don't exist at the time org.bukkit.Registry is statically initialized. ++ final RegistryHolder delayedHolder = new RegistryHolder.Delayed<>(); ++ this.registries.put(registryKey, delayedHolder); ++ return delayedHolder.get(); ++ } else { ++ // if the registry doesn't exist yet or doesn't have a delayed entry, just return null ++ return null; ++ } ++ } ++ ++ @SuppressWarnings("unchecked") ++ @Override ++ public Registry getRegistry(final RegistryKey key) { ++ if (PaperRegistries.getEntry(key) == null) { ++ throw new NoSuchElementException(key + " is not a valid registry key"); ++ } ++ final @Nullable RegistryHolder registryHolder = (RegistryHolder) this.registries.get(key); ++ if (registryHolder == null) { ++ throw new IllegalArgumentException(key + " points to a registry that is not available yet"); ++ } ++ // since this is the getRegistry method that uses the modern RegistryKey, we unwrap any DelayedRegistry instances ++ // that might be returned here. I don't think reference equality is required when doing getRegistry(RegistryKey.WOLF_VARIANT) == Registry.WOLF_VARIANT ++ return possiblyUnwrap(registryHolder.get()); ++ } ++ ++ private static Registry possiblyUnwrap(final Registry registry) { ++ if (registry instanceof final DelayedRegistry delayedRegistry) { // if not coming from legacy, unwrap the delayed registry ++ return delayedRegistry.delegate(); ++ } ++ return registry; ++ } ++ ++ public void registerReloadableRegistry(final ResourceKey> resourceKey, final net.minecraft.core.Registry registry) { ++ this.registerRegistry(resourceKey, registry, true); ++ } ++ ++ public void registerRegistry(final ResourceKey> resourceKey, final net.minecraft.core.Registry registry) { ++ this.registerRegistry(resourceKey, registry, false); ++ } ++ ++ @SuppressWarnings("unchecked") // this method should be called right after any new MappedRegistry instances are created to later be used by the server. ++ private > void registerRegistry(final ResourceKey> resourceKey, final net.minecraft.core.Registry registry, final boolean replace) { ++ final @Nullable RegistryEntry entry = PaperRegistries.getEntry(resourceKey); ++ if (entry == null) { // skip registries that don't have API entries ++ return; ++ } ++ final @Nullable RegistryHolder registryHolder = (RegistryHolder) this.registries.get(entry.apiKey()); ++ if (registryHolder == null || replace) { ++ // if the holder doesn't exist yet, or is marked as "replaceable", put it in the map. ++ this.registries.put(entry.apiKey(), entry.createRegistryHolder(registry)); ++ } else { ++ if (registryHolder instanceof RegistryHolder.Delayed && entry instanceof final DelayedRegistryEntry delayedEntry) { ++ // if the registry holder is delayed, and the entry is marked as "delayed", then load the holder with the CraftRegistry instance that wraps the actual nms Registry. ++ ((RegistryHolder.Delayed) registryHolder).loadFrom(delayedEntry, registry); ++ } else { ++ throw new IllegalArgumentException(resourceKey + " has already been created"); ++ } ++ } ++ } ++ ++ @SuppressWarnings("unchecked") ++ @Deprecated ++ @VisibleForTesting ++ public static @Nullable RegistryKey byType(final Class type) { ++ return (RegistryKey) LegacyRegistryIdentifiers.CLASS_TO_KEY_MAP.get(type); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/RegistryHolder.java b/src/main/java/io/papermc/paper/registry/RegistryHolder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/RegistryHolder.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import com.google.common.base.Suppliers; ++import io.papermc.paper.registry.legacy.DelayedRegistry; ++import io.papermc.paper.registry.legacy.DelayedRegistryEntry; ++import java.util.function.Supplier; ++import org.bukkit.Keyed; ++import org.bukkit.Registry; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.framework.qual.DefaultQualifier; ++ ++@DefaultQualifier(NonNull.class) ++public interface RegistryHolder { ++ ++ Registry get(); ++ ++ final class Memoized> implements RegistryHolder { ++ ++ private final Supplier memoizedSupplier; ++ ++ public Memoized(final Supplier supplier) { ++ this.memoizedSupplier = Suppliers.memoize(supplier::get); ++ } ++ ++ public Registry get() { ++ return this.memoizedSupplier.get(); ++ } ++ } ++ ++ final class Delayed> implements RegistryHolder { ++ ++ private final DelayedRegistry delayedRegistry = new DelayedRegistry<>(); ++ ++ @Override ++ public DelayedRegistry get() { ++ return this.delayedRegistry; ++ } ++ ++ void loadFrom(final DelayedRegistryEntry delayedEntry, final net.minecraft.core.Registry registry) { ++ final RegistryHolder delegateHolder = delayedEntry.delegate().createRegistryHolder(registry); ++ if (!(delegateHolder instanceof RegistryHolder.Memoized)) { ++ throw new IllegalArgumentException(delegateHolder + " must be a memoized holder"); ++ } ++ this.delayedRegistry.load(((Memoized) delegateHolder).memoizedSupplier); ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/entry/ApiRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/ApiRegistryEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/entry/ApiRegistryEntry.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry.entry; ++ ++import io.papermc.paper.registry.RegistryHolder; ++import io.papermc.paper.registry.RegistryKey; ++import java.util.function.Supplier; ++import net.minecraft.core.Registry; ++import net.minecraft.resources.ResourceKey; ++import org.bukkit.Keyed; ++ ++public class ApiRegistryEntry extends BaseRegistryEntry> { ++ ++ private final Supplier> registrySupplier; ++ ++ protected ApiRegistryEntry( ++ final ResourceKey> mcKey, ++ final RegistryKey apiKey, ++ final Supplier> registrySupplier ++ ) { ++ super(mcKey, apiKey); ++ this.registrySupplier = registrySupplier; ++ } ++ ++ @Override ++ public RegistryHolder createRegistryHolder(final Registry nmsRegistry) { ++ return new RegistryHolder.Memoized<>(this.registrySupplier); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/entry/BaseRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/BaseRegistryEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/entry/BaseRegistryEntry.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry.entry; ++ ++import io.papermc.paper.registry.RegistryKey; ++import net.minecraft.core.Registry; ++import net.minecraft.resources.ResourceKey; ++import org.bukkit.Keyed; ++ ++public abstract class BaseRegistryEntry> implements RegistryEntry { // TODO remove Keyed ++ ++ private final ResourceKey> minecraftRegistryKey; ++ private final RegistryKey apiRegistryKey; ++ ++ protected BaseRegistryEntry(final ResourceKey> minecraftRegistryKey, final RegistryKey apiRegistryKey) { ++ this.minecraftRegistryKey = minecraftRegistryKey; ++ this.apiRegistryKey = apiRegistryKey; ++ } ++ ++ @Override ++ public final ResourceKey> mcKey() { ++ return this.minecraftRegistryKey; ++ } ++ ++ @Override ++ public final RegistryKey apiKey() { ++ return this.apiRegistryKey; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/entry/CraftRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/CraftRegistryEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/entry/CraftRegistryEntry.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry.entry; ++ ++import io.papermc.paper.registry.RegistryHolder; ++import io.papermc.paper.registry.RegistryKey; ++import java.util.function.BiFunction; ++import net.minecraft.core.Registry; ++import net.minecraft.resources.ResourceKey; ++import org.bukkit.Keyed; ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.CraftRegistry; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.framework.qual.DefaultQualifier; ++ ++@DefaultQualifier(NonNull.class) ++public class CraftRegistryEntry extends BaseRegistryEntry> { // TODO remove Keyed ++ ++ protected final Class classToPreload; ++ protected final BiFunction minecraftToBukkit; ++ ++ protected CraftRegistryEntry( ++ final ResourceKey> mcKey, ++ final RegistryKey apiKey, ++ final Class classToPreload, ++ final BiFunction minecraftToBukkit ++ ) { ++ super(mcKey, apiKey); ++ this.classToPreload = classToPreload; ++ this.minecraftToBukkit = minecraftToBukkit; ++ } ++ ++ @Override ++ public RegistryHolder createRegistryHolder(final Registry nmsRegistry) { ++ return new RegistryHolder.Memoized<>(() -> this.createApiRegistry(nmsRegistry)); ++ } ++ ++ private CraftRegistry createApiRegistry(final Registry nmsRegistry) { ++ return new CraftRegistry<>(this.classToPreload, nmsRegistry, this.minecraftToBukkit); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry.entry; ++ ++import io.papermc.paper.registry.RegistryHolder; ++import io.papermc.paper.registry.RegistryKey; ++import io.papermc.paper.registry.legacy.DelayedRegistryEntry; ++import java.util.function.BiFunction; ++import java.util.function.Supplier; ++import net.minecraft.core.Registry; ++import net.minecraft.resources.ResourceKey; ++import org.bukkit.Keyed; ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.CraftRegistry; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.framework.qual.DefaultQualifier; ++ ++@DefaultQualifier(NonNull.class) ++public interface RegistryEntry> extends RegistryEntryInfo { // TODO remove Keyed ++ ++ RegistryHolder createRegistryHolder(Registry nmsRegistry); ++ ++ /** ++ * This should only be used if the registry instance needs to exist early due to the need ++ * to populate a field in {@link org.bukkit.Registry}. Data-driven registries shouldn't exist ++ * as fields, but instead be obtained via {@link io.papermc.paper.registry.RegistryAccess#getRegistry(RegistryKey)} ++ */ ++ @Deprecated ++ default RegistryEntry delayed() { ++ return new DelayedRegistryEntry<>(this); ++ } ++ ++ static RegistryEntry> entry( ++ final ResourceKey> mcKey, ++ final RegistryKey apiKey, ++ final Class classToPreload, ++ final BiFunction minecraftToBukkit ++ ) { ++ return new CraftRegistryEntry<>(mcKey, apiKey, classToPreload, minecraftToBukkit); ++ } ++ ++ static RegistryEntry> apiOnly( ++ final ResourceKey> mcKey, ++ final RegistryKey apiKey, ++ final Supplier> apiRegistrySupplier ++ ) { ++ return new ApiRegistryEntry<>(mcKey, apiKey, apiRegistrySupplier); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry.entry; ++ ++import io.papermc.paper.registry.RegistryKey; ++import net.minecraft.core.Registry; ++import net.minecraft.resources.ResourceKey; ++ ++public interface RegistryEntryInfo { ++ ++ ResourceKey> mcKey(); ++ ++ RegistryKey apiKey(); ++} +diff --git a/src/main/java/io/papermc/paper/registry/entry/package-info.java b/src/main/java/io/papermc/paper/registry/entry/package-info.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/entry/package-info.java +@@ -0,0 +0,0 @@ ++@DefaultQualifier(NonNull.class) ++package io.papermc.paper.registry.entry; ++ ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.framework.qual.DefaultQualifier; +diff --git a/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistry.java b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistry.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry.legacy; ++ ++import java.util.Iterator; ++import java.util.function.Supplier; ++import java.util.stream.Stream; ++import org.bukkit.Keyed; ++import org.bukkit.NamespacedKey; ++import org.bukkit.Registry; ++import org.bukkit.craftbukkit.CraftRegistry; ++import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * This is to support the now-deprecated fields in {@link Registry} for ++ * data-driven registries. ++ */ ++public final class DelayedRegistry> implements Registry { ++ ++ private @MonotonicNonNull Supplier delegate; ++ ++ public void load(final Supplier registry) { ++ if (this.delegate != null) { ++ throw new IllegalStateException("Registry already loaded!"); ++ } ++ this.delegate = registry; ++ } ++ ++ public Registry delegate() { ++ if (this.delegate == null) { ++ throw new IllegalStateException("You are trying to access this registry too early!"); ++ } ++ return this.delegate.get(); ++ } ++ ++ @Override ++ public @Nullable T get(final NamespacedKey key) { ++ return this.delegate().get(key); ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return this.delegate().iterator(); ++ } ++ ++ @Override ++ public Stream stream() { ++ return this.delegate().stream(); ++ } ++ ++ @Override ++ public NamespacedKey getKey(final T value) { ++ return this.delegate().getKey(value); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistryEntry.java b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistryEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistryEntry.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry.legacy; ++ ++import io.papermc.paper.registry.RegistryHolder; ++import io.papermc.paper.registry.RegistryKey; ++import io.papermc.paper.registry.entry.RegistryEntry; ++import net.minecraft.core.Registry; ++import net.minecraft.resources.ResourceKey; ++import org.bukkit.Keyed; ++ ++public record DelayedRegistryEntry>(RegistryEntry delegate) implements RegistryEntry { ++ ++ @Override ++ public ResourceKey> mcKey() { ++ return this.delegate.mcKey(); ++ } ++ ++ @Override ++ public RegistryKey apiKey() { ++ return this.delegate.apiKey(); ++ } ++ ++ @Override ++ public RegistryHolder createRegistryHolder(final Registry nmsRegistry) { ++ return this.delegate.createRegistryHolder(nmsRegistry); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/legacy/LegacyRegistryIdentifiers.java b/src/main/java/io/papermc/paper/registry/legacy/LegacyRegistryIdentifiers.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/legacy/LegacyRegistryIdentifiers.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry.legacy; ++ ++import com.google.common.collect.ImmutableMap; ++import io.leangen.geantyref.GenericTypeReflector; ++import io.papermc.paper.registry.RegistryKey; ++import java.lang.reflect.Field; ++import java.lang.reflect.ParameterizedType; ++import java.util.Map; ++ ++@Deprecated ++public final class LegacyRegistryIdentifiers { ++ ++ public static final Map, RegistryKey> CLASS_TO_KEY_MAP; ++ ++ static { ++ final ImmutableMap.Builder, RegistryKey> builder = ImmutableMap.builder(); ++ try { ++ for (final Field field : RegistryKey.class.getFields()) { ++ if (field.getType() == RegistryKey.class) { ++ // get the legacy type from the RegistryKey generic parameter on the field ++ final Class legacyType = GenericTypeReflector.erase(((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]); ++ builder.put(legacyType, (RegistryKey) field.get(null)); ++ } ++ } ++ } catch (final ReflectiveOperationException ex) { ++ throw new RuntimeException(ex); ++ } ++ CLASS_TO_KEY_MAP = builder.build(); ++ } ++ ++ private LegacyRegistryIdentifiers() { ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/legacy/package-info.java b/src/main/java/io/papermc/paper/registry/legacy/package-info.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/legacy/package-info.java +@@ -0,0 +0,0 @@ ++@DefaultQualifier(NonNull.class) ++package io.papermc.paper.registry.legacy; ++ ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.framework.qual.DefaultQualifier; +diff --git a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java ++++ b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java +@@ -0,0 +0,0 @@ public class BuiltInRegistries { + ResourceKey> key, R registry, BuiltInRegistries.RegistryBootstrap initializer + ) { + Bootstrap.checkBootstrapCalled(() -> "registry " + key); ++ io.papermc.paper.registry.PaperRegistryAccess.instance().registerRegistry(registry.key(), registry); // Paper - initialize API registry + ResourceLocation resourceLocation = key.location(); + LOADERS.put(resourceLocation, () -> initializer.run(registry)); + WRITABLE_REGISTRY.register((ResourceKey)key, registry, RegistrationInfo.BUILT_IN); // Paper - decompile fix +diff --git a/src/main/java/net/minecraft/resources/RegistryDataLoader.java b/src/main/java/net/minecraft/resources/RegistryDataLoader.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/resources/RegistryDataLoader.java ++++ b/src/main/java/net/minecraft/resources/RegistryDataLoader.java +@@ -0,0 +0,0 @@ public class RegistryDataLoader { + public static record RegistryData(ResourceKey> key, Codec elementCodec) { + RegistryDataLoader.Loader create(Lifecycle lifecycle, Map, Exception> errors) { + WritableRegistry writableRegistry = new MappedRegistry<>(this.key, lifecycle); ++ io.papermc.paper.registry.PaperRegistryAccess.instance().registerRegistry(this.key, writableRegistry); // Paper - initialize API registry + return new RegistryDataLoader.Loader<>(this, writableRegistry, errors); + } + +diff --git a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java ++++ b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java +@@ -0,0 +0,0 @@ public class ReloadableServerRegistries { + return CompletableFuture.supplyAsync( + () -> { + WritableRegistry writableRegistry = new MappedRegistry<>(type.registryKey(), Lifecycle.experimental()); ++ io.papermc.paper.registry.PaperRegistryAccess.instance().registerReloadableRegistry(type.registryKey(), writableRegistry); // Paper - register reloadable registry + Map map = new HashMap<>(); + SimpleJsonResourceReloadListener.scanDirectory(resourceManager, type.directory(), GSON, map); + map.forEach( +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java +@@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { + + ", this can happen if a plugin creates its own registry entry with out properly registering it."); + } + +- /** +- * Note: Newly added registries should also be added to RegistriesArgumentProvider in the test package +- * +- * @param bukkitClass the bukkit class of the registry +- * @param registryHolder the minecraft registry holder +- * @return the bukkit registry of the provided class +- */ +- public static Registry createRegistry(Class bukkitClass, RegistryAccess registryHolder) { +- if (bukkitClass == Enchantment.class) { +- return new CraftRegistry<>(Enchantment.class, registryHolder.registryOrThrow(Registries.ENCHANTMENT), CraftEnchantment::new); +- } +- if (bukkitClass == GameEvent.class) { +- return new CraftRegistry<>(GameEvent.class, registryHolder.registryOrThrow(Registries.GAME_EVENT), CraftGameEvent::new); +- } +- if (bukkitClass == MusicInstrument.class) { +- return new CraftRegistry<>(MusicInstrument.class, registryHolder.registryOrThrow(Registries.INSTRUMENT), CraftMusicInstrument::new); +- } +- if (bukkitClass == PotionEffectType.class) { +- return new CraftRegistry<>(PotionEffectType.class, registryHolder.registryOrThrow(Registries.MOB_EFFECT), CraftPotionEffectType::new); +- } +- if (bukkitClass == Structure.class) { +- return new CraftRegistry<>(Structure.class, registryHolder.registryOrThrow(Registries.STRUCTURE), CraftStructure::new); +- } +- if (bukkitClass == StructureType.class) { +- return new CraftRegistry<>(StructureType.class, BuiltInRegistries.STRUCTURE_TYPE, CraftStructureType::new); +- } +- if (bukkitClass == TrimMaterial.class) { +- return new CraftRegistry<>(TrimMaterial.class, registryHolder.registryOrThrow(Registries.TRIM_MATERIAL), CraftTrimMaterial::new); +- } +- if (bukkitClass == TrimPattern.class) { +- return new CraftRegistry<>(TrimPattern.class, registryHolder.registryOrThrow(Registries.TRIM_PATTERN), CraftTrimPattern::new); +- } +- if (bukkitClass == DamageType.class) { +- return new CraftRegistry<>(DamageType.class, registryHolder.registryOrThrow(Registries.DAMAGE_TYPE), CraftDamageType::new); +- } +- if (bukkitClass == Wolf.Variant.class) { +- return new CraftRegistry<>(Wolf.Variant.class, registryHolder.registryOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new); +- } +- +- return null; +- } ++ // Paper - move to PaperRegistries + +- private final Class bukkitClass; ++ private final Class bukkitClass; // Paper - relax preload class + private final Map cache = new HashMap<>(); + private final net.minecraft.core.Registry minecraftRegistry; + private final BiFunction minecraftToBukkit; + private boolean init; + +- public CraftRegistry(Class bukkitClass, net.minecraft.core.Registry minecraftRegistry, BiFunction minecraftToBukkit) { ++ public CraftRegistry(Class bukkitClass, net.minecraft.core.Registry minecraftRegistry, BiFunction minecraftToBukkit) { // Paper - relax preload class + this.bukkitClass = bukkitClass; + this.minecraftRegistry = minecraftRegistry; + this.minecraftToBukkit = minecraftToBukkit; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + protected final DedicatedServer console; + protected final DedicatedPlayerList playerList; + private final Map worlds = new LinkedHashMap(); +- private final Map, Registry> registries = new HashMap<>(); ++ // private final Map, Registry> registries = new HashMap<>(); // Paper - replace with RegistryAccess + private YamlConfiguration configuration; + private YamlConfiguration commandsConfiguration; + private final Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions())); +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + + @Override + public Registry getRegistry(Class aClass) { +- return (Registry) this.registries.computeIfAbsent(aClass, key -> CraftRegistry.createRegistry(aClass, this.console.registryAccess())); ++ return io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(aClass); // Paper - replace with RegistryAccess + } + + @Deprecated +diff --git a/src/main/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess b/src/main/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess +@@ -0,0 +1 @@ ++io.papermc.paper.registry.PaperRegistryAccess +diff --git a/src/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java b/src/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry; ++ ++import org.bukkit.GameEvent; ++import org.bukkit.MusicInstrument; ++import org.bukkit.inventory.meta.trim.TrimPattern; ++import org.bukkit.support.AbstractTestingBase; ++import org.junit.jupiter.api.Test; ++ ++import static org.junit.jupiter.api.Assertions.assertSame; ++ ++@Deprecated ++class LegacyRegistryIdentifierTest extends AbstractTestingBase { ++ ++ @Test ++ void testSeveralConversions() { ++ assertSame(RegistryKey.GAME_EVENT, PaperRegistryAccess.byType(GameEvent.class)); ++ assertSame(RegistryKey.TRIM_PATTERN, PaperRegistryAccess.byType(TrimPattern.class)); ++ assertSame(RegistryKey.INSTRUMENT, PaperRegistryAccess.byType(MusicInstrument.class)); ++ } ++} +diff --git a/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java b/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java ++++ b/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java +@@ -0,0 +0,0 @@ + package io.papermc.paper.registry; + ++import io.papermc.paper.registry.entry.RegistryEntry; + 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.Keyed; + 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.assertNotNull; + import static org.junit.jupiter.api.Assertions.assertTrue; + + class RegistryKeyTest extends AbstractTestingBase { +@@ -0,0 +0,0 @@ class RegistryKeyTest extends AbstractTestingBase { + 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()); ++ } + ++ @ParameterizedTest ++ @MethodSource("data") ++ void testRegistryEntryExists(final RegistryKey key) { ++ final RegistryEntry entry = PaperRegistries.getEntry(key); ++ assertNotNull(entry, "Missing PaperRegistries entry for " + key); + } + } +diff --git a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java ++++ b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java +@@ -0,0 +0,0 @@ public class RegistryArgumentAddedTest extends AbstractTestingBase { + // Make sure every registry is created + Class.forName(Registry.class.getName()); + +- Set> loadedRegistries = new HashSet<>(DummyServer.registers.keySet()); +- Set> notFound = new HashSet<>(); ++ // Paper start ++ Set> loadedRegistries = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); ++ loadedRegistries.addAll(io.papermc.paper.registry.PaperRegistryAccess.instance().getLoadedServerBackedRegistries()); ++ // Paper end ++ Set> notFound = new HashSet<>(); // Paper + + RegistriesArgumentProvider + .getData() + .map(Arguments::get) + .map(array -> array[0]) +- .map(clazz -> (Class) clazz) ++ .map(clazz -> (io.papermc.paper.registry.RegistryKey) clazz) // Paper + .forEach(clazz -> { + if (!loadedRegistries.remove(clazz)) { + notFound.add(clazz); +diff --git a/src/test/java/org/bukkit/registry/RegistryConversionTest.java b/src/test/java/org/bukkit/registry/RegistryConversionTest.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/registry/RegistryConversionTest.java ++++ b/src/test/java/org/bukkit/registry/RegistryConversionTest.java +@@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { + + @Order(1) + @RegistriesTest +- public void testHandleableImplementation(Class clazz) { ++ public void testHandleableImplementation(io.papermc.paper.registry.RegistryKey type, Class clazz) { // Paper + Set> notImplemented = new HashSet<>(); +- Registry registry = Bukkit.getRegistry(clazz); ++ Registry registry = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(type); // Paper + + for (Keyed item : registry) { + if (!(item instanceof Handleable)) { +@@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { + + @Order(2) + @RegistriesTest +- public void testMinecraftToBukkitPresent(Class clazz, ResourceKey> registryKey, ++ public void testMinecraftToBukkitPresent(io.papermc.paper.registry.RegistryKey type, Class clazz, ResourceKey> registryKey, // Paper + Class craftClazz, Class minecraftClazz) { + Method method = null; + try { +@@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { + + @Order(2) + @RegistriesTest +- public void testBukkitToMinecraftPresent(Class clazz, ResourceKey> registryKey, ++ public void testBukkitToMinecraftPresent(io.papermc.paper.registry.RegistryKey type, Class clazz, ResourceKey> registryKey, // Paper + Class craftClazz, Class minecraftClazz) { + Method method = null; + try { +@@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { + """, minecraftClazz.getName(), clazz.getSimpleName()); + } + +- @Order(2) ++ @Order(3) + @RegistriesTest +- public void testMinecraftToBukkitNullValue(Class clazz) throws IllegalAccessException { ++ public void testMinecraftToBukkitNullValue(io.papermc.paper.registry.RegistryKey type, Class clazz) throws IllegalAccessException { // Paper + this.checkValidMinecraftToBukkit(clazz); + + try { +@@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { + + @Order(3) + @RegistriesTest +- public void testBukkitToMinecraftNullValue(Class clazz) throws IllegalAccessException { ++ public void testBukkitToMinecraftNullValue(io.papermc.paper.registry.RegistryKey type, Class clazz) throws IllegalAccessException { // Paper + this.checkValidBukkitToMinecraft(clazz); + + try { +@@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { + + @Order(3) + @RegistriesTest +- public void testMinecraftToBukkit(Class clazz) { ++ public void testMinecraftToBukkit(io.papermc.paper.registry.RegistryKey type, Class clazz) { // Paper + this.checkValidMinecraftToBukkit(clazz); + this.checkValidHandle(clazz); + + Map notMatching = new HashMap<>(); + Method method = RegistryConversionTest.MINECRAFT_TO_BUKKIT_METHODS.get(clazz); + +- RegistryArgumentProvider.getValues(clazz).map(Arguments::get).forEach(arguments -> { ++ RegistryArgumentProvider.getValues(type).map(Arguments::get).forEach(arguments -> { // Paper + Keyed bukkit = (Keyed) arguments[0]; + Object minecraft = arguments[1]; + +@@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { + + @Order(3) + @RegistriesTest +- public void testBukkitToMinecraft(Class clazz) { ++ public void testBukkitToMinecraft(io.papermc.paper.registry.RegistryKey type, Class clazz) { // Paper + this.checkValidBukkitToMinecraft(clazz); + this.checkValidHandle(clazz); + + Map notMatching = new HashMap<>(); + Method method = RegistryConversionTest.BUKKIT_TO_MINECRAFT_METHODS.get(clazz); + +- RegistryArgumentProvider.getValues(clazz).map(Arguments::get).forEach(arguments -> { ++ RegistryArgumentProvider.getValues(type).map(Arguments::get).forEach(arguments -> { // Paper + Keyed bukkit = (Keyed) arguments[0]; + Object minecraft = arguments[1]; + +@@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { + */ + @Order(3) + @RegistriesTest +- public void testMinecraftToBukkitNoValidMinecraft(Class clazz, ResourceKey> registryKey, ++ public void testMinecraftToBukkitNoValidMinecraft(io.papermc.paper.registry.RegistryKey type, Class clazz, ResourceKey> registryKey, // Paper + Class craftClazz, Class minecraftClazz) throws IllegalAccessException { + this.checkValidMinecraftToBukkit(clazz); + +diff --git a/src/test/java/org/bukkit/support/DummyServer.java b/src/test/java/org/bukkit/support/DummyServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/support/DummyServer.java ++++ b/src/test/java/org/bukkit/support/DummyServer.java +@@ -0,0 +0,0 @@ public final class DummyServer { + when(instance.getLootTable(any())).then(mock -> new CraftLootTable(mock.getArgument(0), + AbstractTestingBase.DATA_PACK.fullRegistries().getLootTable(ResourceKey.create(Registries.LOOT_TABLE, CraftNamespacedKey.toMinecraft(mock.getArgument(0)))))); + +- when(instance.getRegistry(any())).then((Answer>) mock -> { +- Class aClass = mock.getArgument(0); +- return registers.computeIfAbsent(aClass, key -> CraftRegistry.createRegistry(aClass, AbstractTestingBase.REGISTRY_CUSTOM)); +- }); ++ // Paper - RegistryAccess + + // Paper start - testing additions + final Thread currentThread = Thread.currentThread(); +diff --git a/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java b/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java ++++ b/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java +@@ -0,0 +0,0 @@ + package org.bukkit.support.provider; + + import com.google.common.collect.Lists; ++import io.papermc.paper.registry.RegistryKey; + import java.util.List; + import java.util.stream.Stream; + import net.minecraft.core.registries.Registries; +@@ -0,0 +0,0 @@ public class RegistriesArgumentProvider implements ArgumentsProvider { + + static { + // Order: Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class +- DATA.add(Arguments.of(Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class)); +- DATA.add(Arguments.of(GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class)); +- DATA.add(Arguments.of(MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class)); +- DATA.add(Arguments.of(PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class)); +- DATA.add(Arguments.of(Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class)); +- DATA.add(Arguments.of(StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class)); +- DATA.add(Arguments.of(TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.armortrim.TrimMaterial.class)); +- DATA.add(Arguments.of(TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.armortrim.TrimPattern.class)); +- DATA.add(Arguments.of(DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class)); +- DATA.add(Arguments.of(Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, WolfVariant.class)); ++ // Order: RegistryKey, Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class ++ DATA.add(Arguments.of(RegistryKey.ENCHANTMENT, Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class)); ++ DATA.add(Arguments.of(RegistryKey.GAME_EVENT, GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class)); ++ DATA.add(Arguments.of(RegistryKey.INSTRUMENT, MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class)); ++ DATA.add(Arguments.of(RegistryKey.MOB_EFFECT, PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class)); ++ DATA.add(Arguments.of(RegistryKey.STRUCTURE, Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class)); ++ DATA.add(Arguments.of(RegistryKey.STRUCTURE_TYPE, StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class)); ++ DATA.add(Arguments.of(RegistryKey.TRIM_MATERIAL, TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.armortrim.TrimMaterial.class)); ++ DATA.add(Arguments.of(RegistryKey.TRIM_PATTERN, TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.armortrim.TrimPattern.class)); ++ DATA.add(Arguments.of(RegistryKey.DAMAGE_TYPE, DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class)); ++ DATA.add(Arguments.of(RegistryKey.WOLF_VARIANT, Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, net.minecraft.world.entity.animal.WolfVariant.class)); + } + + @Override +diff --git a/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java b/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java ++++ b/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java +@@ -0,0 +0,0 @@ public class RegistryArgumentProvider implements ArgumentsProvider, AnnotationCo + + @Override + public Stream provideArguments(ExtensionContext extensionContext) throws Exception { +- return RegistryArgumentProvider.getValues(this.registryType); ++ return RegistryArgumentProvider.getValues(io.papermc.paper.registry.PaperRegistryAccess.byType(this.registryType)); // Paper + } + +- public static Stream getValues(Class registryType) { +- Registry registry = Bukkit.getRegistry(registryType); ++ public static Stream getValues(io.papermc.paper.registry.RegistryKey registryType) { // Paper ++ Registry registry = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(registryType); // Paper + return registry.stream().map(keyed -> (Handleable) keyed) + .map(handleAble -> Arguments.of(handleAble, handleAble.getHandle())); + } diff --git a/patches/server/Add-StructuresLocateEvent.patch b/patches/server/Add-StructuresLocateEvent.patch index 087c8249ad..8ca547c3f5 100644 --- a/patches/server/Add-StructuresLocateEvent.patch +++ b/patches/server/Add-StructuresLocateEvent.patch @@ -5,6 +5,43 @@ Subject: [PATCH] Add StructuresLocateEvent Co-authored-by: Jake Potrebic +diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/src/main/java/io/papermc/paper/registry/PaperRegistries.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/io/papermc/paper/registry/PaperRegistries.java ++++ b/src/main/java/io/papermc/paper/registry/PaperRegistries.java +@@ -0,0 +0,0 @@ import static io.papermc.paper.registry.entry.RegistryEntry.entry; + @DefaultQualifier(NonNull.class) + public final class PaperRegistries { + ++ @Deprecated(forRemoval = true) ++ @org.jetbrains.annotations.VisibleForTesting ++ public static final RegistryKey CONFIGURED_STRUCTURE_REGISTRY_KEY = RegistryKeyImpl.createInternal("worldgen/structure"); ++ @Deprecated(forRemoval = true) ++ static final RegistryEntry CONFIGURED_STRUCTURE_REGISTRY_ENTRY = entry(Registries.STRUCTURE, CONFIGURED_STRUCTURE_REGISTRY_KEY, io.papermc.paper.world.structure.ConfiguredStructure.class, io.papermc.paper.world.structure.PaperConfiguredStructure::minecraftToBukkit).delayed(); ++ + static final List> REGISTRY_ENTRIES; + private static final Map, RegistryEntry> BY_REGISTRY_KEY; + private static final Map, RegistryEntry> BY_RESOURCE_KEY; +diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java ++++ b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java +@@ -0,0 +0,0 @@ public class PaperRegistryAccess implements RegistryAccess { + public @Nullable Registry getRegistry(final Class type) { + final RegistryKey registryKey; + final @Nullable RegistryEntry entry; +- registryKey = requireNonNull(byType(type), () -> type + " is not a valid registry type"); +- entry = PaperRegistries.getEntry(registryKey); ++ if (type == io.papermc.paper.world.structure.ConfiguredStructure.class) { // manually handle "duplicate" registries to avoid polluting maps in PaperRegistries ++ registryKey = (RegistryKey) PaperRegistries.CONFIGURED_STRUCTURE_REGISTRY_KEY; ++ entry = (RegistryEntry) PaperRegistries.CONFIGURED_STRUCTURE_REGISTRY_ENTRY; ++ } else { ++ registryKey = requireNonNull(byType(type), () -> type + " is not a valid registry type"); ++ entry = PaperRegistries.getEntry(registryKey); ++ } + final @Nullable RegistryHolder registry = (RegistryHolder) this.registries.get(registryKey); + if (registry != null) { + // if the registry exists, return right away. Since this is the "legacy" method, we return DelayedRegistry diff --git a/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java b/src/main/java/io/papermc/paper/world/structure/PaperConfiguredStructure.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -32,18 +69,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private PaperConfiguredStructure() { + } + -+ @Deprecated(forRemoval = true) -+ public static final class LegacyRegistry extends CraftRegistry { -+ -+ public LegacyRegistry(final Registry minecraftRegistry) { -+ super(ConfiguredStructure.class, minecraftRegistry, LegacyRegistry::minecraftToBukkit); -+ } -+ -+ private static @Nullable ConfiguredStructure minecraftToBukkit(NamespacedKey key, Structure nms) { -+ final ResourceLocation structureTypeLoc = Objects.requireNonNull(BuiltInRegistries.STRUCTURE_TYPE.getKey(nms.type()), "unexpected structure type " + nms.type()); -+ final @Nullable StructureType structureType = StructureType.getStructureTypes().get(structureTypeLoc.getPath()); -+ return structureType == null ? null : new ConfiguredStructure(key, structureType); -+ } ++ public static @Nullable ConfiguredStructure minecraftToBukkit(NamespacedKey key, Structure nms) { ++ final ResourceLocation structureTypeLoc = Objects.requireNonNull(BuiltInRegistries.STRUCTURE_TYPE.getKey(nms.type()), "unexpected structure type " + nms.type()); ++ final @Nullable StructureType structureType = StructureType.getStructureTypes().get(structureTypeLoc.getPath()); ++ return structureType == null ? null : new ConfiguredStructure(key, structureType); + } +} diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java @@ -75,22 +104,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 ChunkGeneratorStructureState chunkgeneratorstructurestate = world.getChunkSource().getGeneratorState(); Map>> map = new Object2ObjectArrayMap(); Iterator iterator = structures.iterator(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java -@@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { - return new CraftRegistry<>(Wolf.Variant.class, registryHolder.registryOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new); - } - // 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 - - return null; - } diff --git a/src/test/java/io/papermc/paper/world/structure/ConfiguredStructureTest.java b/src/test/java/io/papermc/paper/world/structure/ConfiguredStructureTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -201,7 +214,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (!(object instanceof CraftRegistry registry)) { continue; } -+ if (object instanceof io.papermc.paper.world.structure.PaperConfiguredStructure.LegacyRegistry) continue; // Paper - skip ++ if (object == Registry.CONFIGURED_STRUCTURE) continue; // Paper - skip data.add(Arguments.of(registry)); } catch (ReflectiveOperationException e) { @@ -210,10 +223,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java +++ b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java @@ -0,0 +0,0 @@ public class RegistryArgumentAddedTest extends AbstractTestingBase { - - Set> loadedRegistries = new HashSet<>(DummyServer.registers.keySet()); - Set> notFound = new HashSet<>(); -+ loadedRegistries.remove(io.papermc.paper.world.structure.ConfiguredStructure.class); // Paper - ignore + loadedRegistries.addAll(io.papermc.paper.registry.PaperRegistryAccess.instance().getLoadedServerBackedRegistries()); + // Paper end + Set> notFound = new HashSet<>(); // Paper ++ loadedRegistries.remove(io.papermc.paper.registry.PaperRegistries.CONFIGURED_STRUCTURE_REGISTRY_KEY); // Paper - ignore RegistriesArgumentProvider .getData() diff --git a/patches/server/Flat-bedrock-generator-settings.patch b/patches/server/Flat-bedrock-generator-settings.patch index aab963184f..505f06e3ea 100644 --- a/patches/server/Flat-bedrock-generator-settings.patch +++ b/patches/server/Flat-bedrock-generator-settings.patch @@ -113,9 +113,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper start BuiltInRegistries.bootStrap(() -> { + io.papermc.paper.world.worldgen.OptionallyFlatBedrockConditionSource.bootstrap(); // Paper - Flat bedrock generator settings - io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.enterBootstrappers(); // Paper - Entrypoint for bootstrapping }); // Paper end + CreativeModeTabs.validate(); diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java diff --git a/patches/server/Improve-Registry.patch b/patches/server/Improve-Registry.patch index b7d03a9dc2..5fd373a658 100644 --- a/patches/server/Improve-Registry.patch +++ b/patches/server/Improve-Registry.patch @@ -10,7 +10,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java @@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { - private final Class bukkitClass; + private final Class bukkitClass; // Paper - relax preload class private final Map cache = new HashMap<>(); + private final Map byValue = new java.util.IdentityHashMap<>(); // Paper - improve Registry private final net.minecraft.core.Registry minecraftRegistry; diff --git a/patches/server/Paper-Plugins.patch b/patches/server/Paper-Plugins.patch index 761cc4df4f..bfb73630ca 100644 --- a/patches/server/Paper-Plugins.patch +++ b/patches/server/Paper-Plugins.patch @@ -7211,6 +7211,14 @@ diff --git a/src/main/java/net/minecraft/server/Bootstrap.java b/src/main/java/n index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/Bootstrap.java +++ b/src/main/java/net/minecraft/server/Bootstrap.java +@@ -0,0 +0,0 @@ public class Bootstrap { + Bootstrap.isBootstrapped = true; + Instant instant = Instant.now(); + ++ io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.enterBootstrappers(); // Paper - Entrypoint for bootstrapping + if (BuiltInRegistries.REGISTRY.keySet().isEmpty()) { + throw new IllegalStateException("Unable to load registries"); + } else { @@ -0,0 +0,0 @@ public class Bootstrap { EntitySelectorOptions.bootStrap(); DispenseItemBehavior.bootStrap(); @@ -7218,7 +7226,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - BuiltInRegistries.bootStrap(); + // Paper start + BuiltInRegistries.bootStrap(() -> { -+ io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.enterBootstrappers(); // Paper - Entrypoint for bootstrapping + }); + // Paper end CreativeModeTabs.validate(); diff --git a/patches/server/TODO-Registry-Modification-API.patch b/patches/server/TODO-Registry-Modification-API.patch deleted file mode 100644 index 42fac961f7..0000000000 --- a/patches/server/TODO-Registry-Modification-API.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 27 Feb 2023 18:28:39 -0800 -Subject: [PATCH] TODO Registry Modification API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java -@@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { - if (bukkitClass == Wolf.Variant.class) { - return new CraftRegistry<>(Wolf.Variant.class, registryHolder.registryOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new); - } -+ // TODO registry modification API - - return null; - }