Registry Modification API

This commit is contained in:
Jake Potrebic 2023-02-25 13:47:13 -08:00
parent 854911ead0
commit 51d9ff6956
No known key found for this signature in database
GPG Key ID: ECE0B3C133C016C5
14 changed files with 2233 additions and 71 deletions

View File

@ -0,0 +1,308 @@
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.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.4")
@ApiStatus.Experimental
public final class EnchantmentKeys {
/**
* {@code minecraft:protection}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> PROTECTION = create(key("protection"));
/**
* {@code minecraft:fire_protection}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> FIRE_PROTECTION = create(key("fire_protection"));
/**
* {@code minecraft:feather_falling}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> FEATHER_FALLING = create(key("feather_falling"));
/**
* {@code minecraft:blast_protection}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> BLAST_PROTECTION = create(key("blast_protection"));
/**
* {@code minecraft:projectile_protection}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> PROJECTILE_PROTECTION = create(key("projectile_protection"));
/**
* {@code minecraft:respiration}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> RESPIRATION = create(key("respiration"));
/**
* {@code minecraft:aqua_affinity}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> AQUA_AFFINITY = create(key("aqua_affinity"));
/**
* {@code minecraft:thorns}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> THORNS = create(key("thorns"));
/**
* {@code minecraft:depth_strider}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> DEPTH_STRIDER = create(key("depth_strider"));
/**
* {@code minecraft:frost_walker}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> FROST_WALKER = create(key("frost_walker"));
/**
* {@code minecraft:binding_curse}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> BINDING_CURSE = create(key("binding_curse"));
/**
* {@code minecraft:soul_speed}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> SOUL_SPEED = create(key("soul_speed"));
/**
* {@code minecraft:swift_sneak}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> SWIFT_SNEAK = create(key("swift_sneak"));
/**
* {@code minecraft:sharpness}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> SHARPNESS = create(key("sharpness"));
/**
* {@code minecraft:smite}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> SMITE = create(key("smite"));
/**
* {@code minecraft:bane_of_arthropods}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> BANE_OF_ARTHROPODS = create(key("bane_of_arthropods"));
/**
* {@code minecraft:knockback}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> KNOCKBACK = create(key("knockback"));
/**
* {@code minecraft:fire_aspect}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> FIRE_ASPECT = create(key("fire_aspect"));
/**
* {@code minecraft:looting}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> LOOTING = create(key("looting"));
/**
* {@code minecraft:sweeping}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> SWEEPING = create(key("sweeping"));
/**
* {@code minecraft:efficiency}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> EFFICIENCY = create(key("efficiency"));
/**
* {@code minecraft:silk_touch}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> SILK_TOUCH = create(key("silk_touch"));
/**
* {@code minecraft:unbreaking}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> UNBREAKING = create(key("unbreaking"));
/**
* {@code minecraft:fortune}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> FORTUNE = create(key("fortune"));
/**
* {@code minecraft:power}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> POWER = create(key("power"));
/**
* {@code minecraft:punch}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> PUNCH = create(key("punch"));
/**
* {@code minecraft:flame}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> FLAME = create(key("flame"));
/**
* {@code minecraft:infinity}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> INFINITY = create(key("infinity"));
/**
* {@code minecraft:luck_of_the_sea}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> 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<Enchantment> LURE = create(key("lure"));
/**
* {@code minecraft:loyalty}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> LOYALTY = create(key("loyalty"));
/**
* {@code minecraft:impaling}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> IMPALING = create(key("impaling"));
/**
* {@code minecraft:riptide}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> RIPTIDE = create(key("riptide"));
/**
* {@code minecraft:channeling}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> CHANNELING = create(key("channeling"));
/**
* {@code minecraft:multishot}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> MULTISHOT = create(key("multishot"));
/**
* {@code minecraft:quick_charge}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> QUICK_CHARGE = create(key("quick_charge"));
/**
* {@code minecraft:piercing}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> PIERCING = create(key("piercing"));
/**
* {@code minecraft:mending}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> MENDING = create(key("mending"));
/**
* {@code minecraft:vanishing_curse}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<Enchantment> VANISHING_CURSE = create(key("vanishing_curse"));
private EnchantmentKeys() {
}
private static @NotNull TypedKey<Enchantment> create(final @NotNull Key key) {
return TypedKey.create(RegistryKey.ENCHANTMENT, key);
}
}

View File

@ -0,0 +1,266 @@
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.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.4")
@ApiStatus.Experimental
public final class MobEffectKeys {
/**
* {@code minecraft:speed}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> SPEED = create(key("speed"));
/**
* {@code minecraft:slowness}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> SLOWNESS = create(key("slowness"));
/**
* {@code minecraft:haste}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> HASTE = create(key("haste"));
/**
* {@code minecraft:mining_fatigue}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> MINING_FATIGUE = create(key("mining_fatigue"));
/**
* {@code minecraft:strength}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> STRENGTH = create(key("strength"));
/**
* {@code minecraft:instant_health}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> INSTANT_HEALTH = create(key("instant_health"));
/**
* {@code minecraft:instant_damage}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> INSTANT_DAMAGE = create(key("instant_damage"));
/**
* {@code minecraft:jump_boost}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> JUMP_BOOST = create(key("jump_boost"));
/**
* {@code minecraft:nausea}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> NAUSEA = create(key("nausea"));
/**
* {@code minecraft:regeneration}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> 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<PotionEffectType> RESISTANCE = create(key("resistance"));
/**
* {@code minecraft:fire_resistance}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> FIRE_RESISTANCE = create(key("fire_resistance"));
/**
* {@code minecraft:water_breathing}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> WATER_BREATHING = create(key("water_breathing"));
/**
* {@code minecraft:invisibility}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> INVISIBILITY = create(key("invisibility"));
/**
* {@code minecraft:blindness}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> BLINDNESS = create(key("blindness"));
/**
* {@code minecraft:night_vision}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> NIGHT_VISION = create(key("night_vision"));
/**
* {@code minecraft:hunger}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> HUNGER = create(key("hunger"));
/**
* {@code minecraft:weakness}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> WEAKNESS = create(key("weakness"));
/**
* {@code minecraft:poison}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> POISON = create(key("poison"));
/**
* {@code minecraft:wither}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> WITHER = create(key("wither"));
/**
* {@code minecraft:health_boost}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> HEALTH_BOOST = create(key("health_boost"));
/**
* {@code minecraft:absorption}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> ABSORPTION = create(key("absorption"));
/**
* {@code minecraft:saturation}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> SATURATION = create(key("saturation"));
/**
* {@code minecraft:glowing}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> GLOWING = create(key("glowing"));
/**
* {@code minecraft:levitation}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> 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<PotionEffectType> LUCK = create(key("luck"));
/**
* {@code minecraft:unluck}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> UNLUCK = create(key("unluck"));
/**
* {@code minecraft:slow_falling}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> SLOW_FALLING = create(key("slow_falling"));
/**
* {@code minecraft:conduit_power}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> CONDUIT_POWER = create(key("conduit_power"));
/**
* {@code minecraft:dolphins_grace}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> DOLPHINS_GRACE = create(key("dolphins_grace"));
/**
* {@code minecraft:bad_omen}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> BAD_OMEN = create(key("bad_omen"));
/**
* {@code minecraft:hero_of_the_village}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> HERO_OF_THE_VILLAGE = create(key("hero_of_the_village"));
/**
* {@code minecraft:darkness}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<PotionEffectType> DARKNESS = create(key("darkness"));
private MobEffectKeys() {
}
private static @NotNull TypedKey<PotionEffectType> create(final @NotNull Key key) {
return TypedKey.create(RegistryKey.MOB_EFFECT, key);
}
}

View File

@ -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.4")
@ApiStatus.Experimental
public final class MusicInstrumentKeys {
/**
* {@code minecraft:ponder_goat_horn}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MusicInstrument> PONDER_GOAT_HORN = create(key("ponder_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<MusicInstrument> SING_GOAT_HORN = create(key("sing_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<MusicInstrument> SEEK_GOAT_HORN = create(key("seek_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<MusicInstrument> FEEL_GOAT_HORN = create(key("feel_goat_horn"));
/**
* {@code minecraft:admire_goat_horn}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TypedKey<MusicInstrument> 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<MusicInstrument> CALL_GOAT_HORN = create(key("call_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<MusicInstrument> YEARN_GOAT_HORN = create(key("yearn_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<MusicInstrument> DREAM_GOAT_HORN = create(key("dream_goat_horn"));
private MusicInstrumentKeys() {
}
private static @NotNull TypedKey<MusicInstrument> create(final @NotNull Key key) {
return TypedKey.create(RegistryKey.INSTRUMENT, key);
}
}

View File

@ -8,11 +8,14 @@ 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.enchantments.Enchantment;
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 {
@ -23,6 +26,9 @@ public interface Generators {
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("MusicInstrumentKeys", 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),
new MobGoalGenerator("VanillaGoal", "com.destroystokyo.paper.entity.ai")
};

View File

@ -85,19 +85,22 @@ index 0000000000000000000000000000000000000000..2512dba27edfdccbc4430815b6cba048
+}
diff --git a/src/main/java/io/papermc/paper/registry/RegistryKey.java b/src/main/java/io/papermc/paper/registry/RegistryKey.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4b30b16ce4db754b958c493ad86d0863592c263
index 0000000000000000000000000000000000000000..5dde0eac9aa6354f71a910aff1d5e484deef0a5d
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java
@@ -0,0 +1,67 @@
@@ -0,0 +1,85 @@
+package io.papermc.paper.registry;
+
+import net.kyori.adventure.key.Keyed;
+import org.bukkit.GameEvent;
+import org.bukkit.MusicInstrument;
+import org.bukkit.block.Biome;
+import org.bukkit.enchantments.Enchantment;
+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;
+import org.jetbrains.annotations.ApiStatus;
+
+import static io.papermc.paper.registry.RegistryKeyImpl.create;
@ -131,6 +134,21 @@ index 0000000000000000000000000000000000000000..c4b30b16ce4db754b958c493ad86d086
+ * @see io.papermc.paper.registry.keys.StructureTypeKeys
+ */
+ RegistryKey<StructureType> STRUCTURE_TYPE = create("worldgen/structure_type");
+ /**
+ * Built-in registry for instruments.
+ * @see io.papermc.paper.registry.keys.MusicInstrumentKeys
+ */
+ RegistryKey<MusicInstrument> INSTRUMENT = create("instrument");
+ /**
+ * Built-in registry for enchantments.
+ * @see io.papermc.paper.registry.keys.EnchantmentKeys
+ */
+ RegistryKey<Enchantment> ENCHANTMENT = create("enchantment");
+ /**
+ * Built-in registry for potion effect types (mob effects).
+ * @see io.papermc.paper.registry.keys.MobEffectKeys
+ */
+ RegistryKey<PotionEffectType> MOB_EFFECT = create("mob_effect");
+
+ /* ********************** *
+ * Data-driven Registries *
@ -183,7 +201,7 @@ index 0000000000000000000000000000000000000000..9ad300fa1668cb59bbd85ff8091591db
+}
diff --git a/src/main/java/io/papermc/paper/registry/TypedKey.java b/src/main/java/io/papermc/paper/registry/TypedKey.java
new file mode 100644
index 0000000000000000000000000000000000000000..271454cd1b92ada4301025b57348ea77da9116a1
index 0000000000000000000000000000000000000000..6f5a062ba7ee7173468ecea3c1855a233bf3855e
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/TypedKey.java
@@ -0,0 +1,44 @@
@ -227,13 +245,13 @@ index 0000000000000000000000000000000000000000..271454cd1b92ada4301025b57348ea77
+ * @return a new key for the value key and registry key
+ */
+ @ApiStatus.Experimental
+ static <T extends Keyed> @NotNull TypedKey<T> create(final @NotNull RegistryKey<T> registryKey, final @NotNull Key key) {
+ static <T> @NotNull TypedKey<T> create(final @NotNull RegistryKey<T> registryKey, final @NotNull Key key) {
+ return new TypedKeyImpl<>(key, registryKey);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..3c3fd73f7742bb8602e2f9164dd4c1208a412255
index 0000000000000000000000000000000000000000..1a97b3359c4ece5c29131da7c3f208aaa8fab66e
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java
@@ -0,0 +1,8 @@
@ -243,7 +261,7 @@ index 0000000000000000000000000000000000000000..3c3fd73f7742bb8602e2f9164dd4c120
+import net.kyori.adventure.key.Keyed;
+import org.jetbrains.annotations.NotNull;
+
+record TypedKeyImpl<T extends Keyed>(@NotNull Key key, @NotNull RegistryKey<T> registryKey) implements TypedKey<T> {
+record TypedKeyImpl<T>(@NotNull Key key, @NotNull RegistryKey<T> registryKey) implements TypedKey<T> {
+}
diff --git a/src/main/java/org/bukkit/MinecraftExperimental.java b/src/main/java/org/bukkit/MinecraftExperimental.java
index b6f4810e387c22c4a70609ea1d605130245689a5..03824ae54e1bdb8b14f79b3c5e0294ae725e43f8 100644

View File

@ -164,47 +164,20 @@ index 0000000000000000000000000000000000000000..b89e19c070f97c9662f1e16309446494
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/RegistryKey.java b/src/main/java/io/papermc/paper/registry/RegistryKey.java
index c4b30b16ce4db754b958c493ad86d0863592c263..e376c95ac4db43a1c5233287f01b20b9c8b614bc 100644
index 5dde0eac9aa6354f71a910aff1d5e484deef0a5d..9908ab753e983fba6e827980de68e7cf6f6feb13 100644
--- a/src/main/java/io/papermc/paper/registry/RegistryKey.java
+++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java
@@ -2,11 +2,16 @@ package io.papermc.paper.registry;
import net.kyori.adventure.key.Keyed;
@@ -4,7 +4,9 @@ import net.kyori.adventure.key.Keyed;
import org.bukkit.GameEvent;
+import org.bukkit.MusicInstrument;
import org.bukkit.MusicInstrument;
import org.bukkit.block.Biome;
+import org.bukkit.damage.DamageType;
+import org.bukkit.enchantments.Enchantment;
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;
import org.jetbrains.annotations.ApiStatus;
import static io.papermc.paper.registry.RegistryKeyImpl.create;
@@ -40,6 +45,19 @@ public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
* @see io.papermc.paper.registry.keys.StructureTypeKeys
*/
RegistryKey<StructureType> STRUCTURE_TYPE = create("worldgen/structure_type");
+ /**
+ * Built-in registry for instruments.
+ */
+ RegistryKey<MusicInstrument> INSTRUMENT = create("instrument");
+ /**
+ * Built-in registry for enchantments.
+ */
+ RegistryKey<Enchantment> ENCHANTMENT = create("enchantment");
+ /**
+ * Built-in registry for potion effect types (mob effects).
+ */
+ RegistryKey<PotionEffectType> MOB_EFFECT = create("mob_effect");
+
/* ********************** *
* Data-driven Registries *
@@ -64,4 +82,12 @@ public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
@@ -82,4 +84,12 @@ public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
* @see io.papermc.paper.registry.keys.TrimPatternKeys
*/
RegistryKey<TrimPattern> TRIM_PATTERN = create("trim_pattern");
@ -237,30 +210,6 @@ index 9ad300fa1668cb59bbd85ff8091591db69b8c9dc..791813220b2504214b1adecc69093cd6
+ }
+
}
diff --git a/src/main/java/io/papermc/paper/registry/TypedKey.java b/src/main/java/io/papermc/paper/registry/TypedKey.java
index 271454cd1b92ada4301025b57348ea77da9116a1..6f5a062ba7ee7173468ecea3c1855a233bf3855e 100644
--- a/src/main/java/io/papermc/paper/registry/TypedKey.java
+++ b/src/main/java/io/papermc/paper/registry/TypedKey.java
@@ -38,7 +38,7 @@ public sealed interface TypedKey<T> extends Keyed permits TypedKeyImpl {
* @return a new key for the value key and registry key
*/
@ApiStatus.Experimental
- static <T extends Keyed> @NotNull TypedKey<T> create(final @NotNull RegistryKey<T> registryKey, final @NotNull Key key) {
+ static <T> @NotNull TypedKey<T> create(final @NotNull RegistryKey<T> registryKey, final @NotNull Key key) {
return new TypedKeyImpl<>(key, registryKey);
}
}
diff --git a/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java
index 3c3fd73f7742bb8602e2f9164dd4c1208a412255..1a97b3359c4ece5c29131da7c3f208aaa8fab66e 100644
--- a/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java
+++ b/src/main/java/io/papermc/paper/registry/TypedKeyImpl.java
@@ -4,5 +4,5 @@ import net.kyori.adventure.key.Key;
import net.kyori.adventure.key.Keyed;
import org.jetbrains.annotations.NotNull;
-record TypedKeyImpl<T extends Keyed>(@NotNull Key key, @NotNull RegistryKey<T> registryKey) implements TypedKey<T> {
+record TypedKeyImpl<T>(@NotNull Key key, @NotNull RegistryKey<T> registryKey) implements TypedKey<T> {
}
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 732ed3724e784ad659cb4411dbd73b42a8330a2c..cbf660db860e73df21be426e63928f8aeec0ac90 100644
--- a/src/main/java/org/bukkit/Bukkit.java

View File

@ -0,0 +1,398 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 2 Mar 2022 13:36:21 -0800
Subject: [PATCH] Registry Modification API
diff --git a/src/main/java/io/papermc/paper/registry/RegistryBuilder.java b/src/main/java/io/papermc/paper/registry/RegistryBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..2bec1f1d750e796e1d26c3cd090d53de2672170f
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/RegistryBuilder.java
@@ -0,0 +1,11 @@
+package io.papermc.paper.registry;
+
+import org.jetbrains.annotations.ApiStatus;
+
+/**
+ * To be implemented by any type used for modifying registries.
+ */
+@ApiStatus.NonExtendable
+@ApiStatus.Experimental
+public interface RegistryBuilder<T> {
+}
diff --git a/src/main/java/io/papermc/paper/registry/RegistryView.java b/src/main/java/io/papermc/paper/registry/RegistryView.java
new file mode 100644
index 0000000000000000000000000000000000000000..768f4370fc622b7a6c783fdd67a222f1e0570e1a
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/RegistryView.java
@@ -0,0 +1,20 @@
+package io.papermc.paper.registry;
+
+import net.kyori.adventure.key.Key;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Provides read-only access to a registry.
+ *
+ * @param <T> registry object type
+ */
+@ApiStatus.Experimental
+@ApiStatus.NonExtendable
+public interface RegistryView<T> extends Iterable<T> {
+
+ @Nullable T get(final @NotNull Key key);
+
+ @NotNull T getOrThrow(final @NotNull Key key);
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryAdditionEvent.java b/src/main/java/io/papermc/paper/registry/event/RegistryAdditionEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..e70e0b79f300f6453b8f5a76defdb2300360f688
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryAdditionEvent.java
@@ -0,0 +1,33 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.registry.RegistryBuilder;
+import io.papermc.paper.registry.TypedKey;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Event object for {@link RegistryEvents.Provider#addition()}. This
+ * event is fired right before a specific object is added to a registry.
+ * It provides a way for plugins to modify parts of this object.
+ *
+ * @param <T> object type
+ * @param <B> object builder type
+ */
+@ApiStatus.Experimental
+@ApiStatus.NonExtendable
+public interface RegistryAdditionEvent<T, B extends RegistryBuilder<T>> extends RegistryEvent<T> {
+
+ /**
+ * Gets the builder for the object being added to the registry.
+ *
+ * @return the object builder
+ */
+ @NotNull B builder();
+
+ /**
+ * Gets the key for this object in the registry.
+ *
+ * @return the key
+ */
+ @NotNull TypedKey<T> key();
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEvent.java b/src/main/java/io/papermc/paper/registry/event/RegistryEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4841b63fa4b6bf49d1e04339561d48ba8ae562d
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryEvent.java
@@ -0,0 +1,41 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
+import io.papermc.paper.registry.RegistryKey;
+import io.papermc.paper.registry.RegistryView;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Base type for all registry events.
+ *
+ * @param <T> object type
+ */
+@ApiStatus.Experimental
+@ApiStatus.NonExtendable
+public interface RegistryEvent<T> extends LifecycleEvent {
+
+ /**
+ * Get the key for the registry this event pertains to.
+ *
+ * @return the registry key
+ */
+ @NotNull RegistryKey<T> registryKey();
+
+ /**
+ * Get a view of the registry which may or may not
+ * be complete based on the event.
+ *
+ * @return a registry view
+ */
+ @NotNull RegistryView<T> registry();
+
+ /**
+ * Get the name of the event.
+ *
+ * @return the event name
+ */
+ default @NotNull String eventName() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEventProviderImpl.java b/src/main/java/io/papermc/paper/registry/event/RegistryEventProviderImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..0df562062e6468617597a49abf88e116dd693935
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryEventProviderImpl.java
@@ -0,0 +1,40 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
+import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfiguration;
+import io.papermc.paper.registry.RegistryBuilder;
+import io.papermc.paper.registry.RegistryKey;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+import org.jetbrains.annotations.ApiStatus;
+
+@ApiStatus.Internal
+@DefaultQualifier(NonNull.class)
+record RegistryEventProviderImpl<T, B extends RegistryBuilder<T>>(RegistryKey<T> registryKey) implements RegistryEvents.Provider<T, B> {
+
+ static <T, B extends RegistryBuilder<T>> RegistryEvents.Provider<T, B> create(final RegistryKey<T> registryKey) {
+ return new RegistryEventProviderImpl<>(registryKey);
+ }
+
+ @Override
+ public LifecycleEventType.Prioritizable<BootstrapContext, RegistryAdditionEvent<T, B>> addition() {
+ return RegistryEventTypeProvider.PROVIDER.registryAddition(this);
+ }
+
+ @Override
+ public PrioritizedLifecycleEventHandlerConfiguration<BootstrapContext> newAdditionHandler(final LifecycleEventHandler<? super RegistryAdditionEvent<T, B>> handler) {
+ return this.addition().newHandler(handler);
+ }
+
+ @Override
+ public LifecycleEventType.Prioritizable<BootstrapContext, RegistryPreFreezeEvent<T, B>> preFreeze() {
+ return RegistryEventTypeProvider.PROVIDER.registryPreFreeze(this);
+ }
+
+ @Override
+ public PrioritizedLifecycleEventHandlerConfiguration<BootstrapContext> newPreFreezeHandler(final LifecycleEventHandler<? super RegistryPreFreezeEvent<T, B>> handler) {
+ return this.preFreeze().newHandler(handler);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProvider.java b/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..118306c85e7c861a0c4010ba9e37f15ca49498a7
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProvider.java
@@ -0,0 +1,20 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
+import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
+import io.papermc.paper.registry.RegistryBuilder;
+import java.util.ServiceLoader;
+import org.jetbrains.annotations.ApiStatus;
+
+@ApiStatus.Internal
+interface RegistryEventTypeProvider {
+
+ RegistryEventTypeProvider PROVIDER = ServiceLoader.load(RegistryEventTypeProvider.class)
+ .findFirst()
+ .orElseThrow();
+
+
+ <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryAdditionEvent<T, B>> registryAddition(RegistryEvents.Provider<T, B> type);
+
+ <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryPreFreezeEvent<T, B>> registryPreFreeze(RegistryEvents.Provider<T, B> type);
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java b/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java
new file mode 100644
index 0000000000000000000000000000000000000000..0df2045dab9b19f5456a8946e0b827cbdcf31159
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java
@@ -0,0 +1,87 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.LifecycleEventHandlerConfiguration;
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfiguration;
+import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
+import io.papermc.paper.registry.RegistryBuilder;
+import io.papermc.paper.registry.RegistryKey;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+import static io.papermc.paper.registry.event.RegistryEventProviderImpl.create;
+
+/**
+ * Holds providers for {@link RegistryAdditionEvent} and {@link RegistryPreFreezeEvent}
+ * handlers for each applicable registry.
+ */
+@ApiStatus.Experimental
+public final class RegistryEvents {
+
+
+ /**
+ * Provider for each registry event type for a specific registry.
+ *
+ * @param <T> object type
+ * @param <B> object builder type
+ */
+ @ApiStatus.Experimental
+ @ApiStatus.NonExtendable
+ public interface Provider<T, B extends RegistryBuilder<T>> {
+
+ /**
+ * Gets the event type for {@link RegistryAdditionEvent} which is fired just before
+ * an object is added to a registry.
+ * <p>
+ * Can be used in {@link io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager#registerEventHandler(LifecycleEventType, LifecycleEventHandler)}
+ * to register a handler for {@link RegistryAdditionEvent}.
+ *
+ * @return the addition event type
+ */
+ LifecycleEventType.@NotNull Prioritizable<BootstrapContext, RegistryAdditionEvent<T, B>> addition();
+
+ /**
+ * Shortcut for calling {@link #addition()} followed by {@link LifecycleEventType#newHandler(LifecycleEventHandler)}.
+ * <p>
+ * Can be used in {@link io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager#registerEventHandler(LifecycleEventHandlerConfiguration)}
+ * to register a handler for {@link RegistryAdditionEvent}
+ *
+ * @param handler the event handler for {@link RegistryAdditionEvent}
+ * @return the configuration for further use
+ */
+ @NotNull PrioritizedLifecycleEventHandlerConfiguration<BootstrapContext> newAdditionHandler(@NotNull LifecycleEventHandler<? super RegistryAdditionEvent<T, B>> handler);
+
+ /**
+ * Gets the event type for {@link RegistryPreFreezeEvent} which is fired just before
+ * a registry is frozen. It allows for the registration of new objects.
+ * <p>
+ * Can be used in {@link io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager#registerEventHandler(LifecycleEventType, LifecycleEventHandler)}
+ * to register a handler for {@link RegistryPreFreezeEvent}.
+ *
+ * @return the pre-freeze event type
+ */
+ LifecycleEventType.@NotNull Prioritizable<BootstrapContext, RegistryPreFreezeEvent<T, B>> preFreeze();
+
+ /**
+ * Shortcut for calling {@link #preFreeze()} followed by {@link LifecycleEventType#newHandler(LifecycleEventHandler)}.
+ * <p>
+ * Can be used in {@link io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager#registerEventHandler(LifecycleEventHandlerConfiguration)}
+ * to register a handler for {@link RegistryPreFreezeEvent}
+ *
+ * @param handler the event handler for {@link RegistryPreFreezeEvent}
+ * @return the configuration for further use
+ */
+ @NotNull PrioritizedLifecycleEventHandlerConfiguration<BootstrapContext> newPreFreezeHandler(@NotNull LifecycleEventHandler<? super RegistryPreFreezeEvent<T, B>> handler);
+
+ /**
+ * Gets the registry key associated with this event type provider.
+ *
+ * @return the registry key
+ */
+ @NotNull RegistryKey<T> registryKey();
+ }
+
+ private RegistryEvents() {
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryPreFreezeEvent.java b/src/main/java/io/papermc/paper/registry/event/RegistryPreFreezeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ca6cc14b544399e32477c5fbe8b58f3bb4f55c4
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryPreFreezeEvent.java
@@ -0,0 +1,27 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.registry.RegistryBuilder;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Event object for {@link RegistryEvents.Provider#preFreeze()}. This
+ * event is fired right before a registry is frozen disallowing further changes.
+ * It provides a way for plugins to add new objects to the registry.
+ *
+ * @param <T> object type
+ * @param <B> object builder type
+ */
+@ApiStatus.Experimental
+@ApiStatus.NonExtendable
+public interface RegistryPreFreezeEvent<T, B extends RegistryBuilder<T>> extends RegistryEvent<T> {
+
+ /**
+ * Get a view of the registry which supports
+ * the registering of new values.
+ *
+ * @return a writable registry view
+ */
+ @Override
+ @NotNull WritableRegistry<T, B> registry();
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/WritableRegistry.java b/src/main/java/io/papermc/paper/registry/event/WritableRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..3cab150544f2bd7f8dd483f638817e5a36f462ed
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/WritableRegistry.java
@@ -0,0 +1,27 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.registry.RegistryBuilder;
+import io.papermc.paper.registry.RegistryView;
+import io.papermc.paper.registry.TypedKey;
+import java.util.function.Consumer;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A registry view which supports registering new objects.
+ *
+ * @param <T> object type
+ * @param <B> object builder type
+ */
+@ApiStatus.NonExtendable
+@ApiStatus.Experimental
+public interface WritableRegistry<T, B extends RegistryBuilder<T>> extends RegistryView<T> {
+
+ /**
+ * Register a new value with the specified key.
+ *
+ * @param key the object's key (must be unique from others)
+ * @param value a consumer for the object's builder
+ */
+ void register(@NotNull TypedKey<T> key, @NotNull Consumer<? super B> value);
+}
diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java
index c63a2d5d21eb599939ec7ae5e57506ff746e4174..6aecb2d04479439d9d133f723ef160a693f699c6 100644
--- a/src/main/java/org/bukkit/Registry.java
+++ b/src/main/java/org/bukkit/Registry.java
@@ -331,6 +331,27 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
*/
@Nullable
T get(@NotNull NamespacedKey key);
+ // Paper start
+ /**
+ * Get the object by its key.
+ *
+ * @param key non-null key
+ * @return item or null if it does not exist
+ */
+ default @Nullable T get(final net.kyori.adventure.key.@NotNull Key key) {
+ return key instanceof final NamespacedKey nsKey ? this.get(nsKey) : this.get(new NamespacedKey(key.namespace(), key.value()));
+ }
+
+ /**
+ * Get the object by its typed key.
+ *
+ * @param typedKey non-null typed key
+ * @return item or null if it does not exist
+ */
+ default @Nullable T get(final io.papermc.paper.registry.@NotNull TypedKey<T> typedKey) {
+ return this.get(typedKey.key());
+ }
+ // Paper end
// Paper start - improve Registry
/**

View File

@ -0,0 +1,85 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 25 Feb 2023 21:26:44 -0800
Subject: [PATCH] Support registry mod API with GameEvent
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java b/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java
index 0df2045dab9b19f5456a8946e0b827cbdcf31159..b222103a73d388d5cf7eb088db1de06b582dea7d 100644
--- a/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java
@@ -7,6 +7,7 @@ import io.papermc.paper.plugin.lifecycle.event.handler.configuration.Prioritized
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
import io.papermc.paper.registry.RegistryBuilder;
import io.papermc.paper.registry.RegistryKey;
+import org.bukkit.GameEvent;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -19,6 +20,7 @@ import static io.papermc.paper.registry.event.RegistryEventProviderImpl.create;
@ApiStatus.Experimental
public final class RegistryEvents {
+ public static final Provider<GameEvent, GameEvent.Builder> GAME_EVENT = create(RegistryKey.GAME_EVENT);
/**
* Provider for each registry event type for a specific registry.
diff --git a/src/main/java/org/bukkit/GameEvent.java b/src/main/java/org/bukkit/GameEvent.java
index 6c9689baca1763e2ef79495d38618d587e792434..fd9ccb69f99ae77da66583770e994cd958fd4bf9 100644
--- a/src/main/java/org/bukkit/GameEvent.java
+++ b/src/main/java/org/bukkit/GameEvent.java
@@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable;
/**
* Represents a generic Mojang game event.
*/
+@org.checkerframework.framework.qual.DefaultQualifier(NotNull.class) // Paper
public abstract class GameEvent implements Keyed {
public static final GameEvent BLOCK_ACTIVATE = getEvent("block_activate");
@@ -147,4 +148,46 @@ public abstract class GameEvent implements Keyed {
return gameEvent;
}
+
+ // Paper start
+ /**
+ * Gets the range of the event which is used to
+ * notify listeners of the event.
+ *
+ * @return the range
+ */
+ public abstract int getRange();
+
+ /**
+ * Gets the vibration level of the game event for vibration listeners.
+ * Not all events have vibration levels, and a level of 0 means
+ * it won't cause any vibrations.
+ *
+ * @return the vibration level
+ */
+ public abstract int getVibrationLevel();
+
+ @org.jetbrains.annotations.ApiStatus.Experimental
+ @org.jetbrains.annotations.ApiStatus.NonExtendable
+ public interface Builder extends io.papermc.paper.registry.RegistryBuilder<GameEvent> {
+
+ /**
+ * Gets the range of the event which is used to
+ * notify listeners of the event.
+ *
+ * @return the range
+ */
+ int range();
+
+ /**
+ * Sets the range of the event which is used to
+ * notify listeners of the event.
+ *
+ * @param range the range
+ * @return the builder
+ */
+ @org.jetbrains.annotations.Contract("_ -> this")
+ @NotNull Builder range(int range);
+ }
+ // Paper end
}

View File

@ -760,16 +760,18 @@ index 0000000000000000000000000000000000000000..b38e1e0f3d3055086f51bb191fd4b60e
+}
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/LaunchEntryPointHandler.java b/src/main/java/io/papermc/paper/plugin/entrypoint/LaunchEntryPointHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c0f2c315387734f8dd4a7eca633aa0a9856dd17
index 0000000000000000000000000000000000000000..48bc745ca9632fc46b5f786ff570434702eb47f2
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/LaunchEntryPointHandler.java
@@ -0,0 +1,65 @@
@@ -0,0 +1,74 @@
+package io.papermc.paper.plugin.entrypoint;
+
+import io.papermc.paper.plugin.provider.PluginProvider;
+import io.papermc.paper.plugin.storage.BootstrapProviderStorage;
+import io.papermc.paper.plugin.storage.ProviderStorage;
+import io.papermc.paper.plugin.storage.ServerPluginProviderStorage;
+import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
+import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.HashMap;
@ -782,9 +784,11 @@ index 0000000000000000000000000000000000000000..6c0f2c315387734f8dd4a7eca633aa0a
+
+ public static final LaunchEntryPointHandler INSTANCE = new LaunchEntryPointHandler();
+ private final Map<Entrypoint<?>, ProviderStorage<?>> storage = new HashMap<>();
+ private final Object2BooleanMap<Entrypoint<?>> enteredMap = new Object2BooleanOpenHashMap<>();
+
+ LaunchEntryPointHandler() {
+ this.populateProviderStorage();
+ this.enteredMap.defaultReturnValue(false);
+ }
+
+ // Utility
@ -800,6 +804,7 @@ index 0000000000000000000000000000000000000000..6c0f2c315387734f8dd4a7eca633aa0a
+ }
+
+ storage.enter();
+ this.enteredMap.put(entrypoint, true);
+ }
+
+ @Override
@ -823,6 +828,10 @@ index 0000000000000000000000000000000000000000..6c0f2c315387734f8dd4a7eca633aa0a
+ return storage;
+ }
+
+ public boolean hasEntered(Entrypoint<?> entrypoint) {
+ return this.enteredMap.getBoolean(entrypoint);
+ }
+
+ // Reload only
+ public void populateProviderStorage() {
+ this.storage.put(Entrypoint.BOOTSTRAPPER, new BootstrapProviderStorage());
@ -7208,17 +7217,24 @@ index bc91370654f5da33cbfe7d42431568915c1159d6..b43af53960978ac04bccde08544a5628
validate(REGISTRY);
}
diff --git a/src/main/java/net/minecraft/server/Bootstrap.java b/src/main/java/net/minecraft/server/Bootstrap.java
index 15ee2f2a83bfef2f6891d9bfb2d3a8c14b24ffb1..d0d95d729853fc296c4931a2f73a3fc5f94302c9 100644
index 15ee2f2a83bfef2f6891d9bfb2d3a8c14b24ffb1..bae46c0c18d4394849ac8e68e59a6cdd6ebfb4cc 100644
--- a/src/main/java/net/minecraft/server/Bootstrap.java
+++ b/src/main/java/net/minecraft/server/Bootstrap.java
@@ -74,7 +74,11 @@ public class Bootstrap {
@@ -66,6 +66,7 @@ public class Bootstrap {
if (BuiltInRegistries.REGISTRY.keySet().isEmpty()) {
throw new IllegalStateException("Unable to load registries");
} else {
+ io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.enterBootstrappers(); // Paper - Entrypoint for bootstrapping (before any registry is populated)
FireBlock.bootStrap();
ComposterBlock.bootStrap();
if (EntityType.getKey(EntityType.PLAYER) == null) {
@@ -74,7 +75,10 @@ public class Bootstrap {
EntitySelectorOptions.bootStrap();
DispenseItemBehavior.bootStrap();
CauldronInteraction.bootStrap();
- BuiltInRegistries.bootStrap();
+ // Paper start
+ BuiltInRegistries.bootStrap(() -> {
+ io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.enterBootstrappers(); // Paper - Entrypoint for bootstrapping
+ });
+ // Paper end
CreativeModeTabs.validate();

View File

@ -105,17 +105,17 @@ index 0000000000000000000000000000000000000000..e0d73113c937ddbcf8144f88b15a8d3d
+ }
+}
diff --git a/src/main/java/net/minecraft/server/Bootstrap.java b/src/main/java/net/minecraft/server/Bootstrap.java
index 05f4be8dfff37ab6804a2d990b1f8c430d42dc7c..2a49a6a6bccabf588ba67b565d8f16fda04ba0b0 100644
index 8ffc3b27b98de3a73bccdb9bb4fe5a47d2781d4e..c66afe7c6734756b00265599bf17ad29203996db 100644
--- a/src/main/java/net/minecraft/server/Bootstrap.java
+++ b/src/main/java/net/minecraft/server/Bootstrap.java
@@ -76,6 +76,7 @@ public class Bootstrap {
@@ -77,6 +77,7 @@ public class Bootstrap {
CauldronInteraction.bootStrap();
// 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 dc765b92cc90f5f370254e68bbbdfa5add7935ce..8ce870a5341a61fbbaf42021ef7f7f615a6a3e09 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java

View File

@ -0,0 +1,913 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 27 Feb 2023 18:28:39 -0800
Subject: [PATCH] Registry Modification API
== AT ==
public net.minecraft.server.RegistryLayer STATIC_ACCESS
public net.minecraft.core.MappedRegistry validateWrite(Lnet/minecraft/resources/ResourceKey;)V
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
index e3c16b2aee3da74c43c52a20f52fcde066f0d90d..5c246637630b9e85b710b41a522ba2de2aad5475 100644
--- a/src/main/java/io/papermc/paper/registry/PaperRegistries.java
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
@@ -34,6 +34,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.DefaultQualifier;
import static io.papermc.paper.registry.entry.RegistryEntry.entry;
+import static io.papermc.paper.registry.entry.RegistryEntry.writable;
@DefaultQualifier(NonNull.class)
public final class PaperRegistries {
@@ -51,7 +52,7 @@ public final class PaperRegistries {
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),
+ writable(Registries.GAME_EVENT, RegistryKey.GAME_EVENT, GameEvent.class, CraftGameEvent::new, CraftGameEvent.Builder::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),
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
index db6aa01babce66cbfe95b0f758d2bcec4d7351dc..9cecc6a9ed2a660c8967786ac0a31118349095e1 100644
--- a/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
@@ -80,6 +80,14 @@ public class PaperRegistryAccess implements RegistryAccess {
return possiblyUnwrap(registryHolder.get());
}
+ public <M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> WritableCraftRegistry<M, T, B> getWritableRegistry(final RegistryKey<T> key) {
+ final Registry<T> registry = this.getRegistry(key);
+ if (registry instanceof WritableCraftRegistry<?, T, ?>) {
+ return (WritableCraftRegistry<M, T, B>) registry;
+ }
+ throw new IllegalArgumentException(key + " does not point to a writable registry");
+ }
+
private static <T extends Keyed> Registry<T> possiblyUnwrap(final Registry<T> registry) {
if (registry instanceof final DelayedRegistry<T, ?> delayedRegistry) { // if not coming from legacy, unwrap the delayed registry
return delayedRegistry.delegate();
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryBuilder.java b/src/main/java/io/papermc/paper/registry/PaperRegistryBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..4cf32102a134ebef67d3893cfd24bf0add321eb9
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistryBuilder.java
@@ -0,0 +1,24 @@
+package io.papermc.paper.registry;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public interface PaperRegistryBuilder<M, T> extends RegistryBuilder<T> {
+
+ M build();
+
+ @FunctionalInterface
+ interface Filler<M, T, B extends PaperRegistryBuilder<M, T>> {
+
+ B fill(final TypedKey<T> key, final @Nullable M nms);
+
+ default Factory<M, T, B> asFactory() {
+ return key -> this.fill(key, null);
+ }
+ }
+
+ @FunctionalInterface
+ interface Factory<M, T, B extends PaperRegistryBuilder<M, T>> {
+
+ B create(final TypedKey<T> key);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java b/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..4291d875a2df5c75d648c02e7607b3fab82f8c63
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java
@@ -0,0 +1,169 @@
+package io.papermc.paper.registry;
+
+import com.google.common.base.Preconditions;
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
+import io.papermc.paper.plugin.entrypoint.Entrypoint;
+import io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler;
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner;
+import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
+import io.papermc.paper.registry.entry.RegistryEntry;
+import io.papermc.paper.registry.entry.RegistryEntryInfo;
+import io.papermc.paper.registry.event.RegistryAdditionEvent;
+import io.papermc.paper.registry.event.RegistryAdditionEventImpl;
+import io.papermc.paper.registry.event.RegistryEventMap;
+import io.papermc.paper.registry.event.RegistryEvents;
+import io.papermc.paper.registry.event.RegistryPreFreezeEvent;
+import io.papermc.paper.registry.event.RegistryPreFreezeEventImpl;
+import net.kyori.adventure.key.Key;
+import net.minecraft.core.Holder;
+import net.minecraft.core.MappedRegistry;
+import net.minecraft.core.RegistrationInfo;
+import net.minecraft.core.Registry;
+import net.minecraft.core.WritableRegistry;
+import net.minecraft.resources.ResourceKey;
+import net.minecraft.resources.ResourceLocation;
+import org.bukkit.craftbukkit.CraftRegistry;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.intellij.lang.annotations.Subst;
+
+public final class PaperRegistryListenerManager {
+
+ public static final PaperRegistryListenerManager INSTANCE = new PaperRegistryListenerManager();
+
+ public final RegistryEventMap additionHooks = new RegistryEventMap("addition");
+ public final RegistryEventMap preFreezeHooks = new RegistryEventMap("pre-freeze");
+
+ private PaperRegistryListenerManager() {
+ }
+
+ /**
+ * For {@link Registry#register(Registry, String, Object)}
+ */
+ public <M> M registerWithListeners(final Registry<M> registry, final String id, final M nms) {
+ return this.registerWithListeners(registry, new ResourceLocation(id), nms);
+ }
+
+ /**
+ * For {@link Registry#register(Registry, ResourceLocation, Object)}
+ */
+ public <M> M registerWithListeners(final Registry<M> registry, final ResourceLocation loc, final M nms) {
+ return this.registerWithListeners(registry, ResourceKey.create(registry.key(), loc), nms);
+ }
+
+ /**
+ * For {@link Registry#register(Registry, ResourceKey, Object)}
+ */
+ public <M> M registerWithListeners(final Registry<M> registry, final ResourceKey<M> key, final M nms) {
+ return this.registerWithListeners(registry, key, nms, RegistrationInfo.BUILT_IN, PaperRegistryListenerManager::registerWithInstance);
+ }
+
+ /**
+ * For {@link Registry#registerForHolder(Registry, ResourceLocation, Object)}
+ */
+ public <M> Holder.Reference<M> registerForHolderWithListeners(final Registry<M> registry, final ResourceLocation loc, final M nms) {
+ return this.registerForHolderWithListeners(registry, ResourceKey.create(registry.key(), loc), nms);
+ }
+
+ /**
+ * For {@link Registry#registerForHolder(Registry, ResourceKey, Object)}
+ */
+ public <M> Holder.Reference<M> registerForHolderWithListeners(final Registry<M> registry, final ResourceKey<M> key, final M nms) {
+ return this.registerWithListeners(registry, key, nms, RegistrationInfo.BUILT_IN, WritableRegistry::register);
+ }
+
+ public <M, T extends org.bukkit.Keyed, B extends PaperRegistryBuilder<M, T>> void registerWithListeners(
+ final Registry<M> registry,
+ final ResourceKey<M> key,
+ final M nms,
+ final RegistrationInfo registrationInfo
+ ) {
+ this.registerWithListeners(registry, key, nms, registrationInfo, WritableRegistry::register);
+ }
+
+ public <M, T extends org.bukkit.Keyed, B extends PaperRegistryBuilder<M, T>, R> R registerWithListeners(
+ final Registry<M> registry,
+ final ResourceKey<M> key,
+ final M nms,
+ final RegistrationInfo registrationInfo,
+ final RegisterMethod<M, R> registerMethod
+ ) {
+ Preconditions.checkState(LaunchEntryPointHandler.INSTANCE.hasEntered(Entrypoint.BOOTSTRAPPER), registry.key() + " tried to run modification listeners before bootstrappers have been called"); // verify that bootstrappers have been called
+ final @Nullable RegistryEntryInfo<M, T> entry = PaperRegistries.getEntry(registry.key());
+ if (!(entry instanceof RegistryEntry.Modifiable<?, ?, ?>) || !this.additionHooks.hasHooks(entry.apiKey())) {
+ return registerMethod.register((WritableRegistry<M>) registry, key, nms, registrationInfo);
+ }
+ final RegistryEntry.Modifiable<M, T, B> modifiableEntry = (RegistryEntry.Modifiable<M, T, B>) entry;
+ final CraftRegistry<T, M> craftRegistry = (CraftRegistry<T, M>) PaperRegistryAccess.instance().getRegistry(entry.apiKey());
+ @SuppressWarnings("PatternValidation") final TypedKey<T> typedKey = TypedKey.create(entry.apiKey(), Key.key(key.location().getNamespace(), key.location().getPath()));
+ final B builder = modifiableEntry.fillBuilder(typedKey, nms);
+ return this.registerWithListeners(registry, craftRegistry.view, modifiableEntry, key, nms, builder, registrationInfo, registerMethod);
+ }
+
+ public <M, T extends org.bukkit.Keyed, B extends PaperRegistryBuilder<M, T>> void registerWithListeners(
+ final Registry<M> registry,
+ final RegistryView<T> registryView,
+ final RegistryEntry.Modifiable<M, T, B> entry,
+ final ResourceKey<M> key,
+ final @Nullable M oldNms,
+ final B builder,
+ final RegistrationInfo registrationInfo
+ ) {
+ this.registerWithListeners(registry, registryView, entry, key, oldNms, builder, registrationInfo, WritableRegistry::register);
+ }
+
+ public <M, T extends org.bukkit.Keyed, B extends PaperRegistryBuilder<M, T>, R> R registerWithListeners(
+ final Registry<M> registry,
+ final RegistryView<T> registryView,
+ final RegistryEntry.Modifiable<M, T, B> entry,
+ final ResourceKey<M> key,
+ final @Nullable M oldNms,
+ final B builder,
+ final RegistrationInfo registrationInfo,
+ final RegisterMethod<M, R> registerMethod
+ ) {
+ @Subst("namespace:key") final ResourceLocation beingAdded = key.location();
+ @SuppressWarnings("PatternValidation") final TypedKey<T> typedKey = TypedKey.create(entry.apiKey(), Key.key(beingAdded.getNamespace(), beingAdded.getPath()));
+ final RegistryAdditionEventImpl<T, B> event = entry.createAdditionEvent(typedKey, builder, registryView);
+ LifecycleEventRunner.INSTANCE.callEvent(this.additionHooks.getHook(entry.apiKey()), event);
+ if (oldNms != null) {
+ ((MappedRegistry<M>) registry).clearIntrusiveHolder(oldNms);
+ }
+ final M newNms = event.builder().build();
+ return registerMethod.register((WritableRegistry<M>) registry, key, newNms, registrationInfo);
+ }
+
+ private static <M> M registerWithInstance(final WritableRegistry<M> writableRegistry, final ResourceKey<M> key, final M value, final RegistrationInfo registrationInfo) {
+ writableRegistry.register(key, value, registrationInfo);
+ return value;
+ }
+
+ @FunctionalInterface
+ public interface RegisterMethod<M, R> {
+
+ R register(WritableRegistry<M> writableRegistry, ResourceKey<M> key, M value, RegistrationInfo registrationInfo);
+ }
+
+ public <M, T extends org.bukkit.Keyed, B extends PaperRegistryBuilder<M, T>> void runFreezeListeners(final ResourceKey<? extends Registry<M>> resourceKey) {
+ final @Nullable RegistryEntryInfo<M, T> entry = PaperRegistries.getEntry(resourceKey);
+ if (!(entry instanceof RegistryEntry.Writable<?, ?, ?>) || !this.preFreezeHooks.hasHooks(entry.apiKey())) {
+ return;
+ }
+ final RegistryEntry.Writable<M, T, B> writableEntry = (RegistryEntry.Writable<M, T, B>) entry;
+ final RegistryPreFreezeEventImpl<T, B> event = writableEntry.createPreFreezeEvent(PaperRegistryAccess.instance().getWritableRegistry(entry.apiKey()));
+ LifecycleEventRunner.INSTANCE.callEvent(this.preFreezeHooks.getHook(entry.apiKey()), event);
+ }
+
+ public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryAdditionEvent<T, B>> getRegistryAdditionEventType(final RegistryEvents.Provider<T, B> type) {
+ if (!(PaperRegistries.getEntry(type.registryKey()) instanceof RegistryEntry.Modifiable)) {
+ throw new IllegalArgumentException(type.registryKey() + " does not support RegistryAdditionEvent");
+ }
+ return this.additionHooks.getOrCreate(type);
+ }
+
+ public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryPreFreezeEvent<T, B>> getRegistryPreFreezeEventType(final RegistryEvents.Provider<T, B> type) {
+ if (!(PaperRegistries.getEntry(type.registryKey()) instanceof RegistryEntry.Writable)) {
+ throw new IllegalArgumentException(type.registryKey() + " does not support RegistryPreFreezeEvent");
+ }
+ return this.preFreezeHooks.getOrCreate(type);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/SimpleWritableCraftRegistry.java b/src/main/java/io/papermc/paper/registry/SimpleWritableCraftRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c18f50e5599d12cdec5e978020eb5ad53892b90
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/SimpleWritableCraftRegistry.java
@@ -0,0 +1,31 @@
+package io.papermc.paper.registry;
+
+import io.papermc.paper.registry.entry.RegistryEntry;
+import io.papermc.paper.registry.entry.WritableRegistryEntry;
+import java.util.function.BiFunction;
+import net.minecraft.core.MappedRegistry;
+import net.minecraft.core.Registry;
+import org.bukkit.Keyed;
+import org.bukkit.NamespacedKey;
+
+public final class SimpleWritableCraftRegistry<M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> extends WritableCraftRegistry<M, T, B> {
+
+ private final PaperRegistryBuilder.Factory<M, T, ? extends B> builderFactory;
+ private final BiFunction<? super NamespacedKey, M, T> minecraftToBukkit;
+
+ public SimpleWritableCraftRegistry(final WritableRegistryEntry<M, T, B> entry, final Registry<M> nmsRegistry, final PaperRegistryBuilder.Factory<M, T, ? extends B> builderFactory, final BiFunction<? super NamespacedKey, M, T> minecraftToBukkit) {
+ super(entry, (MappedRegistry<M>) nmsRegistry);
+ this.builderFactory = builderFactory;
+ this.minecraftToBukkit = minecraftToBukkit;
+ }
+
+ @Override
+ public T minecraftToBukkit(final NamespacedKey namespacedKey, final M minecraft) {
+ return this.minecraftToBukkit.apply(namespacedKey, minecraft);
+ }
+
+ @Override
+ public B newBuilder(final TypedKey<T> key) {
+ return this.builderFactory.create(key);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/WritableCraftRegistry.java b/src/main/java/io/papermc/paper/registry/WritableCraftRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..89594ca9a2e955785e8a4dfd66dc1f45d9efe065
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/WritableCraftRegistry.java
@@ -0,0 +1,59 @@
+package io.papermc.paper.registry;
+
+import com.mojang.serialization.Lifecycle;
+import io.papermc.paper.adventure.PaperAdventure;
+import io.papermc.paper.registry.entry.RegistryEntry;
+import io.papermc.paper.registry.event.PaperWritableRegistry;
+import io.papermc.paper.registry.event.WritableRegistry;
+import java.util.Optional;
+import java.util.function.Consumer;
+import net.minecraft.core.MappedRegistry;
+import net.minecraft.core.RegistrationInfo;
+import net.minecraft.resources.ResourceKey;
+import org.bukkit.Keyed;
+import org.bukkit.NamespacedKey;
+import org.bukkit.craftbukkit.CraftRegistry;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public abstract class WritableCraftRegistry<M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> extends CraftRegistry<T, M> {
+
+ private static final RegistrationInfo FROM_PLUGIN = new RegistrationInfo(Optional.empty(), Lifecycle.experimental());
+
+ private final RegistryEntry.Writable<M, T, B> entry;
+ private final MappedRegistry<M> registry;
+ public final WritableRegistry<T, B> modifiableView;
+
+ public WritableCraftRegistry(final RegistryEntry.Writable<M, T, B> entry, final MappedRegistry<M> registry) {
+ super(entry.toPreload(), registry, null);
+ this.entry = entry;
+ this.registry = registry;
+ this.modifiableView = new PaperWritableRegistry<>(this.registry, this);
+ }
+
+ public void register(final TypedKey<T> key, final Consumer<? super B> value) {
+ final ResourceKey<M> resourceKey = ResourceKey.create(this.registry.key(), PaperAdventure.asVanilla(key.key()));
+ this.registry.validateWrite(resourceKey);
+ final B builder = this.newBuilder(key);
+ value.accept(builder);
+ PaperRegistryListenerManager.INSTANCE.registerWithListeners(this.registry,
+ this.view,
+ this.entry,
+ resourceKey,
+ null,
+ builder,
+ FROM_PLUGIN
+ );
+ }
+
+ @Override
+ public final @Nullable T createBukkit(final NamespacedKey namespacedKey, final @Nullable M minecraft) {
+ if (minecraft == null) {
+ return null;
+ }
+ return this.minecraftToBukkit(namespacedKey, minecraft);
+ }
+
+ public abstract T minecraftToBukkit(NamespacedKey namespacedKey, M minecraft);
+
+ protected abstract B newBuilder(TypedKey<T> key);
+}
diff --git a/src/main/java/io/papermc/paper/registry/entry/ModifiableRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/ModifiableRegistryEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd130cc1e0d36196b98f4949aaa966bcaec9c953
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/entry/ModifiableRegistryEntry.java
@@ -0,0 +1,38 @@
+package io.papermc.paper.registry.entry;
+
+import io.papermc.paper.registry.PaperRegistryBuilder;
+import io.papermc.paper.registry.RegistryKey;
+import io.papermc.paper.registry.RegistryView;
+import io.papermc.paper.registry.TypedKey;
+import io.papermc.paper.registry.event.RegistryAdditionEventImpl;
+import java.util.function.BiFunction;
+import net.minecraft.core.Registry;
+import net.minecraft.resources.ResourceKey;
+import org.bukkit.Keyed;
+import org.bukkit.NamespacedKey;
+
+public class ModifiableRegistryEntry<M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> extends CraftRegistryEntry<M, T> implements RegistryEntry.Modifiable<M, T, B> {
+
+ protected final PaperRegistryBuilder.Filler<M, T, B> builderFiller;
+
+ protected ModifiableRegistryEntry(
+ final ResourceKey<? extends Registry<M>> mcKey,
+ final RegistryKey<T> apiKey,
+ final Class<?> toPreload,
+ final BiFunction<NamespacedKey, M, T> minecraftToBukkit,
+ final PaperRegistryBuilder.Filler<M, T, B> builderFiller
+ ) {
+ super(mcKey, apiKey, toPreload, minecraftToBukkit);
+ this.builderFiller = builderFiller;
+ }
+
+ @Override
+ public RegistryAdditionEventImpl<T, B> createAdditionEvent(final TypedKey<T> key, final B initialBuilder, final RegistryView<T> view) {
+ return new RegistryAdditionEventImpl<>(key, initialBuilder, this.apiKey(), view);
+ }
+
+ @Override
+ public B fillBuilder(final TypedKey<T> key, final M nms) {
+ return this.builderFiller.fill(key, nms);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java
index 9cda87cd03a04998cb527a4be9d3950523646cd3..5a108fd327c7cb223627e0e44791f0cf0392fd3b 100644
--- a/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java
+++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java
@@ -1,7 +1,14 @@
package io.papermc.paper.registry.entry;
+import io.papermc.paper.registry.PaperRegistryBuilder;
import io.papermc.paper.registry.RegistryHolder;
import io.papermc.paper.registry.RegistryKey;
+import io.papermc.paper.registry.RegistryView;
+import io.papermc.paper.registry.TypedKey;
+import io.papermc.paper.registry.WritableCraftRegistry;
+import io.papermc.paper.registry.event.RegistryAdditionEventImpl;
+import io.papermc.paper.registry.event.RegistryPreFreezeEventImpl;
+import io.papermc.paper.registry.event.WritableRegistry;
import io.papermc.paper.registry.legacy.DelayedRegistryEntry;
import java.util.function.BiFunction;
import net.minecraft.core.Registry;
@@ -27,7 +34,38 @@ public interface RegistryEntry<M, B extends Keyed, R extends org.bukkit.Registry
return new DelayedRegistryEntry<>(this);
}
- static <M, B extends Keyed> RegistryEntry<M, B, CraftRegistry<B, M>> entry(final ResourceKey<? extends Registry<M>> minecraftRegistryKey, final RegistryKey<B> apiRegistryKey, final Class<?> classToPreload, final BiFunction<NamespacedKey, M, B> minecraftToBukkit) {
- return new CraftRegistryEntry<>(minecraftRegistryKey, apiRegistryKey, classToPreload, minecraftToBukkit);
+ interface Modifiable<M, T, B extends PaperRegistryBuilder<M, T>> extends RegistryEntryInfo<M, T> {
+
+ RegistryAdditionEventImpl<T, B> createAdditionEvent(TypedKey<T> key, B initialBuilder, RegistryView<T> view);
+
+ B fillBuilder(TypedKey<T> key, M nms);
+ }
+
+ interface Writable<M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> extends Modifiable<M, T, B> { // TODO remove Keyed
+
+ RegistryPreFreezeEventImpl<T, B> createPreFreezeEvent(WritableCraftRegistry<M, T, B> writableRegistry);
+ }
+
+ static <M, B extends Keyed> RegistryEntry<M, B, ?> entry(final ResourceKey<? extends Registry<M>> mcKey,
+ final RegistryKey<B> apiKey,
+ final Class<?> toPreload,
+ final BiFunction<NamespacedKey, M, B> minecraftToBukkit) {
+ return new CraftRegistryEntry<>(mcKey, apiKey, toPreload, minecraftToBukkit);
+ }
+
+ static <M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> RegistryEntry<M, T, ?> modifiable(final ResourceKey<? extends Registry<M>> mcKey,
+ final RegistryKey<T> apiKey,
+ final Class<?> toPreload,
+ final BiFunction<NamespacedKey, M, T> minecraftToBukkit,
+ final PaperRegistryBuilder.Filler<M, T, B> filler) {
+ return new ModifiableRegistryEntry<>(mcKey, apiKey, toPreload, minecraftToBukkit, filler);
+ }
+
+ static <M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> RegistryEntry<M, T, ?> writable(final ResourceKey<? extends Registry<M>> mcKey,
+ final RegistryKey<T> apiKey,
+ final Class<?> toPreload,
+ final BiFunction<NamespacedKey, M, T> minecraftToBukkit,
+ final PaperRegistryBuilder.Filler<M, T, B> filler) {
+ return new WritableRegistryEntry<>(mcKey, apiKey, toPreload, minecraftToBukkit, filler);
}
}
diff --git a/src/main/java/io/papermc/paper/registry/entry/WritableRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/WritableRegistryEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..57bae24373f3af6a37decf8a656317d68daaa21a
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/entry/WritableRegistryEntry.java
@@ -0,0 +1,56 @@
+package io.papermc.paper.registry.entry;
+
+import io.papermc.paper.registry.PaperRegistryBuilder;
+import io.papermc.paper.registry.RegistryHolder;
+import io.papermc.paper.registry.RegistryKey;
+import io.papermc.paper.registry.RegistryView;
+import io.papermc.paper.registry.SimpleWritableCraftRegistry;
+import io.papermc.paper.registry.TypedKey;
+import io.papermc.paper.registry.WritableCraftRegistry;
+import io.papermc.paper.registry.event.RegistryAdditionEventImpl;
+import io.papermc.paper.registry.event.RegistryPreFreezeEventImpl;
+import java.util.function.BiFunction;
+import net.minecraft.core.Registry;
+import net.minecraft.resources.ResourceKey;
+import org.bukkit.Keyed;
+import org.bukkit.NamespacedKey;
+
+public class WritableRegistryEntry<M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> extends BaseRegistryEntry<M, T, WritableCraftRegistry<M, T, B>> implements RegistryEntry.Writable<M, T, B> {
+
+ private final PaperRegistryBuilder.Filler<M, T, B> builderFiller;
+
+ protected WritableRegistryEntry(
+ final ResourceKey<? extends Registry<M>> mcKey,
+ final RegistryKey<T> apiKey,
+ final Class<?> toPreload,
+ final BiFunction<NamespacedKey, M, T> minecraftToBukkit,
+ final PaperRegistryBuilder.Filler<M, T, B> builderFiller
+ ) {
+ super(mcKey, apiKey, toPreload, minecraftToBukkit);
+ this.builderFiller = builderFiller;
+ }
+
+ private WritableCraftRegistry<M, T, B> createRegistry(final Registry<M> registry) {
+ return new SimpleWritableCraftRegistry<>(this, registry, this.builderFiller.asFactory(), this.minecraftToBukkit);
+ }
+
+ @Override
+ public RegistryHolder<T, WritableCraftRegistry<M, T, B>> createRegistryHolder(final Registry<M> nmsRegistry) {
+ return new RegistryHolder<>(() -> this.createRegistry(nmsRegistry));
+ }
+
+ @Override
+ public RegistryAdditionEventImpl<T, B> createAdditionEvent(final TypedKey<T> key, final B initialBuilder, final RegistryView<T> view) {
+ return new RegistryAdditionEventImpl<>(key, initialBuilder, this.apiKey(), view);
+ }
+
+ @Override
+ public B fillBuilder(final TypedKey<T> key, final M nms) {
+ return this.builderFiller.fill(key, nms);
+ }
+
+ @Override
+ public RegistryPreFreezeEventImpl<T, B> createPreFreezeEvent(final WritableCraftRegistry<M, T, B> registry) {
+ return new RegistryPreFreezeEventImpl<>(this.apiKey(), registry.modifiableView);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/PaperRegistryView.java b/src/main/java/io/papermc/paper/registry/event/PaperRegistryView.java
new file mode 100644
index 0000000000000000000000000000000000000000..468115c3695bb3bc1529560c624b93462fd02491
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/PaperRegistryView.java
@@ -0,0 +1,53 @@
+package io.papermc.paper.registry.event;
+
+import com.google.common.collect.Iterators;
+import io.papermc.paper.registry.RegistryView;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.function.BiFunction;
+import net.kyori.adventure.key.Key;
+import net.minecraft.core.MappedRegistry;
+import net.minecraft.core.Registry;
+import net.minecraft.resources.ResourceLocation;
+import org.bukkit.NamespacedKey;
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public class PaperRegistryView<M, T> implements RegistryView<T> {
+
+ protected final MappedRegistry<M> registry;
+ private final BiFunction<? super Key, M, T> minecraftToBukkit;
+
+ public PaperRegistryView(final Registry<M> registry, final BiFunction<? super NamespacedKey, M, T> minecraftToBukkit) {
+ this.registry = (MappedRegistry<M>) registry;
+ this.minecraftToBukkit = convert(minecraftToBukkit);
+ }
+
+ @Override
+ public T get(final Key key) {
+ final @Nullable M value = this.registry.beforeFrozenView().get(new ResourceLocation(key.namespace(), key.value()));
+ if (value == null) {
+ return null;
+ }
+
+ return this.minecraftToBukkit.apply(key, value);
+ }
+
+ @Override
+ public T getOrThrow(final Key key) {
+ final @Nullable T value = this.get(key);
+ if (value == null) {
+ throw new NoSuchElementException("No value found for key " + key);
+ }
+ return value;
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return Iterators.transform(this.registry.beforeFrozenView().entrySet().iterator(), input -> this.minecraftToBukkit.apply(CraftNamespacedKey.fromMinecraft(input.getKey()), input.getValue()));
+ }
+
+ private static <M, T> BiFunction<? super Key, M, T> convert(final BiFunction<? super NamespacedKey, M, T> original) {
+ return (key, m) -> original.apply(key instanceof final NamespacedKey ns ? ns : new NamespacedKey(key.namespace(), key.value()), m);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/PaperWritableRegistry.java b/src/main/java/io/papermc/paper/registry/event/PaperWritableRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..85296647e9a1bfcbaa9c94f1e7a47722727cd7c8
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/PaperWritableRegistry.java
@@ -0,0 +1,24 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.registry.PaperRegistryBuilder;
+import io.papermc.paper.registry.TypedKey;
+import io.papermc.paper.registry.WritableCraftRegistry;
+import java.util.function.Consumer;
+import net.minecraft.core.Registry;
+import org.bukkit.Keyed;
+import org.jetbrains.annotations.NotNull;
+
+public class PaperWritableRegistry<M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> extends PaperRegistryView<M, T> implements WritableRegistry<T, B> {
+
+ private final WritableCraftRegistry<M, T, B> writableRegistry;
+
+ public PaperWritableRegistry(final Registry<M> registry, final WritableCraftRegistry<M, T, B> writableRegistry) {
+ super(registry, writableRegistry::minecraftToBukkit);
+ this.writableRegistry = writableRegistry;
+ }
+
+ @Override
+ public void register(final @NotNull TypedKey<T> key, final Consumer<? super B> value) {
+ this.writableRegistry.register(key, value);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryAdditionEventImpl.java b/src/main/java/io/papermc/paper/registry/event/RegistryAdditionEventImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe2619b2e590cbd048a0bb9f06f82a3025d9dfaf
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryAdditionEventImpl.java
@@ -0,0 +1,15 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEvent;
+import io.papermc.paper.registry.RegistryBuilder;
+import io.papermc.paper.registry.RegistryKey;
+import io.papermc.paper.registry.RegistryView;
+import io.papermc.paper.registry.TypedKey;
+
+public record RegistryAdditionEventImpl<T, B extends RegistryBuilder<T>>(
+ TypedKey<T> key,
+ B builder,
+ RegistryKey<T> registryKey,
+ RegistryView<T> registry
+) implements RegistryAdditionEvent<T, B>, PaperLifecycleEvent {
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEventMap.java b/src/main/java/io/papermc/paper/registry/event/RegistryEventMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..d68698725f6e90fa05db3668ea559c25a559cd25
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryEventMap.java
@@ -0,0 +1,43 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner;
+import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
+import io.papermc.paper.registry.RegistryBuilder;
+import io.papermc.paper.registry.RegistryKey;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+public final class RegistryEventMap {
+
+ private final Map<RegistryKey<?>, LifecycleEventType.Prioritizable<BootstrapContext, ? extends RegistryEvent<?>>> hooks = new HashMap<>();
+ private final String name;
+
+ public RegistryEventMap(final String name) {
+ this.name = name;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T, B extends RegistryBuilder<T>, E extends RegistryEvent<T>> LifecycleEventType.Prioritizable<BootstrapContext, E> getOrCreate(final RegistryEvents.Provider<T, B> type) {
+ final RegistryLifecycleEventType<T, B, E> registerHook;
+ if (this.hooks.containsKey(type.registryKey())) {
+ registerHook = (RegistryLifecycleEventType<T, B, E>) this.hooks.get(type.registryKey());
+ } else {
+ registerHook = new RegistryLifecycleEventType<>(type, this.name);
+ LifecycleEventRunner.INSTANCE.addEventType(registerHook);
+ this.hooks.put(type.registryKey(), registerHook);
+ }
+ return registerHook;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T, B extends RegistryBuilder<T>, E extends RegistryEvent<T>> LifecycleEventType.Prioritizable<BootstrapContext, E> getHook(final RegistryKey<T> registryKey) {
+ return (RegistryLifecycleEventType<T, B, E>) this.hooks.get(registryKey);
+ }
+
+ public boolean hasHooks(final RegistryKey<?> registryKey) {
+ return this.hooks.containsKey(registryKey);
+ }
+
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProviderImpl.java b/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProviderImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf04f6426d56ee6ae4d23c47f458d1ecece6e834
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryEventTypeProviderImpl.java
@@ -0,0 +1,23 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
+import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
+import io.papermc.paper.registry.PaperRegistryListenerManager;
+import io.papermc.paper.registry.RegistryBuilder;
+
+public class RegistryEventTypeProviderImpl implements RegistryEventTypeProvider {
+
+ public static RegistryEventTypeProviderImpl instance() {
+ return (RegistryEventTypeProviderImpl) RegistryEventTypeProvider.PROVIDER;
+ }
+
+ @Override
+ public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryAdditionEvent<T, B>> registryAddition(final RegistryEvents.Provider<T, B> type) {
+ return PaperRegistryListenerManager.INSTANCE.getRegistryAdditionEventType(type);
+ }
+
+ @Override
+ public <T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryPreFreezeEvent<T, B>> registryPreFreeze(final RegistryEvents.Provider<T, B> type) {
+ return PaperRegistryListenerManager.INSTANCE.getRegistryPreFreezeEventType(type);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryLifecycleEventType.java b/src/main/java/io/papermc/paper/registry/event/RegistryLifecycleEventType.java
new file mode 100644
index 0000000000000000000000000000000000000000..a318fa8cd83d44546412462e80df38624ea04954
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryLifecycleEventType.java
@@ -0,0 +1,12 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
+import io.papermc.paper.plugin.lifecycle.event.types.PrioritizableLifecycleEventType;
+import io.papermc.paper.registry.RegistryBuilder;
+
+public final class RegistryLifecycleEventType<T, B extends RegistryBuilder<T>, E extends RegistryEvent<T>> extends PrioritizableLifecycleEventType<BootstrapContext, E> {
+
+ RegistryLifecycleEventType(final RegistryEvents.Provider<T, B> type, final String eventName) {
+ super(type.registryKey() + " / " + eventName, BootstrapContext.class);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryPreFreezeEventImpl.java b/src/main/java/io/papermc/paper/registry/event/RegistryPreFreezeEventImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ffb90d495dbe45e2fa6df9e61f13eee7c77f5a8
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryPreFreezeEventImpl.java
@@ -0,0 +1,12 @@
+package io.papermc.paper.registry.event;
+
+import io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEvent;
+import io.papermc.paper.registry.RegistryBuilder;
+import io.papermc.paper.registry.RegistryKey;
+import net.kyori.adventure.key.Keyed;
+
+public record RegistryPreFreezeEventImpl<T, B extends RegistryBuilder<T>>(
+ RegistryKey<T> registryKey,
+ WritableRegistry<T, B> registry
+) implements RegistryPreFreezeEvent<T, B>, PaperLifecycleEvent {
+}
diff --git a/src/main/java/io/papermc/paper/registry/event/package-info.java b/src/main/java/io/papermc/paper/registry/event/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..14d2d9766b8dee763f220c397aba3ad432d02aaa
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/event/package-info.java
@@ -0,0 +1,5 @@
+@DefaultQualifier(NonNull.class)
+package io.papermc.paper.registry.event;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
diff --git a/src/main/java/io/papermc/paper/registry/package-info.java b/src/main/java/io/papermc/paper/registry/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b80179ff90e085568d7ceafd9b17511789dc99b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/package-info.java
@@ -0,0 +1,5 @@
+@DefaultQualifier(NonNull.class)
+package io.papermc.paper.registry;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java
index 72c0c4a12aea39fa1c1967fa0277ed117471107e..7af48c1cb6985769cea840a01f8290b73380be29 100644
--- a/src/main/java/net/minecraft/core/MappedRegistry.java
+++ b/src/main/java/net/minecraft/core/MappedRegistry.java
@@ -77,6 +77,14 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
}
};
private final Object tagAdditionLock = new Object();
+ // Paper start
+ @Nullable
+ private Map<ResourceLocation, T> beforeFrozen = new HashMap<>(2048);
+ public Map<ResourceLocation, T> beforeFrozenView() {
+ com.google.common.base.Preconditions.checkState(this.beforeFrozen != null, "Cannot get this after the registry is frozen");
+ return Collections.unmodifiableMap(this.beforeFrozen);
+ }
+ // Paper end
public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle) {
this(key, lifecycle, false);
@@ -144,6 +152,7 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
this.byId.add(reference);
this.toId.put(value, i);
this.registrationInfos.put(key, info);
+ Objects.requireNonNull(this.beforeFrozen).put(key.location(), value); // Paper
this.registryLifecycle = this.registryLifecycle.add(info.lifecycle());
return reference;
}
@@ -323,6 +332,7 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
} else {
this.frozen = true;
this.byValue.forEach((value, entry) -> entry.bindValue((T)value));
+ this.beforeFrozen = null; // Paper
List<ResourceLocation> list = this.byKey
.entrySet()
.stream()
@@ -436,4 +446,12 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
public HolderLookup.RegistryLookup<T> asLookup() {
return this.lookup;
}
+ // Paper start
+ // used to clear intrusive holders from GameEvent, Item, Block, EntityType, and Fluid from unused instances of those types
+ public void clearIntrusiveHolder(final T instance) {
+ if (this.unregisteredIntrusiveHolders != null) {
+ this.unregisteredIntrusiveHolders.remove(instance);
+ }
+ }
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
index 8daee5a7935e3253834c4cbe81d5e8886f776dad..d7da62360d48d8c12c489296b4ee2ee44c0c2d93 100644
--- a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
+++ b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
@@ -310,6 +310,7 @@ public class BuiltInRegistries {
}
public static void bootStrap(Runnable runnable) {
// Paper end
+ REGISTRY.freeze(); // Paper - freeze main registry early
createContents();
runnable.run(); // Paper
freeze();
@@ -328,6 +329,7 @@ public class BuiltInRegistries {
REGISTRY.freeze();
for (Registry<?> registry : REGISTRY) {
+ io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.runFreezeListeners(registry.key()); // Paper
registry.freeze();
}
}
diff --git a/src/main/java/net/minecraft/resources/RegistryDataLoader.java b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
index d59356df2d98de873fc5accc749f87fa3d685267..cf3f3a737c4efe832bea8797d0c9af18f87d932f 100644
--- a/src/main/java/net/minecraft/resources/RegistryDataLoader.java
+++ b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
@@ -188,7 +188,7 @@ public class RegistryDataLoader {
JsonElement jsonElement = JsonParser.parseReader(reader);
DataResult<E> dataResult = decoder.parse(ops, jsonElement);
E object = dataResult.getOrThrow();
- registry.register(key, object, entryInfo);
+ io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.registerWithListeners(registry, key, object, entryInfo); // Paper
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
index a3a00778a8fdbc13f8adbf4e4fbc4f1303d22789..0ec0b8f1d2a9b601194fe07c511dc7ce1abdaea1 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
@@ -106,13 +106,15 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
private final Map<NamespacedKey, B> cache = new HashMap<>();
private final Map<B, NamespacedKey> byValue = new java.util.IdentityHashMap<>(); // Paper - improve Registry
private final net.minecraft.core.Registry<M> minecraftRegistry;
- private final BiFunction<NamespacedKey, M, B> minecraftToBukkit;
+ private final BiFunction<? super NamespacedKey, M, B> minecraftToBukkit; // Paper
+ public final io.papermc.paper.registry.RegistryView<B> view; // Paper
private boolean init;
- public CraftRegistry(Class<?> bukkitClass, net.minecraft.core.Registry<M> minecraftRegistry, BiFunction<NamespacedKey, M, B> minecraftToBukkit) { // Paper - relax preload class
+ public CraftRegistry(Class<?> bukkitClass, net.minecraft.core.Registry<M> minecraftRegistry, BiFunction<? super NamespacedKey, M, B> minecraftToBukkit) { // Paper - relax preload class
this.bukkitClass = bukkitClass;
this.minecraftRegistry = minecraftRegistry;
this.minecraftToBukkit = minecraftToBukkit;
+ this.view = new io.papermc.paper.registry.event.PaperRegistryView<>(this.minecraftRegistry, this.minecraftToBukkit); // Paper
}
@Override
diff --git a/src/main/resources/META-INF/services/io.papermc.paper.registry.event.RegistryEventTypeProvider b/src/main/resources/META-INF/services/io.papermc.paper.registry.event.RegistryEventTypeProvider
new file mode 100644
index 0000000000000000000000000000000000000000..8bee1a5ed877a04e4d027593df1f42cefdd824e7
--- /dev/null
+++ b/src/main/resources/META-INF/services/io.papermc.paper.registry.event.RegistryEventTypeProvider
@@ -0,0 +1 @@
+io.papermc.paper.registry.event.RegistryEventTypeProviderImpl
diff --git a/src/test/java/io/papermc/paper/registry/DummyRegistryAccess.java b/src/test/java/io/papermc/paper/registry/DummyRegistryAccess.java
new file mode 100644
index 0000000000000000000000000000000000000000..64fec4a1b81e51c790734c525fed886e31c30e67
--- /dev/null
+++ b/src/test/java/io/papermc/paper/registry/DummyRegistryAccess.java
@@ -0,0 +1,22 @@
+package io.papermc.paper.registry;
+
+import java.util.function.BooleanSupplier;
+import net.minecraft.core.RegistryAccess;
+import org.bukkit.support.AbstractTestingBase;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+@DefaultQualifier(NonNull.class)
+public class DummyRegistryAccess extends PaperRegistryAccess {
+
+ @Override
+ public RegistryAccess getDelayedRegistryAccess() {
+ return AbstractTestingBase.REGISTRY_CUSTOM;
+ }
+
+ @Override
+ public BooleanSupplier delayedValidCheck() {
+ //noinspection ConstantValue
+ return () -> AbstractTestingBase.REGISTRY_CUSTOM != null;
+ }
+}
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..6c7526bbc7318f510f81f4073a158f7136017a56
--- /dev/null
+++ b/src/test/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess
@@ -0,0 +1 @@
+io.papermc.paper.registry.DummyRegistryAccess

View File

@ -0,0 +1,80 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 25 Feb 2023 21:25:08 -0800
Subject: [PATCH] Support registry mod API with GameEvent
diff --git a/src/main/java/net/minecraft/world/level/gameevent/GameEvent.java b/src/main/java/net/minecraft/world/level/gameevent/GameEvent.java
index ef0eecd4404fcce4046b53ff9e176ea59978d1ac..c4f8a03aac42507df2d9a84b3acf53887d2eed86 100644
--- a/src/main/java/net/minecraft/world/level/gameevent/GameEvent.java
+++ b/src/main/java/net/minecraft/world/level/gameevent/GameEvent.java
@@ -81,7 +81,7 @@ public record GameEvent(int notificationRadius) {
}
private static Holder.Reference<GameEvent> register(String id, int range) {
- return Registry.registerForHolder(BuiltInRegistries.GAME_EVENT, new ResourceLocation(id), new GameEvent(range));
+ return io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.registerForHolderWithListeners(BuiltInRegistries.GAME_EVENT, new ResourceLocation(id), new GameEvent(range)); // Paper
}
public static record Context(@Nullable Entity sourceEntity, @Nullable BlockState affectedState) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftGameEvent.java b/src/main/java/org/bukkit/craftbukkit/CraftGameEvent.java
index ac9b4328cd55a68664a3f71186bc9a7be7cd9658..34c63a685606a55936f27dfe4393d23e46d8d20d 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftGameEvent.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftGameEvent.java
@@ -19,10 +19,12 @@ public class CraftGameEvent extends GameEvent implements Handleable<net.minecraf
private final NamespacedKey key;
private final net.minecraft.world.level.gameevent.GameEvent handle;
+ private final net.minecraft.resources.ResourceKey<net.minecraft.world.level.gameevent.GameEvent> handleKey; // Paper
public CraftGameEvent(NamespacedKey key, net.minecraft.world.level.gameevent.GameEvent handle) {
this.key = key;
this.handle = handle;
+ this.handleKey = net.minecraft.resources.ResourceKey.create(net.minecraft.core.registries.Registries.GAME_EVENT, org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(this.key)); // Paper
}
@Override
@@ -58,4 +60,43 @@ public class CraftGameEvent extends GameEvent implements Handleable<net.minecraf
public String toString() {
return "CraftGameEvent{key=" + this.key + "}";
}
+
+ // Paper start
+ @Override
+ public int getRange() {
+ return this.handle.notificationRadius();
+ }
+
+ @Override
+ public int getVibrationLevel() {
+ return net.minecraft.world.level.gameevent.vibrations.VibrationSystem.getGameEventFrequency(this.handleKey);
+ }
+
+ public static final class Builder implements GameEvent.Builder, io.papermc.paper.registry.PaperRegistryBuilder<net.minecraft.world.level.gameevent.GameEvent, org.bukkit.GameEvent> {
+
+ private int range = 16;
+
+ public Builder(final io.papermc.paper.registry.TypedKey<GameEvent> $, final net.minecraft.world.level.gameevent.@org.checkerframework.checker.nullness.qual.Nullable GameEvent nms) {
+ if (nms != null) {
+ this.range = nms.notificationRadius();
+ }
+ }
+
+ @Override
+ public int range() {
+ return this.range;
+ }
+
+ @Override
+ public Builder range(final int range) {
+ this.range = range;
+ return this;
+ }
+
+ @Override
+ public net.minecraft.world.level.gameevent.GameEvent build() {
+ return new net.minecraft.world.level.gameevent.GameEvent(this.range);
+ }
+ }
+ // Paper end
}

View File

@ -1,5 +1,7 @@
package io.papermc.testplugin;
import org.bukkit.GameEvent;
import org.bukkit.Registry;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
@ -8,5 +10,13 @@ public final class TestPlugin extends JavaPlugin implements Listener {
@Override
public void onEnable() {
this.getServer().getPluginManager().registerEvents(this, this);
final GameEvent newEvent = Registry.GAME_EVENT.get(TestPluginBootstrap.NEW_EVENT);
if (newEvent == null) {
throw new RuntimeException("could not find new event");
} else {
System.out.println("New event: " + newEvent.getKey() + " " + newEvent.getRange());
}
}
}

View File

@ -2,12 +2,34 @@ package io.papermc.testplugin;
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
import io.papermc.paper.plugin.bootstrap.PluginBootstrap;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import io.papermc.paper.registry.event.RegistryEvents;
import io.papermc.paper.registry.keys.GameEventKeys;
import net.kyori.adventure.key.Key;
import org.bukkit.GameEvent;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.jetbrains.annotations.NotNull;
@DefaultQualifier(NonNull.class)
public class TestPluginBootstrap implements PluginBootstrap {
static final TypedKey<GameEvent> NEW_EVENT = TypedKey.create(RegistryKey.GAME_EVENT, Key.key("machine_maker", "best_event"));
@Override
public void bootstrap(@NotNull BootstrapContext context) {
final LifecycleEventManager<BootstrapContext> lifecycleManager = context.getLifecycleManager();
lifecycleManager.registerEventHandler(RegistryEvents.GAME_EVENT.newAdditionHandler(event -> {
if (event.key().equals(GameEventKeys.BLOCK_OPEN)) {
event.builder().range(event.builder().range() * 2);
}
}).priority(10));
lifecycleManager.registerEventHandler(RegistryEvents.GAME_EVENT.preFreeze(), event -> {
event.registry().register(NEW_EVENT, builder -> {
builder.range(2);
});
});
}
}