mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-22 22:45:31 +01:00
5632210f10
* add RegistryAccess for managing registries * add missing types to key data generator * fix some stuff * Add RegistryKeys for all other non-server-backed registries * fix tests * remove Experimental annotations
1026 lines
55 KiB
Diff
1026 lines
55 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
|
Date: Mon, 27 Feb 2023 18:28:39 -0800
|
|
Subject: [PATCH] Add RegistryAccess for managing Registries
|
|
|
|
RegistryAccess is independant from CraftServer and
|
|
doesn't require one to be created allowing the
|
|
org.bukkit.Registry class to be loaded earlier.
|
|
|
|
== AT ==
|
|
public net.minecraft.server.RegistryLayer STATIC_ACCESS
|
|
|
|
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..cc7d4924098eab9663cc52917e4b30d6ef4b02c7
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
|
|
@@ -0,0 +1,101 @@
|
|
+package io.papermc.paper.registry;
|
|
+
|
|
+import io.papermc.paper.registry.entry.RegistryEntry;
|
|
+import java.util.Collections;
|
|
+import java.util.IdentityHashMap;
|
|
+import java.util.List;
|
|
+import java.util.Map;
|
|
+import net.minecraft.core.Registry;
|
|
+import net.minecraft.core.registries.Registries;
|
|
+import net.minecraft.resources.ResourceKey;
|
|
+import net.minecraft.world.item.enchantment.Enchantment;
|
|
+import net.minecraft.world.level.levelgen.structure.Structure;
|
|
+import org.bukkit.GameEvent;
|
|
+import org.bukkit.Keyed;
|
|
+import org.bukkit.MusicInstrument;
|
|
+import org.bukkit.craftbukkit.CraftGameEvent;
|
|
+import org.bukkit.craftbukkit.CraftMusicInstrument;
|
|
+import org.bukkit.craftbukkit.damage.CraftDamageType;
|
|
+import org.bukkit.craftbukkit.enchantments.CraftEnchantment;
|
|
+import org.bukkit.craftbukkit.entity.CraftWolf;
|
|
+import org.bukkit.craftbukkit.generator.structure.CraftStructure;
|
|
+import org.bukkit.craftbukkit.generator.structure.CraftStructureType;
|
|
+import org.bukkit.craftbukkit.inventory.trim.CraftTrimMaterial;
|
|
+import org.bukkit.craftbukkit.inventory.trim.CraftTrimPattern;
|
|
+import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
|
|
+import org.bukkit.damage.DamageType;
|
|
+import org.bukkit.entity.Wolf;
|
|
+import org.bukkit.entity.memory.MemoryKey;
|
|
+import org.bukkit.generator.structure.StructureType;
|
|
+import org.bukkit.inventory.meta.trim.TrimMaterial;
|
|
+import org.bukkit.inventory.meta.trim.TrimPattern;
|
|
+import org.bukkit.potion.PotionEffectType;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+import static io.papermc.paper.registry.entry.RegistryEntry.apiOnly;
|
|
+import static io.papermc.paper.registry.entry.RegistryEntry.entry;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public final class PaperRegistries {
|
|
+
|
|
+ static final List<RegistryEntry<?, ?, ?>> REGISTRY_ENTRIES;
|
|
+ private static final Map<RegistryKey<?>, RegistryEntry<?, ?, ?>> BY_REGISTRY_KEY;
|
|
+ private static final Map<ResourceKey<?>, RegistryEntry<?, ?, ?>> BY_RESOURCE_KEY;
|
|
+ static {
|
|
+ REGISTRY_ENTRIES = List.of(
|
|
+ // built-ins
|
|
+ entry(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, Enchantment.class, CraftEnchantment::new),
|
|
+ entry(Registries.GAME_EVENT, RegistryKey.GAME_EVENT, GameEvent.class, CraftGameEvent::new),
|
|
+ entry(Registries.INSTRUMENT, RegistryKey.INSTRUMENT, MusicInstrument.class, CraftMusicInstrument::new),
|
|
+ entry(Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT, PotionEffectType.class, CraftPotionEffectType::new),
|
|
+ entry(Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE, StructureType.class, CraftStructureType::new),
|
|
+
|
|
+ // data-drivens
|
|
+ entry(Registries.STRUCTURE, RegistryKey.STRUCTURE, Structure.class, CraftStructure::new).delayed(),
|
|
+ entry(Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL, TrimMaterial.class, CraftTrimMaterial::new).delayed(),
|
|
+ entry(Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN, TrimPattern.class, CraftTrimPattern::new).delayed(),
|
|
+ entry(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE, DamageType.class, CraftDamageType::new).delayed(),
|
|
+ entry(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT, Wolf.Variant.class, CraftWolf.CraftVariant::new).delayed(),
|
|
+
|
|
+ // api-only
|
|
+ apiOnly(Registries.BIOME, RegistryKey.BIOME, () -> org.bukkit.Registry.BIOME),
|
|
+ apiOnly(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT, () -> org.bukkit.Registry.ART),
|
|
+ apiOnly(Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE, () -> org.bukkit.Registry.ATTRIBUTE),
|
|
+ apiOnly(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN, () -> org.bukkit.Registry.BANNER_PATTERN),
|
|
+ apiOnly(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT, () -> org.bukkit.Registry.CAT_VARIANT),
|
|
+ apiOnly(Registries.ENTITY_TYPE, RegistryKey.ENTITY_TYPE, () -> org.bukkit.Registry.ENTITY_TYPE),
|
|
+ apiOnly(Registries.PARTICLE_TYPE, RegistryKey.PARTICLE_TYPE, () -> org.bukkit.Registry.PARTICLE_TYPE),
|
|
+ apiOnly(Registries.POTION, RegistryKey.POTION, () -> org.bukkit.Registry.POTION),
|
|
+ apiOnly(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT, () -> org.bukkit.Registry.SOUNDS),
|
|
+ apiOnly(Registries.VILLAGER_PROFESSION, RegistryKey.VILLAGER_PROFESSION, () -> org.bukkit.Registry.VILLAGER_PROFESSION),
|
|
+ apiOnly(Registries.VILLAGER_TYPE, RegistryKey.VILLAGER_TYPE, () -> org.bukkit.Registry.VILLAGER_TYPE),
|
|
+ apiOnly(Registries.MEMORY_MODULE_TYPE, RegistryKey.MEMORY_MODULE_TYPE, () -> (org.bukkit.Registry<MemoryKey<?>>) (org.bukkit.Registry) org.bukkit.Registry.MEMORY_MODULE_TYPE),
|
|
+ apiOnly(Registries.FLUID, RegistryKey.FLUID, () -> org.bukkit.Registry.FLUID),
|
|
+ apiOnly(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT, () -> org.bukkit.Registry.FROG_VARIANT),
|
|
+ apiOnly(Registries.MAP_DECORATION_TYPE, RegistryKey.MAP_DECORATION_TYPE, () -> org.bukkit.Registry.MAP_DECORATION_TYPE)
|
|
+ );
|
|
+ final Map<RegistryKey<?>, RegistryEntry<?, ?, ?>> byRegistryKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size());
|
|
+ final Map<ResourceKey<?>, RegistryEntry<?, ?, ?>> byResourceKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size());
|
|
+ for (final RegistryEntry<?, ?, ?> entry : REGISTRY_ENTRIES) {
|
|
+ byRegistryKey.put(entry.apiKey(), entry);
|
|
+ byResourceKey.put(entry.mcKey(), entry);
|
|
+ }
|
|
+ BY_REGISTRY_KEY = Collections.unmodifiableMap(byRegistryKey);
|
|
+ BY_RESOURCE_KEY = Collections.unmodifiableMap(byResourceKey);
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <M, T extends Keyed, R extends org.bukkit.Registry<T>> @Nullable RegistryEntry<M, T, R> getEntry(final ResourceKey<? extends Registry<M>> resourceKey) {
|
|
+ return (RegistryEntry<M, T, R>) BY_RESOURCE_KEY.get(resourceKey);
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <M, T extends Keyed, R extends org.bukkit.Registry<T>> @Nullable RegistryEntry<M, T, R> getEntry(final RegistryKey<? super T> registryKey) {
|
|
+ return (RegistryEntry<M, T, R>) BY_REGISTRY_KEY.get(registryKey);
|
|
+ }
|
|
+
|
|
+ private PaperRegistries() {
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..9f2bcfe0d9e479466a1e46e503071d1151310e6a
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
|
|
@@ -0,0 +1,124 @@
|
|
+package io.papermc.paper.registry;
|
|
+
|
|
+import io.papermc.paper.registry.entry.ApiRegistryEntry;
|
|
+import io.papermc.paper.registry.entry.RegistryEntry;
|
|
+import io.papermc.paper.registry.legacy.DelayedRegistry;
|
|
+import io.papermc.paper.registry.legacy.DelayedRegistryEntry;
|
|
+import io.papermc.paper.registry.legacy.LegacyRegistryIdentifiers;
|
|
+import java.util.Map;
|
|
+import java.util.NoSuchElementException;
|
|
+import java.util.Set;
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
+import java.util.stream.Collectors;
|
|
+import net.minecraft.resources.ResourceKey;
|
|
+import org.bukkit.Keyed;
|
|
+import org.bukkit.Registry;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+import org.jetbrains.annotations.VisibleForTesting;
|
|
+
|
|
+import static java.util.Objects.requireNonNull;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public class PaperRegistryAccess implements RegistryAccess {
|
|
+
|
|
+ // We store the API registries in a memoized supplier, so they can be created on-demand.
|
|
+ // These suppliers are added to this map right after the instance of nms.Registry is created before it is loaded.
|
|
+ // We want to do registration there, so we have access to the nms.Registry instance in order to wrap it in a CraftRegistry instance.
|
|
+ // The memoized Supplier is needed because we *can't* instantiate any CraftRegistry class until **all** the BuiltInRegistries have been added
|
|
+ // to this map because that would class-load org.bukkit.Registry which would query this map.
|
|
+ private final Map<RegistryKey<?>, RegistryHolder<?>> registries = new ConcurrentHashMap<>(); // is "identity" because RegistryKey overrides equals and hashCode
|
|
+
|
|
+ public static PaperRegistryAccess instance() {
|
|
+ return (PaperRegistryAccess) RegistryAccessHolder.INSTANCE.orElseThrow(() -> new IllegalStateException("No RegistryAccess implementation found"));
|
|
+ }
|
|
+
|
|
+ @VisibleForTesting
|
|
+ public Set<RegistryKey<?>> getLoadedServerBackedRegistries() {
|
|
+ return this.registries.keySet().stream().filter(registryHolder -> !(PaperRegistries.getEntry(registryHolder) instanceof ApiRegistryEntry)).collect(Collectors.toUnmodifiableSet());
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("unchecked")
|
|
+ @Deprecated(forRemoval = true)
|
|
+ @Override
|
|
+ public <T extends Keyed> @Nullable Registry<T> getRegistry(final Class<T> type) {
|
|
+ final RegistryKey<T> registryKey;
|
|
+ final @Nullable RegistryEntry<?, T, ?> entry;
|
|
+ registryKey = requireNonNull(byType(type), () -> type + " is not a valid registry type");
|
|
+ entry = PaperRegistries.getEntry(registryKey);
|
|
+ final @Nullable RegistryHolder<T> registry = (RegistryHolder<T>) this.registries.get(registryKey);
|
|
+ if (registry != null) {
|
|
+ // if the registry exists, return right away. Since this is the "legacy" method, we return DelayedRegistry
|
|
+ // for the non-builtin Registry instances stored as fields in Registry.
|
|
+ return registry.get();
|
|
+ } else if (entry instanceof DelayedRegistryEntry<?, T, ?>) {
|
|
+ // if the registry doesn't exist and the entry is marked as "delayed", we create a registry holder that is empty
|
|
+ // which will later be filled with the actual registry. This is so the fields on org.bukkit.Registry can be populated with
|
|
+ // registries that don't exist at the time org.bukkit.Registry is statically initialized.
|
|
+ final RegistryHolder<T> delayedHolder = new RegistryHolder.Delayed<>();
|
|
+ this.registries.put(registryKey, delayedHolder);
|
|
+ return delayedHolder.get();
|
|
+ } else {
|
|
+ // if the registry doesn't exist yet or doesn't have a delayed entry, just return null
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("unchecked")
|
|
+ @Override
|
|
+ public <T extends Keyed> Registry<T> getRegistry(final RegistryKey<T> key) {
|
|
+ if (PaperRegistries.getEntry(key) == null) {
|
|
+ throw new NoSuchElementException(key + " is not a valid registry key");
|
|
+ }
|
|
+ final @Nullable RegistryHolder<T> registryHolder = (RegistryHolder<T>) this.registries.get(key);
|
|
+ if (registryHolder == null) {
|
|
+ throw new IllegalArgumentException(key + " points to a registry that is not available yet");
|
|
+ }
|
|
+ // since this is the getRegistry method that uses the modern RegistryKey, we unwrap any DelayedRegistry instances
|
|
+ // that might be returned here. I don't think reference equality is required when doing getRegistry(RegistryKey.WOLF_VARIANT) == Registry.WOLF_VARIANT
|
|
+ return possiblyUnwrap(registryHolder.get());
|
|
+ }
|
|
+
|
|
+ private static <T extends Keyed> Registry<T> possiblyUnwrap(final Registry<T> registry) {
|
|
+ if (registry instanceof final DelayedRegistry<T, ?> delayedRegistry) { // if not coming from legacy, unwrap the delayed registry
|
|
+ return delayedRegistry.delegate();
|
|
+ }
|
|
+ return registry;
|
|
+ }
|
|
+
|
|
+ public <M> void registerReloadableRegistry(final ResourceKey<? extends net.minecraft.core.Registry<M>> resourceKey, final net.minecraft.core.Registry<M> registry) {
|
|
+ this.registerRegistry(resourceKey, registry, true);
|
|
+ }
|
|
+
|
|
+ public <M> void registerRegistry(final ResourceKey<? extends net.minecraft.core.Registry<M>> resourceKey, final net.minecraft.core.Registry<M> registry) {
|
|
+ this.registerRegistry(resourceKey, registry, false);
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("unchecked") // this method should be called right after any new MappedRegistry instances are created to later be used by the server.
|
|
+ private <M, B extends Keyed, R extends Registry<B>> void registerRegistry(final ResourceKey<? extends net.minecraft.core.Registry<M>> resourceKey, final net.minecraft.core.Registry<M> registry, final boolean replace) {
|
|
+ final @Nullable RegistryEntry<M, B, R> entry = PaperRegistries.getEntry(resourceKey);
|
|
+ if (entry == null) { // skip registries that don't have API entries
|
|
+ return;
|
|
+ }
|
|
+ final @Nullable RegistryHolder<B> registryHolder = (RegistryHolder<B>) this.registries.get(entry.apiKey());
|
|
+ if (registryHolder == null || replace) {
|
|
+ // if the holder doesn't exist yet, or is marked as "replaceable", put it in the map.
|
|
+ this.registries.put(entry.apiKey(), entry.createRegistryHolder(registry));
|
|
+ } else {
|
|
+ if (registryHolder instanceof RegistryHolder.Delayed<?, ?> && entry instanceof final DelayedRegistryEntry<M, B, R> delayedEntry) {
|
|
+ // if the registry holder is delayed, and the entry is marked as "delayed", then load the holder with the CraftRegistry instance that wraps the actual nms Registry.
|
|
+ ((RegistryHolder.Delayed<B, R>) registryHolder).loadFrom(delayedEntry, registry);
|
|
+ } else {
|
|
+ throw new IllegalArgumentException(resourceKey + " has already been created");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("unchecked")
|
|
+ @Deprecated
|
|
+ @VisibleForTesting
|
|
+ public static <T extends Keyed> @Nullable RegistryKey<T> byType(final Class<T> type) {
|
|
+ return (RegistryKey<T>) LegacyRegistryIdentifiers.CLASS_TO_KEY_MAP.get(type);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/registry/RegistryHolder.java b/src/main/java/io/papermc/paper/registry/RegistryHolder.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..02402ef647c3e78ed56fd6b2687bf7c67448f891
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/RegistryHolder.java
|
|
@@ -0,0 +1,47 @@
|
|
+package io.papermc.paper.registry;
|
|
+
|
|
+import com.google.common.base.Suppliers;
|
|
+import io.papermc.paper.registry.legacy.DelayedRegistry;
|
|
+import io.papermc.paper.registry.legacy.DelayedRegistryEntry;
|
|
+import java.util.function.Supplier;
|
|
+import org.bukkit.Keyed;
|
|
+import org.bukkit.Registry;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public interface RegistryHolder<B extends Keyed> {
|
|
+
|
|
+ Registry<B> get();
|
|
+
|
|
+ final class Memoized<B extends Keyed, R extends Registry<B>> implements RegistryHolder<B> {
|
|
+
|
|
+ private final Supplier<R> memoizedSupplier;
|
|
+
|
|
+ public Memoized(final Supplier<? extends R> supplier) {
|
|
+ this.memoizedSupplier = Suppliers.memoize(supplier::get);
|
|
+ }
|
|
+
|
|
+ public Registry<B> get() {
|
|
+ return this.memoizedSupplier.get();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ final class Delayed<B extends Keyed, R extends Registry<B>> implements RegistryHolder<B> {
|
|
+
|
|
+ private final DelayedRegistry<B, R> delayedRegistry = new DelayedRegistry<>();
|
|
+
|
|
+ @Override
|
|
+ public DelayedRegistry<B, R> get() {
|
|
+ return this.delayedRegistry;
|
|
+ }
|
|
+
|
|
+ <M> void loadFrom(final DelayedRegistryEntry<M, B, R> delayedEntry, final net.minecraft.core.Registry<M> registry) {
|
|
+ final RegistryHolder<B> delegateHolder = delayedEntry.delegate().createRegistryHolder(registry);
|
|
+ if (!(delegateHolder instanceof RegistryHolder.Memoized<B, ?>)) {
|
|
+ throw new IllegalArgumentException(delegateHolder + " must be a memoized holder");
|
|
+ }
|
|
+ this.delayedRegistry.load(((Memoized<B, R>) delegateHolder).memoizedSupplier);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/registry/entry/ApiRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/ApiRegistryEntry.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b2281a21eafd1f22f0ce261787e29af8a8637147
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/entry/ApiRegistryEntry.java
|
|
@@ -0,0 +1,27 @@
|
|
+package io.papermc.paper.registry.entry;
|
|
+
|
|
+import io.papermc.paper.registry.RegistryHolder;
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
+import java.util.function.Supplier;
|
|
+import net.minecraft.core.Registry;
|
|
+import net.minecraft.resources.ResourceKey;
|
|
+import org.bukkit.Keyed;
|
|
+
|
|
+public class ApiRegistryEntry<M, B extends Keyed> extends BaseRegistryEntry<M, B, org.bukkit.Registry<B>> {
|
|
+
|
|
+ private final Supplier<org.bukkit.Registry<B>> registrySupplier;
|
|
+
|
|
+ protected ApiRegistryEntry(
|
|
+ final ResourceKey<? extends Registry<M>> mcKey,
|
|
+ final RegistryKey<B> apiKey,
|
|
+ final Supplier<org.bukkit.Registry<B>> registrySupplier
|
|
+ ) {
|
|
+ super(mcKey, apiKey);
|
|
+ this.registrySupplier = registrySupplier;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public RegistryHolder<B> createRegistryHolder(final Registry<M> nmsRegistry) {
|
|
+ return new RegistryHolder.Memoized<>(this.registrySupplier);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/registry/entry/BaseRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/BaseRegistryEntry.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..1be8a5feccd27779fcd8ebb2c362f17d78d307da
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/entry/BaseRegistryEntry.java
|
|
@@ -0,0 +1,27 @@
|
|
+package io.papermc.paper.registry.entry;
|
|
+
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
+import net.minecraft.core.Registry;
|
|
+import net.minecraft.resources.ResourceKey;
|
|
+import org.bukkit.Keyed;
|
|
+
|
|
+public abstract class BaseRegistryEntry<M, B extends Keyed, R extends org.bukkit.Registry<B>> implements RegistryEntry<M, B, R> { // TODO remove Keyed
|
|
+
|
|
+ private final ResourceKey<? extends Registry<M>> minecraftRegistryKey;
|
|
+ private final RegistryKey<B> apiRegistryKey;
|
|
+
|
|
+ protected BaseRegistryEntry(final ResourceKey<? extends Registry<M>> minecraftRegistryKey, final RegistryKey<B> apiRegistryKey) {
|
|
+ this.minecraftRegistryKey = minecraftRegistryKey;
|
|
+ this.apiRegistryKey = apiRegistryKey;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public final ResourceKey<? extends Registry<M>> mcKey() {
|
|
+ return this.minecraftRegistryKey;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public final RegistryKey<B> apiKey() {
|
|
+ return this.apiRegistryKey;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/registry/entry/CraftRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/CraftRegistryEntry.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..d0023caafdb33d2f76bdd7bf6dfb3204069f52a0
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/entry/CraftRegistryEntry.java
|
|
@@ -0,0 +1,39 @@
|
|
+package io.papermc.paper.registry.entry;
|
|
+
|
|
+import io.papermc.paper.registry.RegistryHolder;
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
+import java.util.function.BiFunction;
|
|
+import net.minecraft.core.Registry;
|
|
+import net.minecraft.resources.ResourceKey;
|
|
+import org.bukkit.Keyed;
|
|
+import org.bukkit.NamespacedKey;
|
|
+import org.bukkit.craftbukkit.CraftRegistry;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public class CraftRegistryEntry<M, B extends Keyed> extends BaseRegistryEntry<M, B, CraftRegistry<B, M>> { // TODO remove Keyed
|
|
+
|
|
+ protected final Class<?> classToPreload;
|
|
+ protected final BiFunction<NamespacedKey, M, B> minecraftToBukkit;
|
|
+
|
|
+ protected CraftRegistryEntry(
|
|
+ final ResourceKey<? extends Registry<M>> mcKey,
|
|
+ final RegistryKey<B> apiKey,
|
|
+ final Class<?> classToPreload,
|
|
+ final BiFunction<NamespacedKey, M, B> minecraftToBukkit
|
|
+ ) {
|
|
+ super(mcKey, apiKey);
|
|
+ this.classToPreload = classToPreload;
|
|
+ this.minecraftToBukkit = minecraftToBukkit;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public RegistryHolder<B> createRegistryHolder(final Registry<M> nmsRegistry) {
|
|
+ return new RegistryHolder.Memoized<>(() -> this.createApiRegistry(nmsRegistry));
|
|
+ }
|
|
+
|
|
+ private CraftRegistry<B, M> createApiRegistry(final Registry<M> nmsRegistry) {
|
|
+ return new CraftRegistry<>(this.classToPreload, nmsRegistry, this.minecraftToBukkit);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..3ca3938267bea86df1077c0ebeb8859a634cd042
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java
|
|
@@ -0,0 +1,47 @@
|
|
+package io.papermc.paper.registry.entry;
|
|
+
|
|
+import io.papermc.paper.registry.RegistryHolder;
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
+import io.papermc.paper.registry.legacy.DelayedRegistryEntry;
|
|
+import java.util.function.BiFunction;
|
|
+import java.util.function.Supplier;
|
|
+import net.minecraft.core.Registry;
|
|
+import net.minecraft.resources.ResourceKey;
|
|
+import org.bukkit.Keyed;
|
|
+import org.bukkit.NamespacedKey;
|
|
+import org.bukkit.craftbukkit.CraftRegistry;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public interface RegistryEntry<M, B extends Keyed, R extends org.bukkit.Registry<B>> extends RegistryEntryInfo<M, B> { // TODO remove Keyed
|
|
+
|
|
+ RegistryHolder<B> createRegistryHolder(Registry<M> nmsRegistry);
|
|
+
|
|
+ /**
|
|
+ * This should only be used if the registry instance needs to exist early due to the need
|
|
+ * to populate a field in {@link org.bukkit.Registry}. Data-driven registries shouldn't exist
|
|
+ * as fields, but instead be obtained via {@link io.papermc.paper.registry.RegistryAccess#getRegistry(RegistryKey)}
|
|
+ */
|
|
+ @Deprecated
|
|
+ default RegistryEntry<M, B, R> delayed() {
|
|
+ return new DelayedRegistryEntry<>(this);
|
|
+ }
|
|
+
|
|
+ static <M, B extends Keyed> RegistryEntry<M, B, CraftRegistry<B, M>> entry(
|
|
+ final ResourceKey<? extends Registry<M>> mcKey,
|
|
+ final RegistryKey<B> apiKey,
|
|
+ final Class<?> classToPreload,
|
|
+ final BiFunction<NamespacedKey, M, B> minecraftToBukkit
|
|
+ ) {
|
|
+ return new CraftRegistryEntry<>(mcKey, apiKey, classToPreload, minecraftToBukkit);
|
|
+ }
|
|
+
|
|
+ static <M, B extends Keyed> RegistryEntry<M, B, org.bukkit.Registry<B>> apiOnly(
|
|
+ final ResourceKey<? extends Registry<M>> mcKey,
|
|
+ final RegistryKey<B> apiKey,
|
|
+ final Supplier<org.bukkit.Registry<B>> apiRegistrySupplier
|
|
+ ) {
|
|
+ return new ApiRegistryEntry<>(mcKey, apiKey, apiRegistrySupplier);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0ae855e80fc9fddfc1feb33c7a9748204828b7cc
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java
|
|
@@ -0,0 +1,12 @@
|
|
+package io.papermc.paper.registry.entry;
|
|
+
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
+import net.minecraft.core.Registry;
|
|
+import net.minecraft.resources.ResourceKey;
|
|
+
|
|
+public interface RegistryEntryInfo<M, B> {
|
|
+
|
|
+ ResourceKey<? extends Registry<M>> mcKey();
|
|
+
|
|
+ RegistryKey<B> apiKey();
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/registry/entry/package-info.java b/src/main/java/io/papermc/paper/registry/entry/package-info.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..e4c94d6860e0f5b643cde1ded20b5503c02a4866
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/entry/package-info.java
|
|
@@ -0,0 +1,5 @@
|
|
+@DefaultQualifier(NonNull.class)
|
|
+package io.papermc.paper.registry.entry;
|
|
+
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
diff --git a/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistry.java b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistry.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..5562e8da5ebaef2a3add46e88d64358b7737b59e
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistry.java
|
|
@@ -0,0 +1,55 @@
|
|
+package io.papermc.paper.registry.legacy;
|
|
+
|
|
+import java.util.Iterator;
|
|
+import java.util.function.Supplier;
|
|
+import java.util.stream.Stream;
|
|
+import org.bukkit.Keyed;
|
|
+import org.bukkit.NamespacedKey;
|
|
+import org.bukkit.Registry;
|
|
+import org.bukkit.craftbukkit.CraftRegistry;
|
|
+import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+
|
|
+/**
|
|
+ * This is to support the now-deprecated fields in {@link Registry} for
|
|
+ * data-driven registries.
|
|
+ */
|
|
+public final class DelayedRegistry<T extends Keyed, R extends Registry<T>> implements Registry<T> {
|
|
+
|
|
+ private @MonotonicNonNull Supplier<? extends R> delegate;
|
|
+
|
|
+ public void load(final Supplier<? extends R> registry) {
|
|
+ if (this.delegate != null) {
|
|
+ throw new IllegalStateException("Registry already loaded!");
|
|
+ }
|
|
+ this.delegate = registry;
|
|
+ }
|
|
+
|
|
+ public Registry<T> delegate() {
|
|
+ if (this.delegate == null) {
|
|
+ throw new IllegalStateException("You are trying to access this registry too early!");
|
|
+ }
|
|
+ return this.delegate.get();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public @Nullable T get(final NamespacedKey key) {
|
|
+ return this.delegate().get(key);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Iterator<T> iterator() {
|
|
+ return this.delegate().iterator();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Stream<T> stream() {
|
|
+ return this.delegate().stream();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public NamespacedKey getKey(final T value) {
|
|
+ return this.delegate().getKey(value);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistryEntry.java b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistryEntry.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..5f615f50ac0cdbc47cf7a39b630b653e0d30cdf5
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistryEntry.java
|
|
@@ -0,0 +1,26 @@
|
|
+package io.papermc.paper.registry.legacy;
|
|
+
|
|
+import io.papermc.paper.registry.RegistryHolder;
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
+import io.papermc.paper.registry.entry.RegistryEntry;
|
|
+import net.minecraft.core.Registry;
|
|
+import net.minecraft.resources.ResourceKey;
|
|
+import org.bukkit.Keyed;
|
|
+
|
|
+public record DelayedRegistryEntry<M, T extends Keyed, R extends org.bukkit.Registry<T>>(RegistryEntry<M, T, R> delegate) implements RegistryEntry<M, T, R> {
|
|
+
|
|
+ @Override
|
|
+ public ResourceKey<? extends Registry<M>> mcKey() {
|
|
+ return this.delegate.mcKey();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public RegistryKey<T> apiKey() {
|
|
+ return this.delegate.apiKey();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public RegistryHolder<T> createRegistryHolder(final Registry<M> nmsRegistry) {
|
|
+ return this.delegate.createRegistryHolder(nmsRegistry);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/registry/legacy/LegacyRegistryIdentifiers.java b/src/main/java/io/papermc/paper/registry/legacy/LegacyRegistryIdentifiers.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..83870816cd4c54f94a3c603ffe41c11e457f3dec
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/legacy/LegacyRegistryIdentifiers.java
|
|
@@ -0,0 +1,33 @@
|
|
+package io.papermc.paper.registry.legacy;
|
|
+
|
|
+import com.google.common.collect.ImmutableMap;
|
|
+import io.leangen.geantyref.GenericTypeReflector;
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
+import java.lang.reflect.Field;
|
|
+import java.lang.reflect.ParameterizedType;
|
|
+import java.util.Map;
|
|
+
|
|
+@Deprecated
|
|
+public final class LegacyRegistryIdentifiers {
|
|
+
|
|
+ public static final Map<Class<?>, RegistryKey<?>> CLASS_TO_KEY_MAP;
|
|
+
|
|
+ static {
|
|
+ final ImmutableMap.Builder<Class<?>, RegistryKey<?>> builder = ImmutableMap.builder();
|
|
+ try {
|
|
+ for (final Field field : RegistryKey.class.getFields()) {
|
|
+ if (field.getType() == RegistryKey.class) {
|
|
+ // get the legacy type from the RegistryKey generic parameter on the field
|
|
+ final Class<?> legacyType = GenericTypeReflector.erase(((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]);
|
|
+ builder.put(legacyType, (RegistryKey<?>) field.get(null));
|
|
+ }
|
|
+ }
|
|
+ } catch (final ReflectiveOperationException ex) {
|
|
+ throw new RuntimeException(ex);
|
|
+ }
|
|
+ CLASS_TO_KEY_MAP = builder.build();
|
|
+ }
|
|
+
|
|
+ private LegacyRegistryIdentifiers() {
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/registry/legacy/package-info.java b/src/main/java/io/papermc/paper/registry/legacy/package-info.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..4396982af55872fafbfeaf8161ad6f392726c773
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/registry/legacy/package-info.java
|
|
@@ -0,0 +1,5 @@
|
|
+@DefaultQualifier(NonNull.class)
|
|
+package io.papermc.paper.registry.legacy;
|
|
+
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
diff --git a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
|
|
index b43af53960978ac04bccde08544a562841492791..8daee5a7935e3253834c4cbe81d5e8886f776dad 100644
|
|
--- a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
|
|
+++ b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
|
|
@@ -297,6 +297,7 @@ public class BuiltInRegistries {
|
|
ResourceKey<? extends Registry<T>> key, R registry, BuiltInRegistries.RegistryBootstrap<T> initializer
|
|
) {
|
|
Bootstrap.checkBootstrapCalled(() -> "registry " + key);
|
|
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerRegistry(registry.key(), registry); // Paper - initialize API registry
|
|
ResourceLocation resourceLocation = key.location();
|
|
LOADERS.put(resourceLocation, () -> initializer.run(registry));
|
|
WRITABLE_REGISTRY.register((ResourceKey)key, registry, RegistrationInfo.BUILT_IN); // Paper - decompile fix
|
|
diff --git a/src/main/java/net/minecraft/resources/RegistryDataLoader.java b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
|
index 1a40a600b8a9716ef26f3143f361a47b76ec2510..d59356df2d98de873fc5accc749f87fa3d685267 100644
|
|
--- a/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
|
+++ b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
|
@@ -284,6 +284,7 @@ public class RegistryDataLoader {
|
|
public static record RegistryData<T>(ResourceKey<? extends Registry<T>> key, Codec<T> elementCodec) {
|
|
RegistryDataLoader.Loader<T> create(Lifecycle lifecycle, Map<ResourceKey<?>, Exception> errors) {
|
|
WritableRegistry<T> writableRegistry = new MappedRegistry<>(this.key, lifecycle);
|
|
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerRegistry(this.key, writableRegistry); // Paper - initialize API registry
|
|
return new RegistryDataLoader.Loader<>(this, writableRegistry, errors);
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
|
|
index cf08819dd7ef6db807053a52aaf66a7fdea18ab6..69682d7be64a2163d574de939f5146f5a7a642ef 100644
|
|
--- a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
|
|
+++ b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
|
|
@@ -60,6 +60,7 @@ public class ReloadableServerRegistries {
|
|
return CompletableFuture.supplyAsync(
|
|
() -> {
|
|
WritableRegistry<T> writableRegistry = new MappedRegistry<>(type.registryKey(), Lifecycle.experimental());
|
|
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerReloadableRegistry(type.registryKey(), writableRegistry); // Paper - register reloadable registry
|
|
Map<ResourceLocation, JsonElement> map = new HashMap<>();
|
|
SimpleJsonResourceReloadListener.scanDirectory(resourceManager, type.directory(), GSON, map);
|
|
map.forEach(
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
|
|
index 4209a45af2bfe772f678b07b49070522de4195a8..e2fcbeb8635280fcd2aeedff9803386c9bcabb0c 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
|
|
@@ -100,55 +100,15 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
|
|
+ ", this can happen if a plugin creates its own registry entry with out properly registering it.");
|
|
}
|
|
|
|
- /**
|
|
- * Note: Newly added registries should also be added to RegistriesArgumentProvider in the test package
|
|
- *
|
|
- * @param bukkitClass the bukkit class of the registry
|
|
- * @param registryHolder the minecraft registry holder
|
|
- * @return the bukkit registry of the provided class
|
|
- */
|
|
- public static <B extends Keyed> Registry<?> createRegistry(Class<B> bukkitClass, RegistryAccess registryHolder) {
|
|
- if (bukkitClass == Enchantment.class) {
|
|
- return new CraftRegistry<>(Enchantment.class, registryHolder.registryOrThrow(Registries.ENCHANTMENT), CraftEnchantment::new);
|
|
- }
|
|
- if (bukkitClass == GameEvent.class) {
|
|
- return new CraftRegistry<>(GameEvent.class, registryHolder.registryOrThrow(Registries.GAME_EVENT), CraftGameEvent::new);
|
|
- }
|
|
- if (bukkitClass == MusicInstrument.class) {
|
|
- return new CraftRegistry<>(MusicInstrument.class, registryHolder.registryOrThrow(Registries.INSTRUMENT), CraftMusicInstrument::new);
|
|
- }
|
|
- if (bukkitClass == PotionEffectType.class) {
|
|
- return new CraftRegistry<>(PotionEffectType.class, registryHolder.registryOrThrow(Registries.MOB_EFFECT), CraftPotionEffectType::new);
|
|
- }
|
|
- if (bukkitClass == Structure.class) {
|
|
- return new CraftRegistry<>(Structure.class, registryHolder.registryOrThrow(Registries.STRUCTURE), CraftStructure::new);
|
|
- }
|
|
- if (bukkitClass == StructureType.class) {
|
|
- return new CraftRegistry<>(StructureType.class, BuiltInRegistries.STRUCTURE_TYPE, CraftStructureType::new);
|
|
- }
|
|
- if (bukkitClass == TrimMaterial.class) {
|
|
- return new CraftRegistry<>(TrimMaterial.class, registryHolder.registryOrThrow(Registries.TRIM_MATERIAL), CraftTrimMaterial::new);
|
|
- }
|
|
- if (bukkitClass == TrimPattern.class) {
|
|
- return new CraftRegistry<>(TrimPattern.class, registryHolder.registryOrThrow(Registries.TRIM_PATTERN), CraftTrimPattern::new);
|
|
- }
|
|
- if (bukkitClass == DamageType.class) {
|
|
- return new CraftRegistry<>(DamageType.class, registryHolder.registryOrThrow(Registries.DAMAGE_TYPE), CraftDamageType::new);
|
|
- }
|
|
- if (bukkitClass == Wolf.Variant.class) {
|
|
- return new CraftRegistry<>(Wolf.Variant.class, registryHolder.registryOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new);
|
|
- }
|
|
-
|
|
- return null;
|
|
- }
|
|
+ // Paper - move to PaperRegistries
|
|
|
|
- private final Class<? super B> bukkitClass;
|
|
+ private final Class<?> bukkitClass; // Paper - relax preload class
|
|
private final Map<NamespacedKey, B> cache = new HashMap<>();
|
|
private final net.minecraft.core.Registry<M> minecraftRegistry;
|
|
private final BiFunction<NamespacedKey, M, B> minecraftToBukkit;
|
|
private boolean init;
|
|
|
|
- public CraftRegistry(Class<? super B> bukkitClass, net.minecraft.core.Registry<M> minecraftRegistry, BiFunction<NamespacedKey, M, B> minecraftToBukkit) {
|
|
+ public CraftRegistry(Class<?> bukkitClass, net.minecraft.core.Registry<M> minecraftRegistry, BiFunction<NamespacedKey, M, B> minecraftToBukkit) { // Paper - relax preload class
|
|
this.bukkitClass = bukkitClass;
|
|
this.minecraftRegistry = minecraftRegistry;
|
|
this.minecraftToBukkit = minecraftToBukkit;
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
index 1460060f2ff42ebaa7b2418b375ce661c73bd17f..2c89ba2b518618640064ebea22d3d9595407bad7 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
@@ -283,7 +283,7 @@ public final class CraftServer implements Server {
|
|
protected final DedicatedServer console;
|
|
protected final DedicatedPlayerList playerList;
|
|
private final Map<String, World> worlds = new LinkedHashMap<String, World>();
|
|
- private final Map<Class<?>, Registry<?>> registries = new HashMap<>();
|
|
+ // private final Map<Class<?>, Registry<?>> registries = new HashMap<>(); // Paper - replace with RegistryAccess
|
|
private YamlConfiguration configuration;
|
|
private YamlConfiguration commandsConfiguration;
|
|
private final Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
|
|
@@ -2693,7 +2693,7 @@ public final class CraftServer implements Server {
|
|
|
|
@Override
|
|
public <T extends Keyed> Registry<T> getRegistry(Class<T> aClass) {
|
|
- return (Registry<T>) this.registries.computeIfAbsent(aClass, key -> CraftRegistry.createRegistry(aClass, this.console.registryAccess()));
|
|
+ return io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(aClass); // Paper - replace with RegistryAccess
|
|
}
|
|
|
|
@Deprecated
|
|
diff --git a/src/main/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess b/src/main/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..8a083d45004f82fc9c51c219fb20f34624adb501
|
|
--- /dev/null
|
|
+++ b/src/main/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess
|
|
@@ -0,0 +1 @@
|
|
+io.papermc.paper.registry.PaperRegistryAccess
|
|
diff --git a/src/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java b/src/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b9d00e65639521eecd44bd2be3e012264c3785f5
|
|
--- /dev/null
|
|
+++ b/src/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java
|
|
@@ -0,0 +1,20 @@
|
|
+package io.papermc.paper.registry;
|
|
+
|
|
+import org.bukkit.GameEvent;
|
|
+import org.bukkit.MusicInstrument;
|
|
+import org.bukkit.inventory.meta.trim.TrimPattern;
|
|
+import org.bukkit.support.AbstractTestingBase;
|
|
+import org.junit.jupiter.api.Test;
|
|
+
|
|
+import static org.junit.jupiter.api.Assertions.assertSame;
|
|
+
|
|
+@Deprecated
|
|
+class LegacyRegistryIdentifierTest extends AbstractTestingBase {
|
|
+
|
|
+ @Test
|
|
+ void testSeveralConversions() {
|
|
+ assertSame(RegistryKey.GAME_EVENT, PaperRegistryAccess.byType(GameEvent.class));
|
|
+ assertSame(RegistryKey.TRIM_PATTERN, PaperRegistryAccess.byType(TrimPattern.class));
|
|
+ assertSame(RegistryKey.INSTRUMENT, PaperRegistryAccess.byType(MusicInstrument.class));
|
|
+ }
|
|
+}
|
|
diff --git a/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java b/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java
|
|
index e070aa1bb69859224493d958621389ee757f8752..311837ac7cea6b75eedee01bf893317a8763cdf9 100644
|
|
--- a/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java
|
|
+++ b/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java
|
|
@@ -1,15 +1,18 @@
|
|
package io.papermc.paper.registry;
|
|
|
|
+import io.papermc.paper.registry.entry.RegistryEntry;
|
|
import java.util.Optional;
|
|
import java.util.stream.Stream;
|
|
import net.minecraft.core.Registry;
|
|
import net.minecraft.resources.ResourceKey;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
+import org.bukkit.Keyed;
|
|
import org.bukkit.support.AbstractTestingBase;
|
|
import org.junit.jupiter.api.BeforeAll;
|
|
import org.junit.jupiter.params.ParameterizedTest;
|
|
import org.junit.jupiter.params.provider.MethodSource;
|
|
|
|
+import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
|
class RegistryKeyTest extends AbstractTestingBase {
|
|
@@ -28,6 +31,12 @@ class RegistryKeyTest extends AbstractTestingBase {
|
|
void testApiRegistryKeysExist(final RegistryKey<?> key) {
|
|
final Optional<Registry<Object>> registry = AbstractTestingBase.REGISTRY_CUSTOM.registry(ResourceKey.createRegistryKey(new ResourceLocation(key.key().asString())));
|
|
assertTrue(registry.isPresent(), "Missing vanilla registry for " + key.key().asString());
|
|
+ }
|
|
|
|
+ @ParameterizedTest
|
|
+ @MethodSource("data")
|
|
+ void testRegistryEntryExists(final RegistryKey<?> key) {
|
|
+ final RegistryEntry<?, ?, ?> entry = PaperRegistries.getEntry(key);
|
|
+ assertNotNull(entry, "Missing PaperRegistries entry for " + key);
|
|
}
|
|
}
|
|
diff --git a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
|
|
index 4adaafafb7140e983a4e90f0ff0deaaf0887a9a5..0dd775ad1bd0bf9ba7ea05255d543a9df8b5fcfd 100644
|
|
--- a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
|
|
+++ b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
|
|
@@ -21,14 +21,17 @@ public class RegistryArgumentAddedTest extends AbstractTestingBase {
|
|
// Make sure every registry is created
|
|
Class.forName(Registry.class.getName());
|
|
|
|
- Set<Class<?>> loadedRegistries = new HashSet<>(DummyServer.registers.keySet());
|
|
- Set<Class<?>> notFound = new HashSet<>();
|
|
+ // Paper start
|
|
+ Set<io.papermc.paper.registry.RegistryKey<?>> loadedRegistries = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>());
|
|
+ loadedRegistries.addAll(io.papermc.paper.registry.PaperRegistryAccess.instance().getLoadedServerBackedRegistries());
|
|
+ // Paper end
|
|
+ Set<io.papermc.paper.registry.RegistryKey<?>> notFound = new HashSet<>(); // Paper
|
|
|
|
RegistriesArgumentProvider
|
|
.getData()
|
|
.map(Arguments::get)
|
|
.map(array -> array[0])
|
|
- .map(clazz -> (Class<?>) clazz)
|
|
+ .map(clazz -> (io.papermc.paper.registry.RegistryKey<?>) clazz) // Paper
|
|
.forEach(clazz -> {
|
|
if (!loadedRegistries.remove(clazz)) {
|
|
notFound.add(clazz);
|
|
diff --git a/src/test/java/org/bukkit/registry/RegistryConversionTest.java b/src/test/java/org/bukkit/registry/RegistryConversionTest.java
|
|
index 8c6b7f9804cf56269cc5a1b5924db2d2bf556f88..782c2ce424fc124e18145615187dc1e9d33f80ae 100644
|
|
--- a/src/test/java/org/bukkit/registry/RegistryConversionTest.java
|
|
+++ b/src/test/java/org/bukkit/registry/RegistryConversionTest.java
|
|
@@ -37,9 +37,9 @@ public class RegistryConversionTest extends AbstractTestingBase {
|
|
|
|
@Order(1)
|
|
@RegistriesTest
|
|
- public void testHandleableImplementation(Class<? extends Keyed> clazz) {
|
|
+ public void testHandleableImplementation(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz) { // Paper
|
|
Set<Class<? extends Keyed>> notImplemented = new HashSet<>();
|
|
- Registry<? extends Keyed> registry = Bukkit.getRegistry(clazz);
|
|
+ Registry<? extends Keyed> registry = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(type); // Paper
|
|
|
|
for (Keyed item : registry) {
|
|
if (!(item instanceof Handleable<?>)) {
|
|
@@ -59,7 +59,7 @@ public class RegistryConversionTest extends AbstractTestingBase {
|
|
|
|
@Order(2)
|
|
@RegistriesTest
|
|
- public void testMinecraftToBukkitPresent(Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey,
|
|
+ public void testMinecraftToBukkitPresent(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey, // Paper
|
|
Class<? extends Keyed> craftClazz, Class<?> minecraftClazz) {
|
|
Method method = null;
|
|
try {
|
|
@@ -107,7 +107,7 @@ public class RegistryConversionTest extends AbstractTestingBase {
|
|
|
|
@Order(2)
|
|
@RegistriesTest
|
|
- public void testBukkitToMinecraftPresent(Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey,
|
|
+ public void testBukkitToMinecraftPresent(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey, // Paper
|
|
Class<? extends Keyed> craftClazz, Class<?> minecraftClazz) {
|
|
Method method = null;
|
|
try {
|
|
@@ -153,9 +153,9 @@ public class RegistryConversionTest extends AbstractTestingBase {
|
|
""", minecraftClazz.getName(), clazz.getSimpleName());
|
|
}
|
|
|
|
- @Order(2)
|
|
+ @Order(3)
|
|
@RegistriesTest
|
|
- public void testMinecraftToBukkitNullValue(Class<? extends Keyed> clazz) throws IllegalAccessException {
|
|
+ public void testMinecraftToBukkitNullValue(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz) throws IllegalAccessException { // Paper
|
|
this.checkValidMinecraftToBukkit(clazz);
|
|
|
|
try {
|
|
@@ -174,7 +174,7 @@ public class RegistryConversionTest extends AbstractTestingBase {
|
|
|
|
@Order(3)
|
|
@RegistriesTest
|
|
- public void testBukkitToMinecraftNullValue(Class<? extends Keyed> clazz) throws IllegalAccessException {
|
|
+ public void testBukkitToMinecraftNullValue(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz) throws IllegalAccessException { // Paper
|
|
this.checkValidBukkitToMinecraft(clazz);
|
|
|
|
try {
|
|
@@ -193,14 +193,14 @@ public class RegistryConversionTest extends AbstractTestingBase {
|
|
|
|
@Order(3)
|
|
@RegistriesTest
|
|
- public void testMinecraftToBukkit(Class<? extends Keyed> clazz) {
|
|
+ public void testMinecraftToBukkit(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz) { // Paper
|
|
this.checkValidMinecraftToBukkit(clazz);
|
|
this.checkValidHandle(clazz);
|
|
|
|
Map<Object, Object> notMatching = new HashMap<>();
|
|
Method method = RegistryConversionTest.MINECRAFT_TO_BUKKIT_METHODS.get(clazz);
|
|
|
|
- RegistryArgumentProvider.getValues(clazz).map(Arguments::get).forEach(arguments -> {
|
|
+ RegistryArgumentProvider.getValues(type).map(Arguments::get).forEach(arguments -> { // Paper
|
|
Keyed bukkit = (Keyed) arguments[0];
|
|
Object minecraft = arguments[1];
|
|
|
|
@@ -224,14 +224,14 @@ public class RegistryConversionTest extends AbstractTestingBase {
|
|
|
|
@Order(3)
|
|
@RegistriesTest
|
|
- public void testBukkitToMinecraft(Class<? extends Keyed> clazz) {
|
|
+ public void testBukkitToMinecraft(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz) { // Paper
|
|
this.checkValidBukkitToMinecraft(clazz);
|
|
this.checkValidHandle(clazz);
|
|
|
|
Map<Object, Object> notMatching = new HashMap<>();
|
|
Method method = RegistryConversionTest.BUKKIT_TO_MINECRAFT_METHODS.get(clazz);
|
|
|
|
- RegistryArgumentProvider.getValues(clazz).map(Arguments::get).forEach(arguments -> {
|
|
+ RegistryArgumentProvider.getValues(type).map(Arguments::get).forEach(arguments -> { // Paper
|
|
Keyed bukkit = (Keyed) arguments[0];
|
|
Object minecraft = arguments[1];
|
|
|
|
@@ -259,7 +259,7 @@ public class RegistryConversionTest extends AbstractTestingBase {
|
|
*/
|
|
@Order(3)
|
|
@RegistriesTest
|
|
- public void testMinecraftToBukkitNoValidMinecraft(Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey,
|
|
+ public void testMinecraftToBukkitNoValidMinecraft(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey, // Paper
|
|
Class<? extends Keyed> craftClazz, Class<?> minecraftClazz) throws IllegalAccessException {
|
|
this.checkValidMinecraftToBukkit(clazz);
|
|
|
|
diff --git a/src/test/java/org/bukkit/support/DummyServer.java b/src/test/java/org/bukkit/support/DummyServer.java
|
|
index 7a4681155f740a98ecafa0b992eae1fb5524551f..bd56792fc674c4e3606a3179ebf5a84ef0a4e35c 100644
|
|
--- a/src/test/java/org/bukkit/support/DummyServer.java
|
|
+++ b/src/test/java/org/bukkit/support/DummyServer.java
|
|
@@ -45,10 +45,7 @@ public final class DummyServer {
|
|
when(instance.getLootTable(any())).then(mock -> new CraftLootTable(mock.getArgument(0),
|
|
AbstractTestingBase.DATA_PACK.fullRegistries().getLootTable(ResourceKey.create(Registries.LOOT_TABLE, CraftNamespacedKey.toMinecraft(mock.getArgument(0))))));
|
|
|
|
- when(instance.getRegistry(any())).then((Answer<Registry<?>>) mock -> {
|
|
- Class<? extends Keyed> aClass = mock.getArgument(0);
|
|
- return registers.computeIfAbsent(aClass, key -> CraftRegistry.createRegistry(aClass, AbstractTestingBase.REGISTRY_CUSTOM));
|
|
- });
|
|
+ // Paper - RegistryAccess
|
|
|
|
// Paper start - testing additions
|
|
final Thread currentThread = Thread.currentThread();
|
|
diff --git a/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java b/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java
|
|
index 342ea2914b361f39708bf0d8a39385c62d340c30..69a6a8419947a0617405e8931193f88d0dc5c3c4 100644
|
|
--- a/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java
|
|
+++ b/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java
|
|
@@ -1,6 +1,7 @@
|
|
package org.bukkit.support.provider;
|
|
|
|
import com.google.common.collect.Lists;
|
|
+import io.papermc.paper.registry.RegistryKey;
|
|
import java.util.List;
|
|
import java.util.stream.Stream;
|
|
import net.minecraft.core.registries.Registries;
|
|
@@ -37,16 +38,17 @@ public class RegistriesArgumentProvider implements ArgumentsProvider {
|
|
|
|
static {
|
|
// Order: Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class
|
|
- DATA.add(Arguments.of(Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class));
|
|
- DATA.add(Arguments.of(GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class));
|
|
- DATA.add(Arguments.of(MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class));
|
|
- DATA.add(Arguments.of(PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class));
|
|
- DATA.add(Arguments.of(Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class));
|
|
- DATA.add(Arguments.of(StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class));
|
|
- DATA.add(Arguments.of(TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.armortrim.TrimMaterial.class));
|
|
- DATA.add(Arguments.of(TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.armortrim.TrimPattern.class));
|
|
- DATA.add(Arguments.of(DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class));
|
|
- DATA.add(Arguments.of(Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, WolfVariant.class));
|
|
+ // Order: RegistryKey, Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class
|
|
+ DATA.add(Arguments.of(RegistryKey.ENCHANTMENT, Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class));
|
|
+ DATA.add(Arguments.of(RegistryKey.GAME_EVENT, GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class));
|
|
+ DATA.add(Arguments.of(RegistryKey.INSTRUMENT, MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class));
|
|
+ DATA.add(Arguments.of(RegistryKey.MOB_EFFECT, PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class));
|
|
+ DATA.add(Arguments.of(RegistryKey.STRUCTURE, Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class));
|
|
+ DATA.add(Arguments.of(RegistryKey.STRUCTURE_TYPE, StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class));
|
|
+ DATA.add(Arguments.of(RegistryKey.TRIM_MATERIAL, TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.armortrim.TrimMaterial.class));
|
|
+ DATA.add(Arguments.of(RegistryKey.TRIM_PATTERN, TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.armortrim.TrimPattern.class));
|
|
+ DATA.add(Arguments.of(RegistryKey.DAMAGE_TYPE, DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class));
|
|
+ DATA.add(Arguments.of(RegistryKey.WOLF_VARIANT, Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, net.minecraft.world.entity.animal.WolfVariant.class));
|
|
}
|
|
|
|
@Override
|
|
diff --git a/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java b/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java
|
|
index f2ceb5e67536dfa5de792dc64a7898fd2e8aa810..beb5fc9e721f5de54064c3d241df9ca9f4cd4f65 100644
|
|
--- a/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java
|
|
+++ b/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java
|
|
@@ -22,11 +22,11 @@ public class RegistryArgumentProvider implements ArgumentsProvider, AnnotationCo
|
|
|
|
@Override
|
|
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) throws Exception {
|
|
- return RegistryArgumentProvider.getValues(this.registryType);
|
|
+ return RegistryArgumentProvider.getValues(io.papermc.paper.registry.PaperRegistryAccess.byType(this.registryType)); // Paper
|
|
}
|
|
|
|
- public static Stream<? extends Arguments> getValues(Class<? extends Keyed> registryType) {
|
|
- Registry<?> registry = Bukkit.getRegistry(registryType);
|
|
+ public static Stream<? extends Arguments> getValues(io.papermc.paper.registry.RegistryKey<? extends Keyed> registryType) { // Paper
|
|
+ Registry<?> registry = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(registryType); // Paper
|
|
return registry.stream().map(keyed -> (Handleable<?>) keyed)
|
|
.map(handleAble -> Arguments.of(handleAble, handleAble.getHandle()));
|
|
}
|