diff --git a/patches/api/Introduce-registry-entry-and-builders.patch b/patches/api/Introduce-registry-entry-and-builders.patch index 6d708cc46d..ca3fabdd49 100644 --- a/patches/api/Introduce-registry-entry-and-builders.patch +++ b/patches/api/Introduce-registry-entry-and-builders.patch @@ -45,14 +45,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Range; +import org.jetbrains.annotations.Unmodifiable; -+import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +/** + * A data-centric version-specific registry entry for the {@link Enchantment} type. + */ +@ApiStatus.Experimental -+@NullMarked +@ApiStatus.NonExtendable +public interface EnchantmentRegistryEntry { + @@ -372,13 +370,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Range; -+import org.jspecify.annotations.NullMarked; + +/** + * A data-centric version-specific registry entry for the {@link GameEvent} type. + */ +@ApiStatus.Experimental -+@NullMarked +@ApiStatus.NonExtendable +public interface GameEventRegistryEntry { + @@ -423,21 +419,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.RegistryBuilder; -+import java.util.Optional; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import org.bukkit.Art; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Range; -+import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +/** + * A data-centric version-specific registry entry for the {@link Art} type. + */ +@ApiStatus.Experimental -+@NullMarked +@ApiStatus.NonExtendable +public interface PaintingVariantRegistryEntry { + @@ -565,7 +558,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * Registry entries are not expected to be used during plugin runtime interactions with the API but are mostly + * exposed during registry creation/modification. + */ ++@NullMarked +package io.papermc.paper.registry.data; ++ ++import org.jspecify.annotations.NullMarked; 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java diff --git a/patches/api/Test-changes.patch b/patches/api/Test-changes.patch index bad3327e65..a915fa09bc 100644 --- a/patches/api/Test-changes.patch +++ b/patches/api/Test-changes.patch @@ -223,6 +223,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } private static void collectClasses(@NotNull File from, @NotNull Map to) throws IOException { + if (from.isDirectory()) { ++ // Paper start - skip packages with @NullMarked ++ final File packageInfo = new File(from, "package-info.class"); ++ if (packageInfo.exists()) { ++ try (final FileInputStream in = new FileInputStream(packageInfo)) { ++ final ClassReader cr = new ClassReader(in); ++ ++ final ClassNode node = new ClassNode(); ++ cr.accept(node, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); ++ ++ if (isClassNullMarked0(node)) { ++ return; // skip packages with @NullMarked ++ } ++ } ++ } ++ // Paper end - skip packages with @NullMarked + final File[] files = from.listFiles(); + assert files != null; + @@ -0,0 +0,0 @@ public class AnnotationTest { } } diff --git a/patches/server/Add-RegistryAccess-for-managing-Registries.patch b/patches/server/Add-RegistryAccess-for-managing-Registries.patch index ef56defe13..204e46023c 100644 --- a/patches/server/Add-RegistryAccess-for-managing-Registries.patch +++ b/patches/server/Add-RegistryAccess-for-managing-Registries.patch @@ -83,8 +83,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import org.bukkit.potion.PotionEffectType; +import org.jspecify.annotations.Nullable; + -+import static io.papermc.paper.registry.entry.RegistryEntry.apiOnly; -+import static io.papermc.paper.registry.entry.RegistryEntry.entry; ++import static io.papermc.paper.registry.entry.RegistryEntryBuilder.start; + +public final class PaperRegistries { + @@ -94,39 +93,39 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + static { + REGISTRY_ENTRIES = List.of( + // built-ins -+ entry(Registries.GAME_EVENT, RegistryKey.GAME_EVENT, GameEvent.class, CraftGameEvent::new), -+ entry(Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE, StructureType.class, CraftStructureType::new), -+ entry(Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT, PotionEffectType.class, CraftPotionEffectType::new), -+ entry(Registries.BLOCK, RegistryKey.BLOCK, BlockType.class, CraftBlockType::new), -+ entry(Registries.ITEM, RegistryKey.ITEM, ItemType.class, CraftItemType::new), -+ entry(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT, Cat.Type.class, CraftCat.CraftType::new), -+ entry(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT, Frog.Variant.class, CraftFrog.CraftVariant::new), -+ entry(Registries.VILLAGER_PROFESSION, RegistryKey.VILLAGER_PROFESSION, Villager.Profession.class, CraftVillager.CraftProfession::new), -+ entry(Registries.VILLAGER_TYPE, RegistryKey.VILLAGER_TYPE, Villager.Type.class, CraftVillager.CraftType::new), -+ entry(Registries.MAP_DECORATION_TYPE, RegistryKey.MAP_DECORATION_TYPE, MapCursor.Type.class, CraftMapCursor.CraftType::new), -+ entry(Registries.MENU, RegistryKey.MENU, MenuType.class, CraftMenuType::new), -+ entry(Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE, Attribute.class, CraftAttribute::new), -+ entry(Registries.FLUID, RegistryKey.FLUID, Fluid.class, CraftFluid::new), -+ entry(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT, Sound.class, CraftSound::new), ++ start(Registries.GAME_EVENT, RegistryKey.GAME_EVENT).craft(GameEvent.class, CraftGameEvent::new).build(), ++ start(Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE).craft(StructureType.class, CraftStructureType::new).build(), ++ start(Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT).craft(PotionEffectType.class, CraftPotionEffectType::new).build(), ++ start(Registries.BLOCK, RegistryKey.BLOCK).craft(BlockType.class, CraftBlockType::new).build(), ++ start(Registries.ITEM, RegistryKey.ITEM).craft(ItemType.class, CraftItemType::new).build(), ++ start(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT).craft(Cat.Type.class, CraftCat.CraftType::new).build(), ++ start(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT).craft(Frog.Variant.class, CraftFrog.CraftVariant::new).build(), ++ start(Registries.VILLAGER_PROFESSION, RegistryKey.VILLAGER_PROFESSION).craft(Villager.Profession.class, CraftVillager.CraftProfession::new).build(), ++ start(Registries.VILLAGER_TYPE, RegistryKey.VILLAGER_TYPE).craft(Villager.Type.class, CraftVillager.CraftType::new).build(), ++ start(Registries.MAP_DECORATION_TYPE, RegistryKey.MAP_DECORATION_TYPE).craft(MapCursor.Type.class, CraftMapCursor.CraftType::new).build(), ++ start(Registries.MENU, RegistryKey.MENU).craft(MenuType.class, CraftMenuType::new).build(), ++ start(Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE).craft(Attribute.class, CraftAttribute::new).build(), ++ start(Registries.FLUID, RegistryKey.FLUID).craft(Fluid.class, CraftFluid::new).build(), ++ start(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT).craft(Sound.class, CraftSound::new).build(), + + // data-drivens -+ entry(Registries.BIOME, RegistryKey.BIOME, Biome.class, CraftBiome::new).delayed(), -+ entry(Registries.STRUCTURE, RegistryKey.STRUCTURE, Structure.class, CraftStructure::new).delayed(), -+ entry(Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL, TrimMaterial.class, CraftTrimMaterial::new).delayed(), -+ entry(Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN, TrimPattern.class, CraftTrimPattern::new).delayed(), -+ entry(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE, DamageType.class, CraftDamageType::new).delayed(), -+ entry(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT, Wolf.Variant.class, CraftWolf.CraftVariant::new).delayed(), -+ entry(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, Enchantment.class, CraftEnchantment::new).withSerializationUpdater(FieldRename.ENCHANTMENT_RENAME).delayed(), -+ entry(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG, JukeboxSong.class, CraftJukeboxSong::new).delayed(), -+ entry(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN, PatternType.class, CraftPatternType::new).delayed(), -+ entry(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT, Art.class, CraftArt::new).delayed(), -+ entry(Registries.INSTRUMENT, RegistryKey.INSTRUMENT, MusicInstrument.class, CraftMusicInstrument::new).delayed(), ++ start(Registries.BIOME, RegistryKey.BIOME).craft(Biome.class, CraftBiome::new).build().delayed(), ++ start(Registries.STRUCTURE, RegistryKey.STRUCTURE).craft(Structure.class, CraftStructure::new).build().delayed(), ++ start(Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL).craft(TrimMaterial.class, CraftTrimMaterial::new).build().delayed(), ++ start(Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN).craft(TrimPattern.class, CraftTrimPattern::new).build().delayed(), ++ start(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE).craft(DamageType.class, CraftDamageType::new).build().delayed(), ++ start(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT).craft(Wolf.Variant.class, CraftWolf.CraftVariant::new).build().delayed(), ++ start(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT).craft(Enchantment.class, CraftEnchantment::new).build().withSerializationUpdater(FieldRename.ENCHANTMENT_RENAME).delayed(), ++ start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).build().delayed(), ++ start(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN).craft(PatternType.class, CraftPatternType::new).build().delayed(), ++ start(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT).craft(Art.class, CraftArt::new).build().delayed(), ++ start(Registries.INSTRUMENT, RegistryKey.INSTRUMENT).craft(MusicInstrument.class, CraftMusicInstrument::new).build().delayed(), + + // api-only -+ apiOnly(Registries.ENTITY_TYPE, RegistryKey.ENTITY_TYPE, PaperSimpleRegistry::entityType), -+ apiOnly(Registries.PARTICLE_TYPE, RegistryKey.PARTICLE_TYPE, PaperSimpleRegistry::particleType), -+ apiOnly(Registries.POTION, RegistryKey.POTION, PaperSimpleRegistry::potion), -+ apiOnly(Registries.MEMORY_MODULE_TYPE, RegistryKey.MEMORY_MODULE_TYPE, () -> (org.bukkit.Registry>) (org.bukkit.Registry) org.bukkit.Registry.MEMORY_MODULE_TYPE) ++ start(Registries.ENTITY_TYPE, RegistryKey.ENTITY_TYPE).apiOnly(PaperSimpleRegistry::entityType), ++ start(Registries.PARTICLE_TYPE, RegistryKey.PARTICLE_TYPE).apiOnly(PaperSimpleRegistry::particleType), ++ start(Registries.POTION, RegistryKey.POTION).apiOnly(PaperSimpleRegistry::potion), ++ start(Registries.MEMORY_MODULE_TYPE, RegistryKey.MEMORY_MODULE_TYPE).apiOnly(() -> (org.bukkit.Registry>) (org.bukkit.Registry) org.bukkit.Registry.MEMORY_MODULE_TYPE) + ); + final Map, RegistryEntry> byRegistryKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size()); + final Map, RegistryEntry> byResourceKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size()); @@ -467,9 +466,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package io.papermc.paper.registry.entry; + +import com.google.common.base.Preconditions; ++import com.mojang.datafixers.util.Either; +import io.papermc.paper.registry.RegistryHolder; +import io.papermc.paper.registry.RegistryKey; +import java.util.function.BiFunction; ++import java.util.function.Function; ++import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import org.bukkit.Keyed; @@ -482,14 +484,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private static final BiFunction EMPTY = (namespacedKey, apiVersion) -> namespacedKey; + + protected final Class classToPreload; -+ protected final BiFunction minecraftToBukkit; ++ protected final RegistryTypeMapper minecraftToBukkit; + protected BiFunction updater = EMPTY; + + protected CraftRegistryEntry( + final ResourceKey> mcKey, + final RegistryKey apiKey, + final Class classToPreload, -+ final BiFunction minecraftToBukkit ++ final RegistryTypeMapper minecraftToBukkit + ) { + super(mcKey, apiKey); + Preconditions.checkArgument(!classToPreload.getPackageName().startsWith("net.minecraft"), classToPreload + " should not be in the net.minecraft package as the class-to-preload"); @@ -524,9 +526,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.legacy.DelayedRegistryEntry; +import java.util.function.BiFunction; -+import java.util.function.Supplier; +import net.minecraft.core.Registry; -+import net.minecraft.resources.ResourceKey; +import org.bukkit.Keyed; +import org.bukkit.NamespacedKey; +import org.bukkit.craftbukkit.util.ApiVersion; @@ -548,22 +548,74 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + default RegistryEntry delayed() { + return new DelayedRegistryEntry<>(this); + } ++} +diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryEntryBuilder.java b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryBuilder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryBuilder.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry.entry; + -+ static RegistryEntry entry( ++import com.mojang.datafixers.util.Either; ++import io.papermc.paper.registry.RegistryKey; ++import java.util.function.BiFunction; ++import java.util.function.Function; ++import java.util.function.Supplier; ++import net.minecraft.core.Holder; ++import net.minecraft.core.Registry; ++import net.minecraft.resources.ResourceKey; ++import org.bukkit.Keyed; ++import org.bukkit.NamespacedKey; ++ ++public class RegistryEntryBuilder { // TODO remove Keyed ++ ++ public static RegistryEntryBuilder start( // TODO remove Keyed + final ResourceKey> mcKey, -+ final RegistryKey apiKey, -+ final Class classToPreload, -+ final BiFunction minecraftToBukkit ++ final RegistryKey apiKey + ) { -+ return new CraftRegistryEntry<>(mcKey, apiKey, classToPreload, minecraftToBukkit); ++ return new RegistryEntryBuilder<>(mcKey, apiKey); + } + -+ static RegistryEntry apiOnly( -+ final ResourceKey> mcKey, -+ final RegistryKey apiKey, -+ final Supplier> apiRegistrySupplier -+ ) { -+ return new ApiRegistryEntry<>(mcKey, apiKey, apiRegistrySupplier); ++ protected final ResourceKey> mcKey; ++ protected final RegistryKey apiKey; ++ ++ private RegistryEntryBuilder(final ResourceKey> mcKey, RegistryKey apiKey) { ++ this.mcKey = mcKey; ++ this.apiKey = apiKey; ++ } ++ ++ public RegistryEntry apiOnly(final Supplier> apiRegistrySupplier) { ++ return new ApiRegistryEntry<>(this.mcKey, this.apiKey, apiRegistrySupplier); ++ } ++ ++ public CraftStage craft(final Class classToPreload, final BiFunction minecraftToBukkit) { ++ return new CraftStage<>(this.mcKey, this.apiKey, classToPreload, new RegistryTypeMapper<>(minecraftToBukkit)); ++ } ++ ++ public CraftStage craft(final Class classToPreload, final Function, ? extends A> minecraftToBukkit) { ++ return new CraftStage<>(this.mcKey, this.apiKey, classToPreload, new RegistryTypeMapper<>(minecraftToBukkit)); ++ } ++ ++ public static final class CraftStage extends RegistryEntryBuilder { // TODO remove Keyed ++ ++ private final Class classToPreload; ++ private final RegistryTypeMapper minecraftToBukkit; ++ ++ private CraftStage( ++ final ResourceKey> mcKey, ++ final RegistryKey apiKey, ++ final Class classToPreload, ++ final RegistryTypeMapper minecraftToBukkit ++ ) { ++ super(mcKey, apiKey); ++ this.classToPreload = classToPreload; ++ this.minecraftToBukkit = minecraftToBukkit; ++ } ++ ++ public RegistryEntry build() { ++ return new CraftRegistryEntry<>(this.mcKey, this.apiKey, this.classToPreload, this.minecraftToBukkit); ++ } + } +} diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java @@ -584,6 +636,49 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + RegistryKey apiKey(); +} +diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryTypeMapper.java b/src/main/java/io/papermc/paper/registry/entry/RegistryTypeMapper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/entry/RegistryTypeMapper.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.registry.entry; ++ ++import com.google.common.base.Preconditions; ++import com.mojang.datafixers.util.Either; ++import java.util.function.BiFunction; ++import java.util.function.Function; ++import net.minecraft.core.Holder; ++import org.bukkit.NamespacedKey; ++ ++public final class RegistryTypeMapper { ++ ++ final Either, Function, ? extends A>> minecraftToBukkit; ++ ++ public RegistryTypeMapper(final BiFunction byValueCreator) { ++ this.minecraftToBukkit = Either.left(byValueCreator); ++ } ++ ++ public RegistryTypeMapper(final Function, ? extends A> byHolderCreator) { ++ this.minecraftToBukkit = Either.right(byHolderCreator); ++ } ++ ++ public A createBukkit(final NamespacedKey key, final Holder minecraft) { ++ return this.minecraftToBukkit.map( ++ minecraftToBukkit -> minecraftToBukkit.apply(key, minecraft.value()), ++ minecraftToBukkit -> minecraftToBukkit.apply(minecraft) ++ ); ++ } ++ ++ public boolean supportsDirectHolders() { ++ return this.minecraftToBukkit.right().isPresent(); ++ } ++ ++ public A convertDirectHolder(final Holder directHolder) { ++ Preconditions.checkArgument(this.supportsDirectHolders() && directHolder.kind() == Holder.Kind.DIRECT); ++ return this.minecraftToBukkit.right().orElseThrow().apply(directHolder); ++ } ++} diff --git a/src/main/java/io/papermc/paper/registry/entry/package-info.java b/src/main/java/io/papermc/paper/registry/entry/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -748,6 +843,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package io.papermc.paper.registry; + +import org.jspecify.annotations.NullMarked; +diff --git a/src/main/java/io/papermc/paper/util/Holderable.java b/src/main/java/io/papermc/paper/util/Holderable.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/Holderable.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.util; ++ ++import net.minecraft.core.Holder; ++import org.bukkit.craftbukkit.util.Handleable; ++ ++public interface Holderable extends Handleable { ++ ++ Holder getHolder(); ++ ++ @Override ++ default M getHandle() { ++ return this.getHolder().value(); ++ } ++} diff --git a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java @@ -784,10 +899,83 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Map map = new HashMap<>(); SimpleJsonResourceReloadListener.scanDirectory(resourceManager, type.registryKey(), ops, type.codec(), map); map.forEach((id, value) -> writableRegistry.register(ResourceKey.create(type.registryKey(), id), (T)value, DEFAULT_REGISTRATION_INFO)); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftParticle.java b/src/main/java/org/bukkit/craftbukkit/CraftParticle.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftParticle.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftParticle.java +@@ -0,0 +0,0 @@ public abstract class CraftParticle implements Keyed { + } + + public CraftParticleRegistry(net.minecraft.core.Registry> minecraftRegistry) { +- super(CraftParticle.class, minecraftRegistry, null, FieldRename.PARTICLE_TYPE_RENAME); ++ super(CraftParticle.class, minecraftRegistry, CraftParticleRegistry::createBukkit, FieldRename.PARTICLE_TYPE_RENAME); // Paper - switch to Holder + } + +- @Override +- public CraftParticle createBukkit(NamespacedKey namespacedKey, net.minecraft.core.particles.ParticleType particle) { ++ public static CraftParticle createBukkit(NamespacedKey namespacedKey, net.minecraft.core.particles.ParticleType particle) { // Paper - idk why this is a separate implementation, just wrap the function + if (particle == null) { + return null; + } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java +@@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { + Preconditions.checkArgument(minecraft != null); + + net.minecraft.core.Registry registry = CraftRegistry.getMinecraftRegistry(registryKey); +- B bukkit = bukkitRegistry.get(CraftNamespacedKey.fromMinecraft(registry.getResourceKey(minecraft) +- .orElseThrow(() -> new IllegalStateException(String.format("Cannot convert '%s' to bukkit representation, since it is not registered.", minecraft))).location())); ++ // Paper start - support direct Holders ++ final java.util.Optional> resourceKey = registry.getResourceKey(minecraft); ++ if (resourceKey.isEmpty() && bukkitRegistry instanceof final CraftRegistry craftRegistry && craftRegistry.supportsDirectHolders()) { ++ return ((CraftRegistry) registry).convertDirectHolder(Holder.direct(minecraft)); ++ } else if (resourceKey.isEmpty()) { ++ throw new IllegalStateException(String.format("Cannot convert '%s' to bukkit representation, since it is not registered.", minecraft)); ++ } ++ final B bukkit = bukkitRegistry.get(CraftNamespacedKey.fromMinecraft(resourceKey.get().location())); ++ // Paper end - support direct Holders ++ ++ Preconditions.checkArgument(bukkit != null); ++ ++ return bukkit; ++ } + ++ // Paper start - support direct Holders ++ public static B minecraftHolderToBukkit(final Holder minecraft, final Registry bukkitRegistry) { ++ Preconditions.checkArgument(minecraft != null); ++ ++ final B bukkit = switch (minecraft) { ++ case final Holder.Direct direct -> { ++ if (!(bukkitRegistry instanceof final CraftRegistry craftRegistry) || !craftRegistry.supportsDirectHolders()) { ++ throw new IllegalArgumentException("Cannot convert direct holder to bukkit representation"); ++ } ++ yield ((CraftRegistry) bukkitRegistry).convertDirectHolder(direct); ++ } ++ case final Holder.Reference reference -> bukkitRegistry.get(io.papermc.paper.util.MCUtil.fromResourceKey(reference.key())); ++ default -> throw new IllegalArgumentException("Unknown holder: " + minecraft); ++ }; + Preconditions.checkArgument(bukkit != null); + + return bukkit; + } ++ // Paper end - support direct Holders + + /** + * Usage note: Only use this method to delegate the conversion methods from the individual Craft classes to here. +@@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { + + public static Holder bukkitToMinecraftHolder(B bukkit, ResourceKey> registryKey) { + Preconditions.checkArgument(bukkit != null); ++ // Paper start - support direct Holder ++ if (bukkit instanceof io.papermc.paper.util.Holderable) { ++ return ((io.papermc.paper.util.Holderable) bukkit).getHolder(); ++ } ++ // Paper end - support direct Holder + + net.minecraft.core.Registry registry = CraftRegistry.getMinecraftRegistry(registryKey); + @@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { + ", this can happen if a plugin creates its own registry entry with out properly registering it."); } @@ -896,13 +1084,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private final Class bukkitClass; // Paper - relax preload class private final Map cache = new HashMap<>(); private final net.minecraft.core.Registry minecraftRegistry; - private final BiFunction minecraftToBukkit; +- private final BiFunction minecraftToBukkit; - private final BiFunction updater; ++ private final io.papermc.paper.registry.entry.RegistryTypeMapper minecraftToBukkit; // Paper - switch to Holder + private final BiFunction serializationUpdater; // Paper - rename to make it *clear* what it is *only* for private boolean init; - public CraftRegistry(Class bukkitClass, net.minecraft.core.Registry minecraftRegistry, BiFunction minecraftToBukkit, BiFunction updater) { -+ public CraftRegistry(Class bukkitClass, net.minecraft.core.Registry minecraftRegistry, BiFunction minecraftToBukkit, BiFunction serializationUpdater) { // Paper - relax preload class ++ public CraftRegistry(Class bukkitClass, net.minecraft.core.Registry minecraftRegistry, BiFunction minecraftToBukkit, BiFunction serializationUpdater) { // Paper - relax preload class ++ // Paper start - switch to Holder ++ this(bukkitClass, minecraftRegistry, new io.papermc.paper.registry.entry.RegistryTypeMapper<>(minecraftToBukkit), serializationUpdater); ++ } ++ public CraftRegistry(Class bukkitClass, net.minecraft.core.Registry minecraftRegistry, io.papermc.paper.registry.entry.RegistryTypeMapper minecraftToBukkit, BiFunction serializationUpdater) { // Paper - relax preload class ++ // Paper end - support Holders this.bukkitClass = bukkitClass; this.minecraftRegistry = minecraftRegistry; this.minecraftToBukkit = minecraftToBukkit; @@ -917,6 +1111,39 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public B get(NamespacedKey namespacedKey) { +@@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { + return this.get(namespacedKey); + } + +- B bukkit = this.createBukkit(namespacedKey, this.minecraftRegistry.getOptional(CraftNamespacedKey.toMinecraft(namespacedKey)).orElse(null)); ++ B bukkit = this.createBukkit(namespacedKey, this.minecraftRegistry.get(CraftNamespacedKey.toMinecraft(namespacedKey)).orElse(null)); // Paper - switch to Holder + if (bukkit == null) { + return null; + } +@@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { + return this.stream().iterator(); + } + +- public B createBukkit(NamespacedKey namespacedKey, M minecraft) { ++ public B createBukkit(NamespacedKey namespacedKey, Holder minecraft) { // Paper - switch to Holder + if (minecraft == null) { + return null; + } + +- return this.minecraftToBukkit.apply(namespacedKey, minecraft); ++ return this.minecraftToBukkit.createBukkit(namespacedKey, minecraft); // Paper - switch to Holder ++ } ++ ++ // Paper start - support Direct Holders ++ public boolean supportsDirectHolders() { ++ return this.minecraftToBukkit.supportsDirectHolders(); ++ } ++ ++ public B convertDirectHolder(Holder holder) { ++ return this.minecraftToBukkit.convertDirectHolder(holder); + } ++ // Paper end - support Direct Holders + } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java diff --git a/patches/server/Add-registry-entry-and-builders.patch b/patches/server/Add-registry-entry-and-builders.patch index b385809ac7..f9fae971f6 100644 --- a/patches/server/Add-registry-entry-and-builders.patch +++ b/patches/server/Add-registry-entry-and-builders.patch @@ -22,22 +22,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 static { REGISTRY_ENTRIES = List.of( // built-ins -- entry(Registries.GAME_EVENT, RegistryKey.GAME_EVENT, GameEvent.class, CraftGameEvent::new), -+ writable(Registries.GAME_EVENT, RegistryKey.GAME_EVENT, GameEvent.class, CraftGameEvent::new, PaperGameEventRegistryEntry.PaperBuilder::new), - entry(Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE, StructureType.class, CraftStructureType::new), - entry(Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT, PotionEffectType.class, CraftPotionEffectType::new), - entry(Registries.BLOCK, RegistryKey.BLOCK, BlockType.class, CraftBlockType::new), +- start(Registries.GAME_EVENT, RegistryKey.GAME_EVENT).craft(GameEvent.class, CraftGameEvent::new).build(), ++ start(Registries.GAME_EVENT, RegistryKey.GAME_EVENT).craft(GameEvent.class, CraftGameEvent::new).writable(PaperGameEventRegistryEntry.PaperBuilder::new), + start(Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE).craft(StructureType.class, CraftStructureType::new).build(), + start(Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT).craft(PotionEffectType.class, CraftPotionEffectType::new).build(), + start(Registries.BLOCK, RegistryKey.BLOCK).craft(BlockType.class, CraftBlockType::new).build(), @@ -0,0 +0,0 @@ public final class PaperRegistries { - entry(Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN, TrimPattern.class, CraftTrimPattern::new).delayed(), - entry(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE, DamageType.class, CraftDamageType::new).delayed(), - entry(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT, Wolf.Variant.class, CraftWolf.CraftVariant::new).delayed(), -- entry(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, Enchantment.class, CraftEnchantment::new).withSerializationUpdater(FieldRename.ENCHANTMENT_RENAME).delayed(), -+ writable(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, Enchantment.class, CraftEnchantment::new, PaperEnchantmentRegistryEntry.PaperBuilder::new).withSerializationUpdater(FieldRename.ENCHANTMENT_RENAME).delayed(), - entry(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG, JukeboxSong.class, CraftJukeboxSong::new).delayed(), - entry(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN, PatternType.class, CraftPatternType::new).delayed(), -- entry(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT, Art.class, CraftArt::new).delayed(), -+ writable(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT, Art.class, CraftArt::new, PaperPaintingVariantRegistryEntry.PaperBuilder::new).delayed(), - entry(Registries.INSTRUMENT, RegistryKey.INSTRUMENT, MusicInstrument.class, CraftMusicInstrument::new).delayed(), + start(Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN).craft(TrimPattern.class, CraftTrimPattern::new).build().delayed(), + start(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE).craft(DamageType.class, CraftDamageType::new).build().delayed(), + start(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT).craft(Wolf.Variant.class, CraftWolf.CraftVariant::new).build().delayed(), +- start(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT).craft(Enchantment.class, CraftEnchantment::new).build().withSerializationUpdater(FieldRename.ENCHANTMENT_RENAME).delayed(), ++ start(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT).craft(Enchantment.class, CraftEnchantment::new).writable(PaperEnchantmentRegistryEntry.PaperBuilder::new).withSerializationUpdater(FieldRename.ENCHANTMENT_RENAME).delayed(), + start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).build().delayed(), + start(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN).craft(PatternType.class, CraftPatternType::new).build().delayed(), +- start(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT).craft(Art.class, CraftArt::new).build().delayed(), ++ start(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT).craft(Art.class, CraftArt::new).writable(PaperPaintingVariantRegistryEntry.PaperBuilder::new).delayed(), + start(Registries.INSTRUMENT, RegistryKey.INSTRUMENT).craft(MusicInstrument.class, CraftMusicInstrument::new).build().delayed(), // api-only diff --git a/src/main/java/io/papermc/paper/registry/data/PaperEnchantmentRegistryEntry.java b/src/main/java/io/papermc/paper/registry/data/PaperEnchantmentRegistryEntry.java @@ -103,7 +103,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public PaperEnchantmentRegistryEntry( + final Conversions conversions, -+ final TypedKey ignoredKey, + final @Nullable Enchantment internal + ) { + this.conversions = conversions; @@ -188,8 +187,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static final class PaperBuilder extends PaperEnchantmentRegistryEntry implements EnchantmentRegistryEntry.Builder, + PaperRegistryBuilder { + -+ public PaperBuilder(final Conversions conversions, final TypedKey key, final @Nullable Enchantment internal) { -+ super(conversions, key, internal); ++ public PaperBuilder(final Conversions conversions, final @Nullable Enchantment internal) { ++ super(conversions, internal); + } + + @Override @@ -300,7 +299,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public PaperGameEventRegistryEntry( + final Conversions ignoredConversions, -+ final io.papermc.paper.registry.TypedKey ignoredKey, + final @Nullable GameEvent internal + ) { + if (internal == null) return; @@ -318,10 +316,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public PaperBuilder( + final Conversions conversions, -+ final io.papermc.paper.registry.TypedKey key, + final @Nullable GameEvent internal + ) { -+ super(conversions, key, internal); ++ super(conversions, internal); + } + + @Override @@ -346,7 +343,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import io.papermc.paper.adventure.PaperAdventure; +import io.papermc.paper.registry.PaperRegistryBuilder; -+import io.papermc.paper.registry.TypedKey; +import io.papermc.paper.registry.data.util.Conversions; +import java.util.Optional; +import java.util.OptionalInt; @@ -356,14 +352,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import net.minecraft.world.entity.decoration.PaintingVariant; +import org.bukkit.Art; +import org.jetbrains.annotations.Range; -+import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +import static io.papermc.paper.registry.data.util.Checks.asArgument; +import static io.papermc.paper.registry.data.util.Checks.asArgumentRange; +import static io.papermc.paper.registry.data.util.Checks.asConfigured; + -+@NullMarked +public class PaperPaintingVariantRegistryEntry implements PaintingVariantRegistryEntry { + + protected OptionalInt width = OptionalInt.empty(); @@ -376,7 +370,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public PaperPaintingVariantRegistryEntry( + final Conversions conversions, -+ final TypedKey ignoredKey, + final @Nullable PaintingVariant internal + ) { + this.conversions = conversions; @@ -416,8 +409,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public static final class PaperBuilder extends PaperPaintingVariantRegistryEntry implements PaintingVariantRegistryEntry.Builder, PaperRegistryBuilder { + -+ public PaperBuilder(final Conversions conversions, final TypedKey key, final @Nullable PaintingVariant internal) { -+ super(conversions, key, internal); ++ public PaperBuilder(final Conversions conversions, final @Nullable PaintingVariant internal) { ++ super(conversions, internal); + } + + @Override diff --git a/patches/server/DataComponent-API.patch b/patches/server/DataComponent-API.patch index 5a0a7f4b7d..c73d7540b2 100644 --- a/patches/server/DataComponent-API.patch +++ b/patches/server/DataComponent-API.patch @@ -3704,19 +3704,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import com.google.common.base.Preconditions; import io.papermc.paper.adventure.PaperAdventure; -+import io.papermc.paper.datacomponent.DataComponentType; ++import io.papermc.paper.datacomponent.DataComponentTypes; +import io.papermc.paper.datacomponent.PaperDataComponentType; import io.papermc.paper.registry.data.PaperEnchantmentRegistryEntry; import io.papermc.paper.registry.data.PaperGameEventRegistryEntry; import io.papermc.paper.registry.data.PaperPaintingVariantRegistryEntry; @@ -0,0 +0,0 @@ public final class PaperRegistries { - entry(Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE, Attribute.class, CraftAttribute::new), - entry(Registries.FLUID, RegistryKey.FLUID, Fluid.class, CraftFluid::new), - entry(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT, Sound.class, CraftSound::new), -+ entry(Registries.DATA_COMPONENT_TYPE, RegistryKey.DATA_COMPONENT_TYPE, DataComponentType.class, PaperDataComponentType::of), + start(Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE).craft(Attribute.class, CraftAttribute::new).build(), + start(Registries.FLUID, RegistryKey.FLUID).craft(Fluid.class, CraftFluid::new).build(), + start(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT).craft(Sound.class, CraftSound::new).build(), ++ start(Registries.DATA_COMPONENT_TYPE, RegistryKey.DATA_COMPONENT_TYPE).craft(DataComponentTypes.class, PaperDataComponentType::of).build(), // data-drivens - entry(Registries.BIOME, RegistryKey.BIOME, Biome.class, CraftBiome::new).delayed(), + start(Registries.BIOME, RegistryKey.BIOME).craft(Biome.class, CraftBiome::new).build().delayed(), diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java diff --git a/patches/server/Fixup-NamespacedKey-handling.patch b/patches/server/Fixup-NamespacedKey-handling.patch index c691150656..89bfb62193 100644 --- a/patches/server/Fixup-NamespacedKey-handling.patch +++ b/patches/server/Fixup-NamespacedKey-handling.patch @@ -31,6 +31,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + public static java.util.Optional unwrapAndConvertHolder(final Registry registry, final Holder value) { ++ if (registry instanceof CraftRegistry craftRegistry && craftRegistry.supportsDirectHolders() && value.kind() == Holder.Kind.DIRECT) { ++ return java.util.Optional.of(((CraftRegistry) registry).convertDirectHolder(value)); ++ } + return value.unwrapKey().map(key -> registry.get(CraftNamespacedKey.fromMinecraft(key.location()))); + } + // Paper end - fixup upstream being dum @@ -80,22 +83,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java -@@ -0,0 +0,0 @@ public class CraftMetaArmor extends CraftMetaItem implements ArmorMeta { - super(tag); - - getOrEmpty(tag, CraftMetaArmor.TRIM).ifPresent((trimCompound) -> { -- TrimMaterial trimMaterial = CraftTrimMaterial.minecraftHolderToBukkit(trimCompound.material()); -- TrimPattern trimPattern = CraftTrimPattern.minecraftHolderToBukkit(trimCompound.pattern()); -+ TrimMaterial trimMaterial = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(io.papermc.paper.registry.RegistryKey.TRIM_MATERIAL, trimCompound.material()).orElse(null); // Paper - fix upstream not being correct -+ TrimPattern trimPattern = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(io.papermc.paper.registry.RegistryKey.TRIM_PATTERN, trimCompound.pattern()).orElse(null); // Paper - fix upstream not being correct -+ if (trimMaterial == null || trimPattern == null) return; // Paper - just delete the trim because upstream is not doing this right - - this.trim = new ArmorTrim(trimMaterial, trimPattern); - diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java @@ -109,19 +96,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (color != null && pattern != null) { this.patterns.add(new Pattern(color, pattern)); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java -@@ -0,0 +0,0 @@ public class CraftMetaMusicInstrument extends CraftMetaItem implements MusicInst - super(tag); - - getOrEmpty(tag, CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT).ifPresent((instrument) -> { -- this.instrument = CraftMusicInstrument.minecraftHolderToBukkit(instrument); -+ this.instrument = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(org.bukkit.Registry.INSTRUMENT, instrument).orElse(null); // Paper - fix upstream not handling inlined instrument - }); - } - diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaShield.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaShield.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaShield.java diff --git a/patches/server/Improve-Registry.patch b/patches/server/Improve-Registry.patch index 8627a2716b..df7e512c85 100644 --- a/patches/server/Improve-Registry.patch +++ b/patches/server/Improve-Registry.patch @@ -38,7 +38,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private final Map cache = new HashMap<>(); + private final Map byValue = new java.util.IdentityHashMap<>(); // Paper - improve Registry private final net.minecraft.core.Registry minecraftRegistry; - private final BiFunction minecraftToBukkit; + private final io.papermc.paper.registry.entry.RegistryTypeMapper minecraftToBukkit; // Paper - switch to Holder private final BiFunction serializationUpdater; // Paper - rename to make it *clear* what it is *only* for @@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { } @@ -49,9 +49,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return bukkit; } @@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { - - return this.minecraftToBukkit.apply(namespacedKey, minecraft); + return this.minecraftToBukkit.convertDirectHolder(holder); } + // Paper end - support Direct Holders + + // Paper start - improve Registry + @Override diff --git a/patches/server/Registry-Modification-API.patch b/patches/server/Registry-Modification-API.patch index e05b588afb..633bb895de 100644 --- a/patches/server/Registry-Modification-API.patch +++ b/patches/server/Registry-Modification-API.patch @@ -20,14 +20,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import java.util.Collections; import java.util.IdentityHashMap; import java.util.List; -@@ -0,0 +0,0 @@ import org.jspecify.annotations.Nullable; - - import static io.papermc.paper.registry.entry.RegistryEntry.apiOnly; - import static io.papermc.paper.registry.entry.RegistryEntry.entry; -+import static io.papermc.paper.registry.entry.RegistryEntry.writable; - - public final class PaperRegistries { - @@ -0,0 +0,0 @@ public final class PaperRegistries { return ResourceKey.create((ResourceKey>) PaperRegistries.registryToNms(typedKey.registryKey()), PaperAdventure.asVanilla(typedKey.key())); } @@ -81,17 +73,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @FunctionalInterface + interface Filler> { + -+ B fill(Conversions conversions, TypedKey key, @Nullable M nms); ++ B fill(Conversions conversions, @Nullable M nms); + + default Factory asFactory() { -+ return (lookup, key) -> this.fill(lookup, key, null); ++ return (lookup) -> this.fill(lookup, null); + } + } + + @FunctionalInterface + interface Factory> { + -+ B create(Conversions conversions, TypedKey key); ++ B create(Conversions conversions); + } +} diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java b/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java @@ -204,7 +196,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + final RegistryEntry.Modifiable modifiableEntry = RegistryEntry.Modifiable.asModifiable(entry); + @SuppressWarnings("PatternValidation") final TypedKey typedKey = TypedKey.create(entry.apiKey(), Key.key(key.location().getNamespace(), key.location().getPath())); -+ final B builder = modifiableEntry.fillBuilder(conversions, typedKey, nms); ++ final B builder = modifiableEntry.fillBuilder(conversions, nms); + return this.registerWithListeners(registry, modifiableEntry, key, nms, builder, registrationInfo, registerMethod, conversions); + } + @@ -324,9 +316,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package io.papermc.paper.registry; + +import com.mojang.serialization.Lifecycle; -+import io.papermc.paper.adventure.PaperAdventure; +import io.papermc.paper.registry.data.util.Conversions; +import io.papermc.paper.registry.entry.RegistryEntry; ++import io.papermc.paper.registry.entry.RegistryTypeMapper; +import io.papermc.paper.registry.event.WritableRegistry; +import java.util.Optional; +import java.util.function.BiFunction; @@ -338,7 +330,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import org.bukkit.NamespacedKey; +import org.bukkit.craftbukkit.CraftRegistry; +import org.bukkit.craftbukkit.util.ApiVersion; -+import org.jspecify.annotations.Nullable; + +public class WritableCraftRegistry> extends CraftRegistry { + @@ -347,7 +338,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private final RegistryEntry.BuilderHolder entry; + private final MappedRegistry registry; + private final PaperRegistryBuilder.Factory builderFactory; -+ private final BiFunction minecraftToBukkit; + + public WritableCraftRegistry( + final RegistryEntry.BuilderHolder entry, @@ -355,19 +345,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final MappedRegistry registry, + final BiFunction serializationUpdater, + final PaperRegistryBuilder.Factory builderFactory, -+ final BiFunction minecraftToBukkit ++ final RegistryTypeMapper minecraftToBukkit + ) { -+ super(classToPreload, registry, null, serializationUpdater); ++ super(classToPreload, registry, minecraftToBukkit, serializationUpdater); + this.entry = entry; + this.registry = registry; + this.builderFactory = builderFactory; -+ this.minecraftToBukkit = minecraftToBukkit; + } + + public void register(final TypedKey key, final Consumer value, final Conversions conversions) { -+ final ResourceKey resourceKey = ResourceKey.create(this.registry.key(), PaperAdventure.asVanilla(key.key())); ++ final ResourceKey resourceKey = PaperRegistries.toNms(key); + this.registry.validateWrite(resourceKey); -+ final B builder = this.newBuilder(conversions, key); ++ final B builder = this.newBuilder(conversions); + value.accept(builder); + PaperRegistryListenerManager.INSTANCE.registerWithListeners( + this.registry, @@ -379,24 +368,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ); + } + -+ @Override -+ public final @Nullable T createBukkit(final NamespacedKey namespacedKey, final @Nullable M minecraft) { -+ if (minecraft == null) { -+ return null; -+ } -+ return this.minecraftToBukkit(namespacedKey, minecraft); -+ } -+ + public WritableRegistry createApiWritableRegistry(final Conversions conversions) { + return new ApiWritableRegistry(conversions); + } + -+ public T minecraftToBukkit(final NamespacedKey namespacedKey, final M minecraft) { -+ return this.minecraftToBukkit.apply(namespacedKey, minecraft); -+ } -+ -+ protected B newBuilder(final Conversions conversions, final TypedKey key) { -+ return this.builderFactory.create(conversions, key); ++ protected B newBuilder(final Conversions conversions) { ++ return this.builderFactory.create(conversions); + } + + public class ApiWritableRegistry implements WritableRegistry { @@ -421,15 +398,40 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package io.papermc.paper.registry.data.util; + ++import com.google.common.base.Preconditions; +import com.mojang.serialization.JavaOps; +import io.papermc.paper.adventure.WrapperAwareSerializer; ++import java.util.Optional; +import net.kyori.adventure.text.Component; ++import net.minecraft.core.Registry; ++import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.RegistryOps; ++import net.minecraft.resources.ResourceKey; ++import org.bukkit.craftbukkit.CraftRegistry; +import org.jetbrains.annotations.Contract; +import org.jspecify.annotations.Nullable; + +public class Conversions { + ++ private static @Nullable Conversions globalInstance; ++ public static Conversions global() { ++ if (globalInstance == null) { ++ final RegistryAccess globalAccess = CraftRegistry.getMinecraftRegistry(); ++ Preconditions.checkState(globalAccess != null, "Global registry access is not available"); ++ globalInstance = new Conversions(new RegistryOps.RegistryInfoLookup() { ++ @Override ++ public Optional> lookup(final ResourceKey> registryRef) { ++ final Registry registry = globalAccess.lookupOrThrow(registryRef); ++ return Optional.of( ++ new RegistryOps.RegistryInfo<>(registry, registry, registry.registryLifecycle()) ++ ); ++ } ++ }); ++ } ++ return globalInstance; ++ } ++ ++ + private final RegistryOps.RegistryInfoLookup lookup; + private final WrapperAwareSerializer serializer; + @@ -473,15 +475,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.RegistryHolder; +import io.papermc.paper.registry.RegistryKey; -+import io.papermc.paper.registry.TypedKey; +import io.papermc.paper.registry.WritableCraftRegistry; +import io.papermc.paper.registry.data.util.Conversions; -+import java.util.function.BiFunction; +import net.minecraft.core.MappedRegistry; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import org.bukkit.Keyed; -+import org.bukkit.NamespacedKey; + +public class AddableRegistryEntry> extends CraftRegistryEntry implements RegistryEntry.Addable { + @@ -491,7 +490,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final ResourceKey> mcKey, + final RegistryKey apiKey, + final Class classToPreload, -+ final BiFunction minecraftToBukkit, ++ final RegistryTypeMapper minecraftToBukkit, + final PaperRegistryBuilder.Filler builderFiller + ) { + super(mcKey, apiKey, classToPreload, minecraftToBukkit); @@ -508,8 +507,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public B fillBuilder(final Conversions conversions, final TypedKey key, final M nms) { -+ return this.builderFiller.fill(conversions, key, nms); ++ public B fillBuilder(final Conversions conversions, final M nms) { ++ return this.builderFiller.fill(conversions, nms); + } +} diff --git a/src/main/java/io/papermc/paper/registry/entry/ModifiableRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/ModifiableRegistryEntry.java @@ -522,13 +521,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.RegistryKey; -+import io.papermc.paper.registry.TypedKey; +import io.papermc.paper.registry.data.util.Conversions; -+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> extends CraftRegistryEntry implements RegistryEntry.Modifiable { + @@ -538,7 +534,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final ResourceKey> mcKey, + final RegistryKey apiKey, + final Class toPreload, -+ final BiFunction minecraftToBukkit, ++ final RegistryTypeMapper minecraftToBukkit, + final PaperRegistryBuilder.Filler builderFiller + ) { + super(mcKey, apiKey, toPreload, minecraftToBukkit); @@ -546,8 +542,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public B fillBuilder(final Conversions conversions, final TypedKey key, final M nms) { -+ return this.builderFiller.fill(conversions, key, nms); ++ public B fillBuilder(final Conversions conversions, final M nms) { ++ return this.builderFiller.fill(conversions, 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 @@ -567,8 +563,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import io.papermc.paper.registry.event.RegistryFreezeEventImpl; import io.papermc.paper.registry.legacy.DelayedRegistryEntry; import java.util.function.BiFunction; - import java.util.function.Supplier; -@@ -0,0 +0,0 @@ import net.minecraft.resources.ResourceKey; + import net.minecraft.core.Registry; import org.bukkit.Keyed; import org.bukkit.NamespacedKey; import org.bukkit.craftbukkit.util.ApiVersion; @@ -577,12 +572,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public interface RegistryEntry extends RegistryEntryInfo { // TODO remove Keyed @@ -0,0 +0,0 @@ public interface RegistryEntry extends RegistryEntryInfo delayed() { return new DelayedRegistryEntry<>(this); } - ++ + interface BuilderHolder> extends RegistryEntryInfo { + -+ B fillBuilder(Conversions conversions, TypedKey key, M nms); ++ B fillBuilder(Conversions conversions, M nms); + } + + /** @@ -638,34 +634,36 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private static RegistryEntryInfo possiblyUnwrap(final RegistryEntryInfo entry) { + return entry instanceof final DelayedRegistryEntry delayed ? delayed.delegate() : entry; + } + } +diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryEntryBuilder.java b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryBuilder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/io/papermc/paper/registry/entry/RegistryEntryBuilder.java ++++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryBuilder.java +@@ -0,0 +0,0 @@ + package io.papermc.paper.registry.entry; + + import com.mojang.datafixers.util.Either; ++import io.papermc.paper.registry.PaperRegistryBuilder; + import io.papermc.paper.registry.RegistryKey; + import java.util.function.BiFunction; + import java.util.function.Function; +@@ -0,0 +0,0 @@ public class RegistryEntryBuilder { // TODO remove Keyed + public RegistryEntry build() { + return new CraftRegistryEntry<>(this.mcKey, this.apiKey, this.classToPreload, this.minecraftToBukkit); + } + - static RegistryEntry entry( - final ResourceKey> mcKey, - final RegistryKey apiKey, -@@ -0,0 +0,0 @@ public interface RegistryEntry extends RegistryEntryInfo(mcKey, apiKey, apiRegistrySupplier); ++ public > RegistryEntry modifiable(final PaperRegistryBuilder.Filler filler) { ++ return new ModifiableRegistryEntry<>(this.mcKey, this.apiKey, this.classToPreload, this.minecraftToBukkit, filler); ++ } ++ ++ public > RegistryEntry addable(final PaperRegistryBuilder.Filler filler) { ++ return new AddableRegistryEntry<>(this.mcKey, this.apiKey, this.classToPreload, this.minecraftToBukkit, filler); ++ } ++ ++ public > RegistryEntry writable(final PaperRegistryBuilder.Filler filler) { ++ return new WritableRegistryEntry<>(this.mcKey, this.apiKey, this.classToPreload, this.minecraftToBukkit, filler); ++ } } -+ -+ static > RegistryEntry modifiable( -+ final ResourceKey> mcKey, -+ final RegistryKey apiKey, -+ final Class toPreload, -+ final BiFunction minecraftToBukkit, -+ final PaperRegistryBuilder.Filler filler -+ ) { -+ return new ModifiableRegistryEntry<>(mcKey, apiKey, toPreload, minecraftToBukkit, filler); -+ } -+ -+ static > RegistryEntry writable( -+ final ResourceKey> mcKey, -+ final RegistryKey apiKey, -+ final Class toPreload, -+ final BiFunction minecraftToBukkit, -+ final PaperRegistryBuilder.Filler 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 @@ -675,9 +673,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package io.papermc.paper.registry.entry; + ++import com.mojang.datafixers.util.Either; +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.RegistryKey; +import java.util.function.BiFunction; ++import java.util.function.Function; ++import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import org.bukkit.Keyed; @@ -689,7 +690,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final ResourceKey> mcKey, + final RegistryKey apiKey, + final Class classToPreload, -+ final BiFunction minecraftToBukkit, ++ final RegistryTypeMapper minecraftToBukkit, + final PaperRegistryBuilder.Filler builderFiller + ) { + super(mcKey, apiKey, classToPreload, minecraftToBukkit, builderFiller); @@ -1213,40 +1214,12 @@ diff --git a/src/main/java/net/minecraft/resources/RegistryDataLoader.java b/src index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/resources/RegistryDataLoader.java +++ b/src/main/java/net/minecraft/resources/RegistryDataLoader.java -@@ -0,0 +0,0 @@ public class RegistryDataLoader { - public static RegistryAccess.Frozen load( - ResourceManager resourceManager, List> registries, List> entries - ) { -- return load((loader, infoGetter) -> loader.loadFromResources(resourceManager, infoGetter), registries, entries); -+ return load((loader, infoGetter, conversions) -> loader.loadFromResources(resourceManager, infoGetter, conversions), registries, entries); // Paper - pass conversions - } - - public static RegistryAccess.Frozen load( -@@ -0,0 +0,0 @@ public class RegistryDataLoader { - List> registries, - List> entries - ) { -- return load((loader, infoGetter) -> loader.loadFromNetwork(data, factory, infoGetter), registries, entries); -+ return load((loader, infoGetter, conversions) -> loader.loadFromNetwork(data, factory, infoGetter, conversions), registries, entries); // Paper - pass conversions - } - - private static RegistryAccess.Frozen load( -@@ -0,0 +0,0 @@ public class RegistryDataLoader { - Map, Exception> map = new HashMap<>(); - List> list = entries.stream().map(entry -> entry.create(Lifecycle.stable(), map)).collect(Collectors.toUnmodifiableList()); - RegistryOps.RegistryInfoLookup registryInfoLookup = createContext(registries, list); -- list.forEach(loader -> loadable.apply((RegistryDataLoader.Loader)loader, registryInfoLookup)); -+ final io.papermc.paper.registry.data.util.Conversions conversions = new io.papermc.paper.registry.data.util.Conversions(registryInfoLookup); // Paper - create conversions -+ list.forEach(loader -> loadable.apply((RegistryDataLoader.Loader)loader, registryInfoLookup, conversions)); - list.forEach(loader -> { - Registry registry = loader.registry(); - @@ -0,0 +0,0 @@ public class RegistryDataLoader { } private static void loadElementFromResource( - WritableRegistry registry, Decoder decoder, RegistryOps ops, ResourceKey key, Resource resource, RegistrationInfo entryInfo -+ WritableRegistry registry, Decoder decoder, RegistryOps ops, ResourceKey key, Resource resource, RegistrationInfo entryInfo, io.papermc.paper.registry.data.util.Conversions conversions ++ WritableRegistry registry, Decoder decoder, RegistryOps ops, ResourceKey key, Resource resource, RegistrationInfo entryInfo, io.papermc.paper.registry.data.util.Conversions conversions // Paper - pass conversions ) throws IOException { try (Reader reader = resource.openAsReader()) { JsonElement jsonElement = JsonParser.parseReader(reader); @@ -1258,15 +1231,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } @@ -0,0 +0,0 @@ public class RegistryDataLoader { - RegistryOps.RegistryInfoLookup infoGetter, - WritableRegistry registry, - Decoder elementDecoder, -- Map, Exception> errors -+ Map, Exception> errors, -+ io.papermc.paper.registry.data.util.Conversions conversions // Paper - pass conversions - ) { FileToIdConverter fileToIdConverter = FileToIdConverter.registry(registry.key()); RegistryOps registryOps = RegistryOps.create(JsonOps.INSTANCE, infoGetter); + ++ final io.papermc.paper.registry.data.util.Conversions conversions = new io.papermc.paper.registry.data.util.Conversions(infoGetter); // Paper - create conversions + for (Entry entry : fileToIdConverter.listMatchingResources(resourceManager).entrySet()) { + ResourceLocation resourceLocation = entry.getKey(); + ResourceKey resourceKey = ResourceKey.create(registry.key(), fileToIdConverter.fileToId(resourceLocation)); @@ -0,0 +0,0 @@ public class RegistryDataLoader { RegistrationInfo registrationInfo = REGISTRATION_INFO_CACHE.apply(resource.knownPackInfo()); @@ -1285,15 +1256,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } @@ -0,0 +0,0 @@ public class RegistryDataLoader { - RegistryOps.RegistryInfoLookup infoGetter, - WritableRegistry registry, - Decoder decoder, -- Map, Exception> loadingErrors -+ Map, Exception> loadingErrors, -+ io.papermc.paper.registry.data.util.Conversions conversions // Paper - pass conversions - ) { - RegistryDataLoader.NetworkedRegistryData networkedRegistryData = data.get(registry.key()); - if (networkedRegistryData != null) { + RegistryOps registryOps2 = RegistryOps.create(JsonOps.INSTANCE, infoGetter); + FileToIdConverter fileToIdConverter = FileToIdConverter.registry(registry.key()); + ++ final io.papermc.paper.registry.data.util.Conversions conversions = new io.papermc.paper.registry.data.util.Conversions(infoGetter); // Paper - create conversions + for (RegistrySynchronization.PackedRegistryEntry packedRegistryEntry : networkedRegistryData.elements) { + ResourceKey resourceKey = ResourceKey.create(registry.key(), packedRegistryEntry.id()); + Optional optional = packedRegistryEntry.data(); @@ -0,0 +0,0 @@ public class RegistryDataLoader { try { @@ -1303,35 +1272,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } catch (Exception var17) { loadingErrors.put(resourceKey, new IllegalStateException("Failed to parse local data", var17)); } -@@ -0,0 +0,0 @@ public class RegistryDataLoader { - } - - static record Loader(RegistryDataLoader.RegistryData data, WritableRegistry registry, Map, Exception> loadingErrors) { -- public void loadFromResources(ResourceManager resourceManager, RegistryOps.RegistryInfoLookup infoGetter) { -- RegistryDataLoader.loadContentsFromManager(resourceManager, infoGetter, this.registry, this.data.elementCodec, this.loadingErrors); -+ public void loadFromResources(ResourceManager resourceManager, RegistryOps.RegistryInfoLookup infoGetter, io.papermc.paper.registry.data.util.Conversions conversions) { // Paper - pass conversions -+ RegistryDataLoader.loadContentsFromManager(resourceManager, infoGetter, this.registry, this.data.elementCodec, this.loadingErrors, conversions); // Paper - pass conversions - } - - public void loadFromNetwork( - Map>, RegistryDataLoader.NetworkedRegistryData> data, - ResourceProvider factory, -- RegistryOps.RegistryInfoLookup infoGetter -+ RegistryOps.RegistryInfoLookup infoGetter, -+ io.papermc.paper.registry.data.util.Conversions conversions // Paper - ) { -- RegistryDataLoader.loadContentsFromNetwork(data, factory, infoGetter, this.registry, this.data.elementCodec, this.loadingErrors); -+ RegistryDataLoader.loadContentsFromNetwork(data, factory, infoGetter, this.registry, this.data.elementCodec, this.loadingErrors, conversions); // Paper - pass conversions - } - } - - @FunctionalInterface - interface LoadingFunction { -- void apply(RegistryDataLoader.Loader loader, RegistryOps.RegistryInfoLookup infoGetter); -+ void apply(RegistryDataLoader.Loader loader, RegistryOps.RegistryInfoLookup infoGetter, io.papermc.paper.registry.data.util.Conversions conversions); // Paper - pass conversions - } - - public static record NetworkedRegistryData(List elements, TagNetworkSerialization.NetworkPayload tags) { diff --git a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java @@ -1368,20 +1308,6 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/ index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java -@@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { - private final Map cache = new HashMap<>(); - private final Map byValue = new java.util.IdentityHashMap<>(); // Paper - improve Registry - private final net.minecraft.core.Registry minecraftRegistry; -- private final BiFunction minecraftToBukkit; -+ private final BiFunction minecraftToBukkit; // Paper - private final BiFunction serializationUpdater; // Paper - rename to make it *clear* what it is *only* for - private boolean init; - -- public CraftRegistry(Class bukkitClass, net.minecraft.core.Registry minecraftRegistry, BiFunction minecraftToBukkit, BiFunction serializationUpdater) { // Paper - relax preload class -+ public CraftRegistry(Class bukkitClass, net.minecraft.core.Registry minecraftRegistry, BiFunction minecraftToBukkit, BiFunction serializationUpdater) { // Paper - relax preload class - this.bukkitClass = bukkitClass; - this.minecraftRegistry = minecraftRegistry; - this.minecraftToBukkit = minecraftToBukkit; @@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { return this.byValue.get(value); } @@ -1452,7 +1378,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + void testEquality(final RegistryEntry.BuilderHolder registryEntry) { + final Registry registry = RegistryHelper.getRegistry().lookupOrThrow(registryEntry.mcKey()); + for (final Map.Entry, M> entry : registry.entrySet()) { -+ final M built = registryEntry.fillBuilder(new Conversions(new RegistryOps.HolderLookupAdapter(RegistryHelper.getRegistry())), PaperRegistries.fromNms(entry.getKey()), entry.getValue()).build(); ++ final M built = registryEntry.fillBuilder(new Conversions(new RegistryOps.HolderLookupAdapter(RegistryHelper.getRegistry())), entry.getValue()).build(); + assertEquals(entry.getValue(), built); + } + } diff --git a/patches/server/Switch-Impl-types-to-Holderable.patch b/patches/server/Switch-Impl-types-to-Holderable.patch new file mode 100644 index 0000000000..bf093310c0 --- /dev/null +++ b/patches/server/Switch-Impl-types-to-Holderable.patch @@ -0,0 +1,494 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sun, 24 Nov 2024 15:08:19 -0800 +Subject: [PATCH] Switch Impl types to Holderable + + +diff --git a/src/main/java/io/papermc/paper/util/Holderable.java b/src/main/java/io/papermc/paper/util/Holderable.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/io/papermc/paper/util/Holderable.java ++++ b/src/main/java/io/papermc/paper/util/Holderable.java +@@ -0,0 +0,0 @@ + package io.papermc.paper.util; + ++import com.google.gson.JsonElement; ++import com.google.gson.JsonObject; ++import com.mojang.serialization.Codec; ++import com.mojang.serialization.JsonOps; ++import net.kyori.adventure.key.Key; + import net.minecraft.core.Holder; ++import net.minecraft.resources.RegistryOps; ++import org.bukkit.Keyed; ++import org.bukkit.Registry; ++import org.bukkit.craftbukkit.CraftRegistry; + import org.bukkit.craftbukkit.util.Handleable; ++import org.intellij.lang.annotations.Subst; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; + ++@NullMarked + public interface Holderable extends Handleable { + + Holder getHolder(); +@@ -0,0 +0,0 @@ public interface Holderable extends Handleable { + default M getHandle() { + return this.getHolder().value(); + } ++ ++ static @Nullable T fromBukkitSerializationObject(final Object deserialized, final Codec> codec, final Registry registry) { // TODO remove Keyed ++ return switch (deserialized) { ++ case @Subst("key:value") final String string -> { ++ if (!(Key.parseable(string))) { ++ yield null; ++ } ++ yield registry.get(Key.key(string)); ++ } ++ case JsonObjectWrapper(final JsonObject element) -> { ++ if (!(registry instanceof final CraftRegistry craftRegistry) || !craftRegistry.supportsDirectHolders()) { ++ throw new IllegalArgumentException("Cannot deserialize direct holders for " + registry); ++ } ++ final RegistryOps ops = CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE); ++ final Holder holder = codec.decode(ops, element).getOrThrow().getFirst(); ++ yield ((CraftRegistry) registry).convertDirectHolder(holder); ++ } ++ default -> throw new IllegalArgumentException("Cannot deserialize " + deserialized); ++ }; ++ } ++ ++ default Object toBukkitSerializationObject(final Codec> codec) { ++ return switch (this.getHolder()) { ++ case final Holder.Direct direct -> { ++ final RegistryOps ops = CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE); ++ yield new JsonObjectWrapper(codec.encodeStart(ops, direct).getOrThrow().getAsJsonObject()); ++ } ++ case final Holder.Reference reference -> reference.key().location().toString(); ++ default -> throw new IllegalArgumentException("Cannot serialize " + this.getHolder()); ++ }; ++ } ++ ++ /** ++ * All implementations should use this as their hashCode implementation ++ */ ++ default int implHashCode() { ++ return this.getHolder().hashCode(); ++ } ++ ++ /** ++ * All implementations should use this as their equals implementation ++ */ ++ default boolean implEquals(final @Nullable Object o) { ++ if (o == null || this.getClass() != o.getClass()) return false; ++ final Holderable that = (Holderable) o; ++ return this.getHolder().equals(that.getHolder()); ++ } ++ ++ default String implToString() { ++ return "%s{holder=%s}".formatted(this.getClass().getSimpleName(), this.getHolder().toString()); ++ } + } +diff --git a/src/main/java/io/papermc/paper/util/JsonObjectWrapper.java b/src/main/java/io/papermc/paper/util/JsonObjectWrapper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/JsonObjectWrapper.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.util; ++ ++import com.google.gson.Gson; ++import com.google.gson.JsonElement; ++import com.google.gson.JsonObject; ++import com.google.gson.JsonParser; ++import java.util.Map; ++import org.bukkit.configuration.serialization.ConfigurationSerializable; ++import org.bukkit.configuration.serialization.ConfigurationSerialization; ++import org.jspecify.annotations.NullMarked; ++ ++@NullMarked ++public record JsonObjectWrapper(JsonObject element) implements ConfigurationSerializable { ++ ++ private static final String KEY = "value"; ++ private static final Gson GSON = new Gson(); ++ ++ static { ++ ConfigurationSerialization.registerClass(JsonObjectWrapper.class); ++ } ++ ++ public JsonObjectWrapper(final JsonElement element) { ++ this(element.getAsJsonObject()); ++ } ++ ++ public JsonObjectWrapper(final Map input) { ++ this(JsonParser.parseString((String) input.get(KEY)).getAsJsonObject()); ++ } ++ ++ @Override ++ public Map serialize() { ++ return Map.of(KEY, GSON.toJson(this.element)); ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java b/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java +@@ -0,0 +0,0 @@ import org.bukkit.Registry; + import org.bukkit.craftbukkit.util.Handleable; + import org.jetbrains.annotations.NotNull; + +-public class CraftMusicInstrument extends MusicInstrument implements Handleable { ++public class CraftMusicInstrument extends MusicInstrument implements io.papermc.paper.util.Holderable { + + public static MusicInstrument minecraftToBukkit(Instrument minecraft) { + return CraftRegistry.minecraftToBukkit(minecraft, Registries.INSTRUMENT, Registry.INSTRUMENT); + } + + public static MusicInstrument minecraftHolderToBukkit(Holder minecraft) { +- return CraftMusicInstrument.minecraftToBukkit(minecraft.value()); ++ return CraftRegistry.minecraftHolderToBukkit(minecraft, Registry.INSTRUMENT); // Paper - switch to Holder + } + + public static Instrument bukkitToMinecraft(MusicInstrument bukkit) { +@@ -0,0 +0,0 @@ public class CraftMusicInstrument extends MusicInstrument implements Handleable< + } + + public static Holder bukkitToMinecraftHolder(MusicInstrument bukkit) { +- Preconditions.checkArgument(bukkit != null); +- +- net.minecraft.core.Registry registry = CraftRegistry.getMinecraftRegistry(Registries.INSTRUMENT); +- +- if (registry.wrapAsHolder(CraftMusicInstrument.bukkitToMinecraft(bukkit)) instanceof Holder.Reference holder) { +- return holder; +- } +- +- throw new IllegalArgumentException("No Reference holder found for " + bukkit +- + ", this can happen if a plugin creates its own instrument without properly registering it."); ++ return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.INSTRUMENT); // Paper - switch to Holder + } + +- public static String bukkitToString(MusicInstrument bukkit) { ++ public static Object bukkitToString(MusicInstrument bukkit) { // Paper - switch to Holder + Preconditions.checkArgument(bukkit != null); + +- return bukkit.getKey().toString(); ++ return ((CraftMusicInstrument) bukkit).toBukkitSerializationObject(Instrument.CODEC); // Paper - switch to Holder + } + +- public static MusicInstrument stringToBukkit(String string) { ++ public static MusicInstrument stringToBukkit(Object string) { // Paper - switch to Holder + Preconditions.checkArgument(string != null); + +- return Registry.INSTRUMENT.get(NamespacedKey.fromString(string)); ++ return io.papermc.paper.util.Holderable.fromBukkitSerializationObject(string, Instrument.CODEC, Registry.INSTRUMENT); // Paper - switch to Holder + } + + private final NamespacedKey key; + private final Instrument handle; + +- public CraftMusicInstrument(NamespacedKey key, Instrument handle) { +- this.key = key; +- this.handle = handle; ++ // Paper start - switch to Holder ++ @Override ++ public boolean equals(final Object o) { ++ return this.implEquals(o); ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.implHashCode(); ++ } ++ ++ @Override ++ public String toString() { ++ return this.implToString(); ++ } ++ ++ private final Holder holder; ++ public CraftMusicInstrument(Holder holder) { ++ this.holder = holder; ++ this.key = holder.unwrapKey().map(io.papermc.paper.util.MCUtil::fromResourceKey).orElse(null); ++ this.handle = holder.value(); ++ // Paper end - switch to Holder + } + + @Override +- public Instrument getHandle() { +- return this.handle; ++ public Holder getHolder() { // Paper - switch to Holder ++ return this.holder; // Paper - switch to Holder + } + + @NotNull +@@ -0,0 +0,0 @@ public class CraftMusicInstrument extends MusicInstrument implements Handleable< + } + // Paper end - add translationKey methods + +- @Override +- public boolean equals(Object other) { +- if (this == other) { +- return true; +- } +- +- if (!(other instanceof CraftMusicInstrument)) { +- return false; +- } +- +- return this.getKey().equals(((MusicInstrument) other).getKey()); +- } +- +- @Override +- public int hashCode() { +- return this.getKey().hashCode(); +- } +- +- @Override +- public String toString() { +- return "CraftMusicInstrument{key=" + this.key + "}"; +- } ++ // Paper - switch to Holder + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java +@@ -0,0 +0,0 @@ public class CraftMetaArmor extends CraftMetaItem implements ArmorMeta { + + Map trimData = SerializableMeta.getObject(Map.class, map, CraftMetaArmor.TRIM.BUKKIT, true); + if (trimData != null) { +- String materialKeyString = SerializableMeta.getString(trimData, CraftMetaArmor.TRIM_MATERIAL.BUKKIT, true); +- String patternKeyString = SerializableMeta.getString(trimData, CraftMetaArmor.TRIM_PATTERN.BUKKIT, true); ++ Object materialKeyString = SerializableMeta.getObject(Object.class, trimData, CraftMetaArmor.TRIM_MATERIAL.BUKKIT, true); // Paper - switch to Holder ++ Object patternKeyString = SerializableMeta.getObject(Object.class, trimData, CraftMetaArmor.TRIM_PATTERN.BUKKIT, true); // Paper - switch to Holder + + if (materialKeyString != null && patternKeyString != null) { +- NamespacedKey materialKey = NamespacedKey.fromString(materialKeyString); +- NamespacedKey patternKey = NamespacedKey.fromString(patternKeyString); +- +- if (materialKey != null && patternKey != null) { +- TrimMaterial trimMaterial = Registry.TRIM_MATERIAL.get(materialKey); +- TrimPattern trimPattern = Registry.TRIM_PATTERN.get(patternKey); +- +- if (trimMaterial != null && trimPattern != null) { +- this.trim = new ArmorTrim(trimMaterial, trimPattern); +- } ++ // Paper start - switch to Holder ++ TrimMaterial trimMaterial = CraftTrimMaterial.objectToBukkit(materialKeyString); ++ TrimPattern trimPattern = CraftTrimPattern.objectToBukkit(patternKeyString); ++ if (trimMaterial != null && trimPattern != null) { ++ this.trim = new ArmorTrim(trimMaterial, trimPattern); + } ++ // Paper end - switch to Holder + } + } + } +@@ -0,0 +0,0 @@ public class CraftMetaArmor extends CraftMetaItem implements ArmorMeta { + super.serialize(builder); + + if (this.hasTrim()) { +- Map trimData = new HashMap<>(); +- trimData.put(CraftMetaArmor.TRIM_MATERIAL.BUKKIT, this.trim.getMaterial().getKey().toString()); +- trimData.put(CraftMetaArmor.TRIM_PATTERN.BUKKIT, this.trim.getPattern().getKey().toString()); ++ Map trimData = new HashMap<>(); // Paper - switch to Holder ++ trimData.put(CraftMetaArmor.TRIM_MATERIAL.BUKKIT, CraftTrimMaterial.bukkitToObject(this.trim.getMaterial())); // Paper - switch to Holder ++ trimData.put(CraftMetaArmor.TRIM_PATTERN.BUKKIT, CraftTrimPattern.bukkitToObject(this.trim.getPattern())); // Paper - switch to Holder + builder.put(CraftMetaArmor.TRIM.BUKKIT, trimData); + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java +@@ -0,0 +0,0 @@ public class CraftMetaMusicInstrument extends CraftMetaItem implements MusicInst + CraftMetaMusicInstrument(Map map) { + super(map); + +- String instrumentString = SerializableMeta.getString(map, CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT.BUKKIT, true); ++ Object instrumentString = SerializableMeta.getObject(Object.class, map, CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT.BUKKIT, true); // Paper - switch to Holder + if (instrumentString != null) { + this.instrument = CraftMusicInstrument.stringToBukkit(instrumentString); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java +@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.util.Handleable; + import org.bukkit.inventory.meta.trim.TrimMaterial; + import org.jetbrains.annotations.NotNull; + +-public class CraftTrimMaterial implements TrimMaterial, Handleable { ++public class CraftTrimMaterial implements TrimMaterial, io.papermc.paper.util.Holderable { // Paper - switch to Holder + + public static TrimMaterial minecraftToBukkit(net.minecraft.world.item.equipment.trim.TrimMaterial minecraft) { + return CraftRegistry.minecraftToBukkit(minecraft, Registries.TRIM_MATERIAL, Registry.TRIM_MATERIAL); + } + + public static TrimMaterial minecraftHolderToBukkit(Holder minecraft) { +- return CraftTrimMaterial.minecraftToBukkit(minecraft.value()); ++ return CraftRegistry.minecraftHolderToBukkit(minecraft, Registry.TRIM_MATERIAL); // Paper - switch to Holder + } + + public static net.minecraft.world.item.equipment.trim.TrimMaterial bukkitToMinecraft(TrimMaterial bukkit) { +@@ -0,0 +0,0 @@ public class CraftTrimMaterial implements TrimMaterial, Handleable bukkitToMinecraftHolder(TrimMaterial bukkit) { ++ return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.TRIM_MATERIAL); // Paper - switch to Holder ++ } ++ ++ private final NamespacedKey key; ++ private final net.minecraft.world.item.equipment.trim.TrimMaterial handle; ++ ++ // Paper start - switch to Holder ++ private final Holder holder; ++ ++ public static Object bukkitToObject(TrimMaterial bukkit) { + Preconditions.checkArgument(bukkit != null); + +- net.minecraft.core.Registry registry = CraftRegistry.getMinecraftRegistry(Registries.TRIM_MATERIAL); ++ return ((CraftTrimMaterial) bukkit).toBukkitSerializationObject(net.minecraft.world.item.equipment.trim.TrimMaterial.CODEC); // Paper - switch to Holder ++ } + +- if (registry.wrapAsHolder(CraftTrimMaterial.bukkitToMinecraft(bukkit)) instanceof Holder.Reference holder) { +- return holder; +- } ++ public static TrimMaterial objectToBukkit(Object object) { ++ Preconditions.checkArgument(object != null); + +- throw new IllegalArgumentException("No Reference holder found for " + bukkit +- + ", this can happen if a plugin creates its own trim material without properly registering it."); ++ return io.papermc.paper.util.Holderable.fromBukkitSerializationObject(object, net.minecraft.world.item.equipment.trim.TrimMaterial.CODEC, Registry.TRIM_MATERIAL); // Paper - switch to Holder + } + +- private final NamespacedKey key; +- private final net.minecraft.world.item.equipment.trim.TrimMaterial handle; ++ @Override ++ public boolean equals(final Object o) { ++ return this.implEquals(o); ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.implHashCode(); ++ } ++ ++ @Override ++ public String toString() { ++ return this.implToString(); ++ } + +- public CraftTrimMaterial(NamespacedKey key, net.minecraft.world.item.equipment.trim.TrimMaterial handle) { +- this.key = key; +- this.handle = handle; ++ public CraftTrimMaterial(final Holder holder) { ++ this.key = holder.unwrapKey().map(io.papermc.paper.util.MCUtil::fromResourceKey).orElse(null); ++ this.handle = holder.value(); ++ this.holder = holder; ++ // Paper end - switch to Holder + } + + @Override +- public net.minecraft.world.item.equipment.trim.TrimMaterial getHandle() { +- return this.handle; ++ public Holder getHolder() { // Paper - switch to Holder ++ return this.holder; // Paper - switch to Holder + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java +@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.util.Handleable; + import org.bukkit.inventory.meta.trim.TrimPattern; + import org.jetbrains.annotations.NotNull; + +-public class CraftTrimPattern implements TrimPattern, Handleable { ++public class CraftTrimPattern implements TrimPattern, io.papermc.paper.util.Holderable { // Paper - switch to Holder + + public static TrimPattern minecraftToBukkit(net.minecraft.world.item.equipment.trim.TrimPattern minecraft) { + return CraftRegistry.minecraftToBukkit(minecraft, Registries.TRIM_PATTERN, Registry.TRIM_PATTERN); + } + + public static TrimPattern minecraftHolderToBukkit(Holder minecraft) { +- return CraftTrimPattern.minecraftToBukkit(minecraft.value()); ++ return CraftRegistry.minecraftHolderToBukkit(minecraft, Registry.TRIM_PATTERN); // Paper - switch to Holder + } + + public static net.minecraft.world.item.equipment.trim.TrimPattern bukkitToMinecraft(TrimPattern bukkit) { +@@ -0,0 +0,0 @@ public class CraftTrimPattern implements TrimPattern, Handleable bukkitToMinecraftHolder(TrimPattern bukkit) { ++ return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.TRIM_PATTERN); // Paper - switch to Holder ++ } ++ ++ private final NamespacedKey key; ++ private final net.minecraft.world.item.equipment.trim.TrimPattern handle; ++ ++ // Paper start - switch to Holder ++ private final Holder holder; // Paper - switch to Holder ++ ++ public static Object bukkitToObject(TrimPattern bukkit) { + Preconditions.checkArgument(bukkit != null); + +- net.minecraft.core.Registry registry = CraftRegistry.getMinecraftRegistry(Registries.TRIM_PATTERN); ++ return ((CraftTrimPattern) bukkit).toBukkitSerializationObject(net.minecraft.world.item.equipment.trim.TrimPattern.CODEC); // Paper - switch to Holder ++ } + +- if (registry.wrapAsHolder(CraftTrimPattern.bukkitToMinecraft(bukkit)) instanceof Holder.Reference holder) { +- return holder; +- } ++ public static TrimPattern objectToBukkit(Object object) { ++ Preconditions.checkArgument(object != null); + +- throw new IllegalArgumentException("No Reference holder found for " + bukkit +- + ", this can happen if a plugin creates its own trim pattern without properly registering it."); ++ return io.papermc.paper.util.Holderable.fromBukkitSerializationObject(object, net.minecraft.world.item.equipment.trim.TrimPattern.CODEC, Registry.TRIM_PATTERN); // Paper - switch to Holder + } + +- private final NamespacedKey key; +- private final net.minecraft.world.item.equipment.trim.TrimPattern handle; ++ @Override ++ public boolean equals(final Object o) { ++ return this.implEquals(o); ++ } ++ ++ @Override ++ public int hashCode() { ++ return this.implHashCode(); ++ } ++ ++ @Override ++ public String toString() { ++ return this.implToString(); ++ } + +- public CraftTrimPattern(NamespacedKey key, net.minecraft.world.item.equipment.trim.TrimPattern handle) { +- this.key = key; +- this.handle = handle; ++ public CraftTrimPattern(Holder handle) { ++ this.key = handle.unwrapKey().map(io.papermc.paper.util.MCUtil::fromResourceKey).orElse(null); ++ this.handle = handle.value(); ++ this.holder = handle; ++ // Paper end - switch to Holder + } + + @Override +- public net.minecraft.world.item.equipment.trim.TrimPattern getHandle() { +- return this.handle; ++ public Holder getHolder() { // Paper - switch to Holder ++ return this.holder; // Paper - switch to Holder + } + + @Override +diff --git a/src/test/java/org/bukkit/registry/RegistryConversionTest.java b/src/test/java/org/bukkit/registry/RegistryConversionTest.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/registry/RegistryConversionTest.java ++++ b/src/test/java/org/bukkit/registry/RegistryConversionTest.java +@@ -0,0 +0,0 @@ public class RegistryConversionTest { + Class craftClazz, Class minecraftClazz) throws IllegalAccessException { + this.checkValidMinecraftToBukkit(clazz); + ++ if (type == io.papermc.paper.registry.RegistryKey.TRIM_MATERIAL || type == io.papermc.paper.registry.RegistryKey.TRIM_PATTERN || type == io.papermc.paper.registry.RegistryKey.INSTRUMENT) return; // Paper - manually skip for now + try { + + Object minecraft = mock(minecraftClazz); diff --git a/patches/server/improve-checking-handled-tags-in-itemmeta.patch b/patches/server/improve-checking-handled-tags-in-itemmeta.patch index ab7a975885..6009255e15 100644 --- a/patches/server/improve-checking-handled-tags-in-itemmeta.patch +++ b/patches/server/improve-checking-handled-tags-in-itemmeta.patch @@ -244,7 +244,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + super(tag, extraHandledDcts); // Paper getOrEmpty(tag, CraftMetaArmor.TRIM).ifPresent((trimCompound) -> { - TrimMaterial trimMaterial = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(io.papermc.paper.registry.RegistryKey.TRIM_MATERIAL, trimCompound.material()).orElse(null); // Paper - fix upstream not being correct + TrimMaterial trimMaterial = CraftTrimMaterial.minecraftHolderToBukkit(trimCompound.material()); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java @@ -696,7 +696,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + super(tag, extraHandledDcts); // Paper getOrEmpty(tag, CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT).ifPresent((instrument) -> { - this.instrument = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(org.bukkit.Registry.INSTRUMENT, instrument).orElse(null); // Paper - fix upstream not handling inlined instrument + this.instrument = CraftMusicInstrument.minecraftHolderToBukkit(instrument); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaOminousBottle.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaOminousBottle.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaOminousBottle.java