geforkt von Mirrors/Paper
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
Dieser Commit ist enthalten in:
Ursprung
23b8639dbf
Commit
239e7a6b37
@ -1,7 +1,10 @@
|
|||||||
--- a/net/minecraft/core/registries/BuiltInRegistries.java
|
--- a/net/minecraft/core/registries/BuiltInRegistries.java
|
||||||
+++ b/net/minecraft/core/registries/BuiltInRegistries.java
|
+++ b/net/minecraft/core/registries/BuiltInRegistries.java
|
||||||
@@ -325,12 +325,18 @@
|
@@ -323,14 +323,21 @@
|
||||||
|
ResourceKey<? extends Registry<T>> key, R registry, BuiltInRegistries.RegistryBootstrap<T> initializer
|
||||||
|
) {
|
||||||
Bootstrap.checkBootstrapCalled(() -> "registry " + key.location());
|
Bootstrap.checkBootstrapCalled(() -> "registry " + key.location());
|
||||||
|
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerRegistry(registry.key(), registry); // Paper - initialize API registry
|
||||||
ResourceLocation resourceLocation = key.location();
|
ResourceLocation resourceLocation = key.location();
|
||||||
LOADERS.put(resourceLocation, () -> initializer.run(registry));
|
LOADERS.put(resourceLocation, () -> initializer.run(registry));
|
||||||
- WRITABLE_REGISTRY.register((ResourceKey<WritableRegistry<?>>)key, registry, RegistrationInfo.BUILT_IN);
|
- WRITABLE_REGISTRY.register((ResourceKey<WritableRegistry<?>>)key, registry, RegistrationInfo.BUILT_IN);
|
||||||
|
@ -9,3 +9,11 @@
|
|||||||
private static final RegistrationInfo NETWORK_REGISTRATION_INFO = new RegistrationInfo(Optional.empty(), Lifecycle.experimental());
|
private static final RegistrationInfo NETWORK_REGISTRATION_INFO = new RegistrationInfo(Optional.empty(), Lifecycle.experimental());
|
||||||
private static final Function<Optional<KnownPack>, RegistrationInfo> REGISTRATION_INFO_CACHE = Util.memoize(knownPacks -> {
|
private static final Function<Optional<KnownPack>, RegistrationInfo> REGISTRATION_INFO_CACHE = Util.memoize(knownPacks -> {
|
||||||
Lifecycle lifecycle = knownPacks.map(KnownPack::isVanilla).map(vanilla -> Lifecycle.stable()).orElse(Lifecycle.experimental());
|
Lifecycle lifecycle = knownPacks.map(KnownPack::isVanilla).map(vanilla -> Lifecycle.stable()).orElse(Lifecycle.experimental());
|
||||||
|
@@ -349,6 +349,7 @@
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
--- a/net/minecraft/server/ReloadableServerRegistries.java
|
||||||
|
+++ b/net/minecraft/server/ReloadableServerRegistries.java
|
||||||
|
@@ -64,6 +64,7 @@
|
||||||
|
) {
|
||||||
|
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, T> 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));
|
@ -0,0 +1,153 @@
|
|||||||
|
package io.papermc.paper.registry;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import io.papermc.paper.adventure.PaperAdventure;
|
||||||
|
import io.papermc.paper.registry.entry.RegistryEntry;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import org.bukkit.Art;
|
||||||
|
import org.bukkit.Fluid;
|
||||||
|
import org.bukkit.GameEvent;
|
||||||
|
import org.bukkit.JukeboxSong;
|
||||||
|
import org.bukkit.Keyed;
|
||||||
|
import org.bukkit.MusicInstrument;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.attribute.Attribute;
|
||||||
|
import org.bukkit.block.Biome;
|
||||||
|
import org.bukkit.block.BlockType;
|
||||||
|
import org.bukkit.block.banner.PatternType;
|
||||||
|
import org.bukkit.craftbukkit.CraftArt;
|
||||||
|
import org.bukkit.craftbukkit.CraftFluid;
|
||||||
|
import org.bukkit.craftbukkit.CraftGameEvent;
|
||||||
|
import org.bukkit.craftbukkit.CraftJukeboxSong;
|
||||||
|
import org.bukkit.craftbukkit.CraftMusicInstrument;
|
||||||
|
import org.bukkit.craftbukkit.CraftSound;
|
||||||
|
import org.bukkit.craftbukkit.attribute.CraftAttribute;
|
||||||
|
import org.bukkit.craftbukkit.block.CraftBiome;
|
||||||
|
import org.bukkit.craftbukkit.block.CraftBlockType;
|
||||||
|
import org.bukkit.craftbukkit.block.banner.CraftPatternType;
|
||||||
|
import org.bukkit.craftbukkit.damage.CraftDamageType;
|
||||||
|
import org.bukkit.craftbukkit.enchantments.CraftEnchantment;
|
||||||
|
import org.bukkit.craftbukkit.entity.CraftCat;
|
||||||
|
import org.bukkit.craftbukkit.entity.CraftFrog;
|
||||||
|
import org.bukkit.craftbukkit.entity.CraftVillager;
|
||||||
|
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.CraftItemType;
|
||||||
|
import org.bukkit.craftbukkit.inventory.CraftMenuType;
|
||||||
|
import org.bukkit.craftbukkit.inventory.trim.CraftTrimMaterial;
|
||||||
|
import org.bukkit.craftbukkit.inventory.trim.CraftTrimPattern;
|
||||||
|
import org.bukkit.craftbukkit.legacy.FieldRename;
|
||||||
|
import org.bukkit.craftbukkit.map.CraftMapCursor;
|
||||||
|
import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
|
||||||
|
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||||
|
import org.bukkit.damage.DamageType;
|
||||||
|
import org.bukkit.enchantments.Enchantment;
|
||||||
|
import org.bukkit.entity.Cat;
|
||||||
|
import org.bukkit.entity.Frog;
|
||||||
|
import org.bukkit.entity.Villager;
|
||||||
|
import org.bukkit.entity.Wolf;
|
||||||
|
import org.bukkit.entity.memory.MemoryKey;
|
||||||
|
import org.bukkit.generator.structure.Structure;
|
||||||
|
import org.bukkit.generator.structure.StructureType;
|
||||||
|
import org.bukkit.inventory.ItemType;
|
||||||
|
import org.bukkit.inventory.MenuType;
|
||||||
|
import org.bukkit.inventory.meta.trim.TrimMaterial;
|
||||||
|
import org.bukkit.inventory.meta.trim.TrimPattern;
|
||||||
|
import org.bukkit.map.MapCursor;
|
||||||
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import static io.papermc.paper.registry.entry.RegistryEntryBuilder.start;
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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<MemoryKey<?>>) (org.bukkit.Registry) org.bukkit.Registry.MEMORY_MODULE_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) {
|
||||||
|
Preconditions.checkState(byRegistryKey.put(entry.apiKey(), entry) == null, "Duplicate api registry key: %s", entry.apiKey());
|
||||||
|
Preconditions.checkState(byResourceKey.put(entry.mcKey(), entry) == null, "Duplicate mc registry key: %s", entry.mcKey());
|
||||||
|
}
|
||||||
|
BY_REGISTRY_KEY = Collections.unmodifiableMap(byRegistryKey);
|
||||||
|
BY_RESOURCE_KEY = Collections.unmodifiableMap(byResourceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <M, T extends Keyed> @Nullable RegistryEntry<M, T> getEntry(final ResourceKey<? extends Registry<M>> resourceKey) {
|
||||||
|
return (RegistryEntry<M, T>) BY_RESOURCE_KEY.get(resourceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <M, T extends Keyed> @Nullable RegistryEntry<M, T> getEntry(final RegistryKey<? super T> registryKey) {
|
||||||
|
return (RegistryEntry<M, T>) BY_REGISTRY_KEY.get(registryKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <M, T> RegistryKey<T> registryFromNms(final ResourceKey<? extends Registry<M>> registryResourceKey) {
|
||||||
|
return (RegistryKey<T>) Objects.requireNonNull(BY_RESOURCE_KEY.get(registryResourceKey), registryResourceKey + " doesn't have an api RegistryKey").apiKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <M, T> ResourceKey<? extends Registry<M>> registryToNms(final RegistryKey<T> registryKey) {
|
||||||
|
return (ResourceKey<? extends Registry<M>>) Objects.requireNonNull(BY_REGISTRY_KEY.get(registryKey), registryKey + " doesn't have an mc registry ResourceKey").mcKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <M, T> TypedKey<T> fromNms(final ResourceKey<M> resourceKey) {
|
||||||
|
return TypedKey.create(registryFromNms(resourceKey.registryKey()), CraftNamespacedKey.fromMinecraft(resourceKey.location()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked", "RedundantCast"})
|
||||||
|
public static <M, T> ResourceKey<M> toNms(final TypedKey<T> typedKey) {
|
||||||
|
return ResourceKey.create((ResourceKey<? extends Registry<M>>) PaperRegistries.registryToNms(typedKey.registryKey()), PaperAdventure.asVanilla(typedKey.key()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private PaperRegistries() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,122 @@
|
|||||||
|
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.jetbrains.annotations.VisibleForTesting;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
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 = byType(type);
|
||||||
|
// If our mapping from Class -> RegistryKey did not contain the passed type it was either a completely invalid type or a registry
|
||||||
|
// that merely exists as a SimpleRegistry in the org.bukkit.Registry type. We cannot return a registry for these, return null
|
||||||
|
// as per method contract in Bukkit#getRegistry.
|
||||||
|
if (registryKey == null) return null;
|
||||||
|
|
||||||
|
final RegistryEntry<?, T> entry = PaperRegistries.getEntry(registryKey);
|
||||||
|
final 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> 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> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package io.papermc.paper.registry;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
|
import org.bukkit.Keyed;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.Registry;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.potion.PotionType;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
|
||||||
|
@NullMarked
|
||||||
|
public class PaperSimpleRegistry<T extends Enum<T> & Keyed, M> extends Registry.SimpleRegistry<T> {
|
||||||
|
|
||||||
|
static Registry<EntityType> entityType() {
|
||||||
|
return new PaperSimpleRegistry<>(EntityType.class, entity -> entity != EntityType.UNKNOWN, BuiltInRegistries.ENTITY_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Registry<Particle> particleType() {
|
||||||
|
return new PaperSimpleRegistry<>(Particle.class, BuiltInRegistries.PARTICLE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Registry<PotionType> potion() {
|
||||||
|
return new PaperSimpleRegistry<>(PotionType.class, BuiltInRegistries.POTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final net.minecraft.core.Registry<M> nmsRegistry;
|
||||||
|
|
||||||
|
protected PaperSimpleRegistry(final Class<T> type, final net.minecraft.core.Registry<M> nmsRegistry) {
|
||||||
|
super(type);
|
||||||
|
this.nmsRegistry = nmsRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaperSimpleRegistry(final Class<T> type, final Predicate<T> predicate, final net.minecraft.core.Registry<M> nmsRegistry) {
|
||||||
|
super(type, predicate);
|
||||||
|
this.nmsRegistry = nmsRegistry;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
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> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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> {
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -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> implements RegistryEntry<M, B> { // 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
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;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.craftbukkit.CraftRegistry;
|
||||||
|
import org.bukkit.craftbukkit.util.ApiVersion;
|
||||||
|
|
||||||
|
public class CraftRegistryEntry<M, B extends Keyed> extends BaseRegistryEntry<M, B> { // TODO remove Keyed
|
||||||
|
|
||||||
|
private static final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> EMPTY = (namespacedKey, apiVersion) -> namespacedKey;
|
||||||
|
|
||||||
|
protected final Class<?> classToPreload;
|
||||||
|
protected final RegistryTypeMapper<M, B> minecraftToBukkit;
|
||||||
|
protected BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater = EMPTY;
|
||||||
|
|
||||||
|
protected CraftRegistryEntry(
|
||||||
|
final ResourceKey<? extends Registry<M>> mcKey,
|
||||||
|
final RegistryKey<B> apiKey,
|
||||||
|
final Class<?> classToPreload,
|
||||||
|
final RegistryTypeMapper<M, B> 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");
|
||||||
|
this.classToPreload = classToPreload;
|
||||||
|
this.minecraftToBukkit = minecraftToBukkit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RegistryEntry<M, B> withSerializationUpdater(final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater) {
|
||||||
|
this.updater = updater;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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, this.updater);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
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 net.minecraft.core.Registry;
|
||||||
|
import org.bukkit.Keyed;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.craftbukkit.util.ApiVersion;
|
||||||
|
|
||||||
|
public interface RegistryEntry<M, B extends Keyed> extends RegistryEntryInfo<M, B> { // TODO remove Keyed
|
||||||
|
|
||||||
|
RegistryHolder<B> createRegistryHolder(Registry<M> nmsRegistry);
|
||||||
|
|
||||||
|
default RegistryEntry<M, B> withSerializationUpdater(final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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> delayed() {
|
||||||
|
return new DelayedRegistryEntry<>(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package io.papermc.paper.registry.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<M, A extends Keyed> { // TODO remove Keyed
|
||||||
|
|
||||||
|
public static <M, A extends Keyed> RegistryEntryBuilder<M, A> start( // TODO remove Keyed
|
||||||
|
final ResourceKey<? extends Registry<M>> mcKey,
|
||||||
|
final RegistryKey<A> apiKey
|
||||||
|
) {
|
||||||
|
return new RegistryEntryBuilder<>(mcKey, apiKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final ResourceKey<? extends Registry<M>> mcKey;
|
||||||
|
protected final RegistryKey<A> apiKey;
|
||||||
|
|
||||||
|
private RegistryEntryBuilder(final ResourceKey<? extends Registry<M>> mcKey, RegistryKey<A> apiKey) {
|
||||||
|
this.mcKey = mcKey;
|
||||||
|
this.apiKey = apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegistryEntry<M, A> apiOnly(final Supplier<org.bukkit.Registry<A>> apiRegistrySupplier) {
|
||||||
|
return new ApiRegistryEntry<>(this.mcKey, this.apiKey, apiRegistrySupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CraftStage<M, A> craft(final Class<?> classToPreload, final BiFunction<? super NamespacedKey, M, ? extends A> minecraftToBukkit) {
|
||||||
|
return new CraftStage<>(this.mcKey, this.apiKey, classToPreload, new RegistryTypeMapper<>(minecraftToBukkit));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CraftStage<M, A> craft(final Class<?> classToPreload, final Function<Holder<M>, ? extends A> minecraftToBukkit) {
|
||||||
|
return new CraftStage<>(this.mcKey, this.apiKey, classToPreload, new RegistryTypeMapper<>(minecraftToBukkit));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class CraftStage<M, A extends Keyed> extends RegistryEntryBuilder<M, A> { // TODO remove Keyed
|
||||||
|
|
||||||
|
private final Class<?> classToPreload;
|
||||||
|
private final RegistryTypeMapper<M, A> minecraftToBukkit;
|
||||||
|
|
||||||
|
private CraftStage(
|
||||||
|
final ResourceKey<? extends Registry<M>> mcKey,
|
||||||
|
final RegistryKey<A> apiKey,
|
||||||
|
final Class<?> classToPreload,
|
||||||
|
final RegistryTypeMapper<M, A> minecraftToBukkit
|
||||||
|
) {
|
||||||
|
super(mcKey, apiKey);
|
||||||
|
this.classToPreload = classToPreload;
|
||||||
|
this.minecraftToBukkit = minecraftToBukkit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegistryEntry<M, A> build() {
|
||||||
|
return new CraftRegistryEntry<>(this.mcKey, this.apiKey, this.classToPreload, this.minecraftToBukkit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
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<M, A> {
|
||||||
|
|
||||||
|
final Either<BiFunction<? super NamespacedKey, M, ? extends A>, Function<Holder<M>, ? extends A>> minecraftToBukkit;
|
||||||
|
|
||||||
|
public RegistryTypeMapper(final BiFunction<? super NamespacedKey, M, ? extends A> byValueCreator) {
|
||||||
|
this.minecraftToBukkit = Either.left(byValueCreator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegistryTypeMapper(final Function<Holder<M>, ? extends A> byHolderCreator) {
|
||||||
|
this.minecraftToBukkit = Either.right(byHolderCreator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public A createBukkit(final NamespacedKey key, final Holder<M> 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<M> directHolder) {
|
||||||
|
Preconditions.checkArgument(this.supportsDirectHolders() && directHolder.kind() == Holder.Kind.DIRECT);
|
||||||
|
return this.minecraftToBukkit.right().orElseThrow().apply(directHolder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package io.papermc.paper.registry.entry;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
@ -0,0 +1,57 @@
|
|||||||
|
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.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 @Nullable 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 T getOrThrow(final NamespacedKey key) {
|
||||||
|
return this.delegate().getOrThrow(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return this.delegate().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<T> stream() {
|
||||||
|
return this.delegate().stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable NamespacedKey getKey(final T value) {
|
||||||
|
return this.delegate().getKey(value);
|
||||||
|
}
|
||||||
|
}
|
@ -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>(RegistryEntry<M, T> delegate) implements RegistryEntry<M, T> {
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
@ -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() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package io.papermc.paper.registry.legacy;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
@ -0,0 +1,4 @@
|
|||||||
|
@NullMarked
|
||||||
|
package io.papermc.paper.registry;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
14
paper-server/src/main/java/io/papermc/paper/util/Holderable.java
Normale Datei
14
paper-server/src/main/java/io/papermc/paper/util/Holderable.java
Normale Datei
@ -0,0 +1,14 @@
|
|||||||
|
package io.papermc.paper.util;
|
||||||
|
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import org.bukkit.craftbukkit.util.Handleable;
|
||||||
|
|
||||||
|
public interface Holderable<M> extends Handleable<M> {
|
||||||
|
|
||||||
|
Holder<M> getHolder();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default M getHandle() {
|
||||||
|
return this.getHolder().value();
|
||||||
|
}
|
||||||
|
}
|
@ -216,11 +216,10 @@ public abstract class CraftParticle<D> implements Keyed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CraftParticleRegistry(net.minecraft.core.Registry<net.minecraft.core.particles.ParticleType<?>> minecraftRegistry) {
|
public CraftParticleRegistry(net.minecraft.core.Registry<net.minecraft.core.particles.ParticleType<?>> 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 static CraftParticle<?> createBukkit(NamespacedKey namespacedKey, net.minecraft.core.particles.ParticleType<?> particle) { // Paper - idk why this is a separate implementation, just wrap the function
|
||||||
public CraftParticle<?> createBukkit(NamespacedKey namespacedKey, net.minecraft.core.particles.ParticleType<?> particle) {
|
|
||||||
if (particle == null) {
|
if (particle == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -93,14 +93,41 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
|
|||||||
Preconditions.checkArgument(minecraft != null);
|
Preconditions.checkArgument(minecraft != null);
|
||||||
|
|
||||||
net.minecraft.core.Registry<M> registry = CraftRegistry.getMinecraftRegistry(registryKey);
|
net.minecraft.core.Registry<M> registry = CraftRegistry.getMinecraftRegistry(registryKey);
|
||||||
B bukkit = bukkitRegistry.get(CraftNamespacedKey.fromMinecraft(registry.getResourceKey(minecraft)
|
// Paper start - support direct Holders
|
||||||
.orElseThrow(() -> new IllegalStateException(String.format("Cannot convert '%s' to bukkit representation, since it is not registered.", minecraft))).location()));
|
final java.util.Optional<ResourceKey<M>> resourceKey = registry.getResourceKey(minecraft);
|
||||||
|
if (resourceKey.isEmpty() && bukkitRegistry instanceof final CraftRegistry<?, ?> craftRegistry && craftRegistry.supportsDirectHolders()) {
|
||||||
|
return ((CraftRegistry<B, M>) 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);
|
Preconditions.checkArgument(bukkit != null);
|
||||||
|
|
||||||
return bukkit;
|
return bukkit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Paper start - support direct Holders
|
||||||
|
public static <B extends Keyed, M> B minecraftHolderToBukkit(final Holder<M> minecraft, final Registry<B> bukkitRegistry) {
|
||||||
|
Preconditions.checkArgument(minecraft != null);
|
||||||
|
|
||||||
|
final B bukkit = switch (minecraft) {
|
||||||
|
case final Holder.Direct<M> direct -> {
|
||||||
|
if (!(bukkitRegistry instanceof final CraftRegistry<?, ?> craftRegistry) || !craftRegistry.supportsDirectHolders()) {
|
||||||
|
throw new IllegalArgumentException("Cannot convert direct holder to bukkit representation");
|
||||||
|
}
|
||||||
|
yield ((CraftRegistry<B, M>) bukkitRegistry).convertDirectHolder(direct);
|
||||||
|
}
|
||||||
|
case final Holder.Reference<M> 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.
|
* Usage note: Only use this method to delegate the conversion methods from the individual Craft classes to here.
|
||||||
* Do not use it in other parts of CraftBukkit, use the methods in the respective Craft classes instead.
|
* Do not use it in other parts of CraftBukkit, use the methods in the respective Craft classes instead.
|
||||||
@ -116,6 +143,11 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
|
|||||||
|
|
||||||
public static <B extends Keyed, M> Holder<M> bukkitToMinecraftHolder(B bukkit, ResourceKey<net.minecraft.core.Registry<M>> registryKey) {
|
public static <B extends Keyed, M> Holder<M> bukkitToMinecraftHolder(B bukkit, ResourceKey<net.minecraft.core.Registry<M>> registryKey) {
|
||||||
Preconditions.checkArgument(bukkit != null);
|
Preconditions.checkArgument(bukkit != null);
|
||||||
|
// Paper start - support direct Holder
|
||||||
|
if (bukkit instanceof io.papermc.paper.util.Holderable<?>) {
|
||||||
|
return ((io.papermc.paper.util.Holderable<M>) bukkit).getHolder();
|
||||||
|
}
|
||||||
|
// Paper end - support direct Holder
|
||||||
|
|
||||||
net.minecraft.core.Registry<M> registry = CraftRegistry.getMinecraftRegistry(registryKey);
|
net.minecraft.core.Registry<M> registry = CraftRegistry.getMinecraftRegistry(registryKey);
|
||||||
|
|
||||||
@ -127,96 +159,12 @@ 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.");
|
+ ", this can happen if a plugin creates its own registry entry with out properly registering it.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Paper - move to PaperRegistries
|
||||||
* 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<? super B> bukkitClass, RegistryAccess registryHolder) {
|
|
||||||
if (bukkitClass == Art.class) {
|
|
||||||
return new CraftRegistry<>(Art.class, registryHolder.lookupOrThrow(Registries.PAINTING_VARIANT), CraftArt::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == Attribute.class) {
|
|
||||||
return new CraftRegistry<>(Attribute.class, registryHolder.lookupOrThrow(Registries.ATTRIBUTE), CraftAttribute::new, FieldRename.ATTRIBUTE_RENAME);
|
|
||||||
}
|
|
||||||
if (bukkitClass == Biome.class) {
|
|
||||||
return new CraftRegistry<>(Biome.class, registryHolder.lookupOrThrow(Registries.BIOME), CraftBiome::new, FieldRename.BIOME_RENAME);
|
|
||||||
}
|
|
||||||
if (bukkitClass == Enchantment.class) {
|
|
||||||
return new CraftRegistry<>(Enchantment.class, registryHolder.lookupOrThrow(Registries.ENCHANTMENT), CraftEnchantment::new, FieldRename.ENCHANTMENT_RENAME);
|
|
||||||
}
|
|
||||||
if (bukkitClass == Fluid.class) {
|
|
||||||
return new CraftRegistry<>(Fluid.class, registryHolder.lookupOrThrow(Registries.FLUID), CraftFluid::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == GameEvent.class) {
|
|
||||||
return new CraftRegistry<>(GameEvent.class, registryHolder.lookupOrThrow(Registries.GAME_EVENT), CraftGameEvent::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == MusicInstrument.class) {
|
|
||||||
return new CraftRegistry<>(MusicInstrument.class, registryHolder.lookupOrThrow(Registries.INSTRUMENT), CraftMusicInstrument::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == MenuType.class) {
|
|
||||||
return new CraftRegistry<>(MenuType.class, registryHolder.lookupOrThrow(Registries.MENU), CraftMenuType::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == PotionEffectType.class) {
|
|
||||||
return new CraftRegistry<>(PotionEffectType.class, registryHolder.lookupOrThrow(Registries.MOB_EFFECT), CraftPotionEffectType::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == Sound.class) {
|
|
||||||
return new CraftRegistry<>(Sound.class, registryHolder.lookupOrThrow(Registries.SOUND_EVENT), CraftSound::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == Structure.class) {
|
|
||||||
return new CraftRegistry<>(Structure.class, registryHolder.lookupOrThrow(Registries.STRUCTURE), CraftStructure::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == StructureType.class) {
|
|
||||||
return new CraftRegistry<>(StructureType.class, registryHolder.lookupOrThrow(Registries.STRUCTURE_TYPE), CraftStructureType::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == Villager.Type.class) {
|
|
||||||
return new CraftRegistry<>(Villager.Type.class, registryHolder.lookupOrThrow(Registries.VILLAGER_TYPE), CraftVillager.CraftType::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == Villager.Profession.class) {
|
|
||||||
return new CraftRegistry<>(Villager.Profession.class, registryHolder.lookupOrThrow(Registries.VILLAGER_PROFESSION), CraftVillager.CraftProfession::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == TrimMaterial.class) {
|
|
||||||
return new CraftRegistry<>(TrimMaterial.class, registryHolder.lookupOrThrow(Registries.TRIM_MATERIAL), CraftTrimMaterial::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == TrimPattern.class) {
|
|
||||||
return new CraftRegistry<>(TrimPattern.class, registryHolder.lookupOrThrow(Registries.TRIM_PATTERN), CraftTrimPattern::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == DamageType.class) {
|
|
||||||
return new CraftRegistry<>(DamageType.class, registryHolder.lookupOrThrow(Registries.DAMAGE_TYPE), CraftDamageType::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == JukeboxSong.class) {
|
|
||||||
return new CraftRegistry<>(JukeboxSong.class, registryHolder.lookupOrThrow(Registries.JUKEBOX_SONG), CraftJukeboxSong::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == Wolf.Variant.class) {
|
|
||||||
return new CraftRegistry<>(Wolf.Variant.class, registryHolder.lookupOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == BlockType.class) {
|
|
||||||
return new CraftRegistry<>(BlockType.class, registryHolder.lookupOrThrow(Registries.BLOCK), CraftBlockType::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == ItemType.class) {
|
|
||||||
return new CraftRegistry<>(ItemType.class, registryHolder.lookupOrThrow(Registries.ITEM), CraftItemType::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == Frog.Variant.class) {
|
|
||||||
return new CraftRegistry<>(Frog.Variant.class, registryHolder.lookupOrThrow(Registries.FROG_VARIANT), CraftFrog.CraftVariant::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == Cat.Type.class) {
|
|
||||||
return new CraftRegistry<>(Cat.Type.class, registryHolder.lookupOrThrow(Registries.CAT_VARIANT), CraftCat.CraftType::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == MapCursor.Type.class) {
|
|
||||||
return new CraftRegistry<>(MapCursor.Type.class, registryHolder.lookupOrThrow(Registries.MAP_DECORATION_TYPE), CraftMapCursor.CraftType::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
if (bukkitClass == PatternType.class) {
|
|
||||||
return new CraftRegistry<>(PatternType.class, registryHolder.lookupOrThrow(Registries.BANNER_PATTERN), CraftPatternType::new, FieldRename.NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Paper - NOTE: As long as all uses of the method below relate to *serialization* via ConfigurationSerializable, it's fine
|
||||||
public static <B extends Keyed> B get(Registry<B> bukkit, NamespacedKey namespacedKey, ApiVersion apiVersion) {
|
public static <B extends Keyed> B get(Registry<B> bukkit, NamespacedKey namespacedKey, ApiVersion apiVersion) {
|
||||||
if (bukkit instanceof CraftRegistry<B, ?> craft) {
|
if (bukkit instanceof CraftRegistry<B, ?> craft) {
|
||||||
return craft.get(namespacedKey, apiVersion);
|
return craft.get(craft.serializationUpdater.apply(namespacedKey, apiVersion)); // Paper
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bukkit instanceof Registry.SimpleRegistry<?> simple) {
|
if (bukkit instanceof Registry.SimpleRegistry<?> simple) {
|
||||||
@ -234,23 +182,26 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
|
|||||||
return bukkit.get(namespacedKey);
|
return bukkit.get(namespacedKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Class<? super B> bukkitClass;
|
private final Class<?> bukkitClass; // Paper - relax preload class
|
||||||
private final Map<NamespacedKey, B> cache = new HashMap<>();
|
private final Map<NamespacedKey, B> cache = new HashMap<>();
|
||||||
private final net.minecraft.core.Registry<M> minecraftRegistry;
|
private final net.minecraft.core.Registry<M> minecraftRegistry;
|
||||||
private final BiFunction<NamespacedKey, M, B> minecraftToBukkit;
|
private final io.papermc.paper.registry.entry.RegistryTypeMapper<M, B> minecraftToBukkit; // Paper - switch to Holder
|
||||||
private final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater;
|
private final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> serializationUpdater; // Paper - rename to make it *clear* what it is *only* for
|
||||||
private boolean init;
|
private boolean init;
|
||||||
|
|
||||||
public CraftRegistry(Class<? super B> bukkitClass, net.minecraft.core.Registry<M> minecraftRegistry, BiFunction<NamespacedKey, M, B> minecraftToBukkit, BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater) {
|
public CraftRegistry(Class<?> bukkitClass, net.minecraft.core.Registry<M> minecraftRegistry, BiFunction<? super NamespacedKey, M, B> minecraftToBukkit, BiFunction<NamespacedKey, ApiVersion, NamespacedKey> 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<M> minecraftRegistry, io.papermc.paper.registry.entry.RegistryTypeMapper<M, B> minecraftToBukkit, BiFunction<NamespacedKey, ApiVersion, NamespacedKey> serializationUpdater) { // Paper - relax preload class
|
||||||
|
// Paper end - support Holders
|
||||||
this.bukkitClass = bukkitClass;
|
this.bukkitClass = bukkitClass;
|
||||||
this.minecraftRegistry = minecraftRegistry;
|
this.minecraftRegistry = minecraftRegistry;
|
||||||
this.minecraftToBukkit = minecraftToBukkit;
|
this.minecraftToBukkit = minecraftToBukkit;
|
||||||
this.updater = updater;
|
this.serializationUpdater = serializationUpdater;
|
||||||
}
|
}
|
||||||
|
|
||||||
public B get(NamespacedKey namespacedKey, ApiVersion apiVersion) {
|
// Paper - inline into CraftRegistry#get(Registry, NamespacedKey, ApiVersion) above
|
||||||
return this.get(this.updater.apply(namespacedKey, apiVersion));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public B get(NamespacedKey namespacedKey) {
|
public B get(NamespacedKey namespacedKey) {
|
||||||
@ -280,7 +231,7 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
|
|||||||
return this.get(namespacedKey);
|
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) {
|
if (bukkit == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -311,11 +262,21 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
|
|||||||
return this.stream().iterator();
|
return this.stream().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public B createBukkit(NamespacedKey namespacedKey, M minecraft) {
|
public B createBukkit(NamespacedKey namespacedKey, Holder<M> minecraft) { // Paper - switch to Holder
|
||||||
if (minecraft == null) {
|
if (minecraft == null) {
|
||||||
return 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<M> holder) {
|
||||||
|
return this.minecraftToBukkit.convertDirectHolder(holder);
|
||||||
|
}
|
||||||
|
// Paper end - support Direct Holders
|
||||||
}
|
}
|
||||||
|
@ -284,7 +284,7 @@ public final class CraftServer implements Server {
|
|||||||
protected final DedicatedServer console;
|
protected final DedicatedServer console;
|
||||||
protected final DedicatedPlayerList playerList;
|
protected final DedicatedPlayerList playerList;
|
||||||
private final Map<String, World> worlds = new LinkedHashMap<String, World>();
|
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 configuration;
|
||||||
private YamlConfiguration commandsConfiguration;
|
private YamlConfiguration commandsConfiguration;
|
||||||
private final Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
|
private final Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
|
||||||
@ -431,6 +431,7 @@ public final class CraftServer implements Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadCompatibilities() {
|
private void loadCompatibilities() {
|
||||||
|
if (true) return; // Paper - Big nope
|
||||||
ConfigurationSection compatibilities = this.configuration.getConfigurationSection("settings.compatibility");
|
ConfigurationSection compatibilities = this.configuration.getConfigurationSection("settings.compatibility");
|
||||||
if (compatibilities == null) {
|
if (compatibilities == null) {
|
||||||
this.activeCompatibilities = Collections.emptySet();
|
this.activeCompatibilities = Collections.emptySet();
|
||||||
@ -2754,7 +2755,7 @@ public final class CraftServer implements Server {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Keyed> Registry<T> getRegistry(Class<T> aClass) {
|
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
|
@Deprecated
|
||||||
|
@ -51,11 +51,14 @@ public class FieldRename {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequireCompatibility("allow-old-keys-in-registry")
|
// Paper start - absolutely not, having this as an expectation for plugin developers opens a huge
|
||||||
public static <T extends Keyed> T get(Registry<T> registry, NamespacedKey namespacedKey) {
|
// can of worms in the future, especially if mojang comes back and reuses some old key
|
||||||
// We don't have version-specific changes, so just use current, and don't inject a version
|
//@RequireCompatibility("allow-old-keys-in-registry")
|
||||||
return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT);
|
//public static <T extends Keyed> T get(Registry<T> registry, NamespacedKey namespacedKey) {
|
||||||
}
|
// // We don't have version-specific changes, so just use current, and don't inject a version
|
||||||
|
// return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT);
|
||||||
|
//}
|
||||||
|
// Paper end
|
||||||
|
|
||||||
// PatternType
|
// PatternType
|
||||||
private static final FieldRenameData PATTERN_TYPE_DATA = FieldRenameData.Builder.newBuilder()
|
private static final FieldRenameData PATTERN_TYPE_DATA = FieldRenameData.Builder.newBuilder()
|
||||||
|
@ -220,20 +220,10 @@ public class Commodore {
|
|||||||
|
|
||||||
public byte[] convert(byte[] b, final String pluginName, final ApiVersion pluginVersion, final Set<String> activeCompatibilities) {
|
public byte[] convert(byte[] b, final String pluginName, final ApiVersion pluginVersion, final Set<String> activeCompatibilities) {
|
||||||
final boolean modern = pluginVersion.isNewerThanOrSameAs(ApiVersion.FLATTENING);
|
final boolean modern = pluginVersion.isNewerThanOrSameAs(ApiVersion.FLATTENING);
|
||||||
final boolean enumCompatibility = pluginVersion.isOlderThanOrSameAs(ApiVersion.getOrCreateVersion("1.20.6")) && activeCompatibilities.contains("enum-compatibility-mode");
|
|
||||||
ClassReader cr = new ClassReader(b);
|
ClassReader cr = new ClassReader(b);
|
||||||
ClassWriter cw = new ClassWriter(cr, 0);
|
ClassWriter cw = new ClassWriter(cr, 0);
|
||||||
|
|
||||||
List<String> methodEnumSignatures = Commodore.getMethodSignatures(b);
|
|
||||||
Multimap<String, String> enumLessToEnum = HashMultimap.create();
|
|
||||||
for (String method : methodEnumSignatures) {
|
|
||||||
enumLessToEnum.put(method.replace("Ljava/lang/Enum;", "Ljava/lang/Object;"), method);
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassVisitor visitor = cw;
|
ClassVisitor visitor = cw;
|
||||||
if (enumCompatibility) {
|
|
||||||
visitor = new LimitedClassRemapper(cw, new SimpleRemapper(Commodore.ENUM_RENAMES));
|
|
||||||
}
|
|
||||||
|
|
||||||
visitor = io.papermc.paper.pluginremap.reflect.ReflectionRemapper.visitor(visitor); // Paper
|
visitor = io.papermc.paper.pluginremap.reflect.ReflectionRemapper.visitor(visitor); // Paper
|
||||||
cr.accept(new ClassRemapper(new ClassVisitor(Opcodes.ASM9, visitor) {
|
cr.accept(new ClassRemapper(new ClassVisitor(Opcodes.ASM9, visitor) {
|
||||||
@ -300,15 +290,6 @@ public class Commodore {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||||
if (enumCompatibility && (access & Opcodes.ACC_SYNTHETIC) != 0 && (access & Opcodes.ACC_BRIDGE) != 0 && desc.contains("Ljava/lang/Object;")) {
|
|
||||||
// SPIGOT-7820: Do not use object method if enum method is present
|
|
||||||
// The object method does only redirect to the enum method
|
|
||||||
Collection<String> result = enumLessToEnum.get(desc.replace("Ljava/lang/Enum;", "Ljava/lang/Object;") + " " + name);
|
|
||||||
if (result.size() == 2) {
|
|
||||||
name = name + "_BUKKIT_UNUSED";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new MethodVisitor(this.api, super.visitMethod(access, name, desc, signature, exceptions)) {
|
return new MethodVisitor(this.api, super.visitMethod(access, name, desc, signature, exceptions)) {
|
||||||
// Paper start - Plugin rewrites
|
// Paper start - Plugin rewrites
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
io.papermc.paper.registry.PaperRegistryAccess
|
@ -23,9 +23,6 @@ settings:
|
|||||||
shutdown-message: Server closed
|
shutdown-message: Server closed
|
||||||
minimum-api: none
|
minimum-api: none
|
||||||
use-map-color-cache: true
|
use-map-color-cache: true
|
||||||
compatibility:
|
|
||||||
allow-old-keys-in-registry: false
|
|
||||||
enum-compatibility-mode: false
|
|
||||||
spawn-limits:
|
spawn-limits:
|
||||||
monsters: 70
|
monsters: 70
|
||||||
animals: 10
|
animals: 10
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package io.papermc.paper.registry;
|
||||||
|
|
||||||
|
import org.bukkit.GameEvent;
|
||||||
|
import org.bukkit.MusicInstrument;
|
||||||
|
import org.bukkit.inventory.meta.trim.TrimPattern;
|
||||||
|
import org.bukkit.support.environment.VanillaFeature;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
@VanillaFeature
|
||||||
|
class LegacyRegistryIdentifierTest {
|
||||||
|
|
||||||
|
@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));
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,19 @@
|
|||||||
package io.papermc.paper.registry;
|
package io.papermc.paper.registry;
|
||||||
|
|
||||||
|
import io.papermc.paper.registry.entry.RegistryEntry;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import org.bukkit.support.AbstractTestingBase;
|
import org.bukkit.support.RegistryHelper;
|
||||||
|
import org.bukkit.support.environment.AllFeatures;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
@AllFeatures
|
@AllFeatures
|
||||||
@ -29,6 +33,12 @@ class RegistryKeyTest {
|
|||||||
void testApiRegistryKeysExist(final RegistryKey<?> key) {
|
void testApiRegistryKeysExist(final RegistryKey<?> key) {
|
||||||
final Optional<Registry<Object>> registry = RegistryHelper.getRegistry().lookup(ResourceKey.createRegistryKey(ResourceLocation.parse(key.key().asString())));
|
final Optional<Registry<Object>> registry = RegistryHelper.getRegistry().lookup(ResourceKey.createRegistryKey(ResourceLocation.parse(key.key().asString())));
|
||||||
assertTrue(registry.isPresent(), "Missing vanilla registry for " + key.key().asString());
|
assertTrue(registry.isPresent(), "Missing vanilla registry for " + key.key().asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("data")
|
||||||
|
void testRegistryEntryExists(final RegistryKey<?> key) {
|
||||||
|
final @Nullable RegistryEntry<?, ?> entry = PaperRegistries.getEntry(key);
|
||||||
|
assertNotNull(entry, "Missing PaperRegistries entry for " + key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,14 +22,17 @@ public class RegistryArgumentAddedTest {
|
|||||||
// Make sure every registry is created
|
// Make sure every registry is created
|
||||||
Class.forName(Registry.class.getName());
|
Class.forName(Registry.class.getName());
|
||||||
|
|
||||||
Set<Class<?>> loadedRegistries = new HashSet<>(AllFeaturesExtension.getRealRegistries().keySet());
|
// Paper start
|
||||||
Set<Class<?>> notFound = new HashSet<>();
|
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
|
RegistriesArgumentProvider
|
||||||
.getData()
|
.getData()
|
||||||
.map(Arguments::get)
|
.map(Arguments::get)
|
||||||
.map(array -> array[0])
|
.map(array -> array[0])
|
||||||
.map(clazz -> (Class<?>) clazz)
|
.map(clazz -> (io.papermc.paper.registry.RegistryKey<?>) clazz) // Paper
|
||||||
.forEach(clazz -> {
|
.forEach(clazz -> {
|
||||||
if (!loadedRegistries.remove(clazz)) {
|
if (!loadedRegistries.remove(clazz)) {
|
||||||
notFound.add(clazz);
|
notFound.add(clazz);
|
||||||
|
@ -41,9 +41,9 @@ public class RegistryConversionTest {
|
|||||||
|
|
||||||
@Order(1)
|
@Order(1)
|
||||||
@RegistriesTest
|
@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<>();
|
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) {
|
for (Keyed item : registry) {
|
||||||
if (!(item instanceof Handleable<?>)) {
|
if (!(item instanceof Handleable<?>)) {
|
||||||
@ -63,7 +63,7 @@ public class RegistryConversionTest {
|
|||||||
|
|
||||||
@Order(2)
|
@Order(2)
|
||||||
@RegistriesTest
|
@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,
|
||||||
Class<? extends Keyed> craftClazz, Class<?> minecraftClazz, boolean newMethod) {
|
Class<? extends Keyed> craftClazz, Class<?> minecraftClazz, boolean newMethod) {
|
||||||
String methodName = (newMethod) ? RegistryConversionTest.MINECRAFT_TO_BUKKIT_NEW : RegistryConversionTest.MINECRAFT_TO_BUKKIT;
|
String methodName = (newMethod) ? RegistryConversionTest.MINECRAFT_TO_BUKKIT_NEW : RegistryConversionTest.MINECRAFT_TO_BUKKIT;
|
||||||
Method method = null;
|
Method method = null;
|
||||||
@ -112,7 +112,7 @@ public class RegistryConversionTest {
|
|||||||
|
|
||||||
@Order(2)
|
@Order(2)
|
||||||
@RegistriesTest
|
@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,
|
||||||
Class<? extends Keyed> craftClazz, Class<?> minecraftClazz, boolean newMethod) {
|
Class<? extends Keyed> craftClazz, Class<?> minecraftClazz, boolean newMethod) {
|
||||||
String methodName = (newMethod) ? RegistryConversionTest.BUKKIT_TO_MINECRAFT_NEW : RegistryConversionTest.BUKKIT_TO_MINECRAFT;
|
String methodName = (newMethod) ? RegistryConversionTest.BUKKIT_TO_MINECRAFT_NEW : RegistryConversionTest.BUKKIT_TO_MINECRAFT;
|
||||||
Method method = null;
|
Method method = null;
|
||||||
@ -159,9 +159,9 @@ public class RegistryConversionTest {
|
|||||||
""", minecraftClazz.getName(), methodName, clazz.getSimpleName());
|
""", minecraftClazz.getName(), methodName, clazz.getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Order(2)
|
@Order(3)
|
||||||
@RegistriesTest
|
@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);
|
this.checkValidMinecraftToBukkit(clazz);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -180,7 +180,7 @@ public class RegistryConversionTest {
|
|||||||
|
|
||||||
@Order(3)
|
@Order(3)
|
||||||
@RegistriesTest
|
@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);
|
this.checkValidBukkitToMinecraft(clazz);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -199,14 +199,14 @@ public class RegistryConversionTest {
|
|||||||
|
|
||||||
@Order(3)
|
@Order(3)
|
||||||
@RegistriesTest
|
@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.checkValidMinecraftToBukkit(clazz);
|
||||||
this.checkValidHandle(clazz);
|
this.checkValidHandle(clazz);
|
||||||
|
|
||||||
Map<Object, Object> notMatching = new HashMap<>();
|
Map<Object, Object> notMatching = new HashMap<>();
|
||||||
Method method = RegistryConversionTest.MINECRAFT_TO_BUKKIT_METHODS.get(clazz);
|
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];
|
Keyed bukkit = (Keyed) arguments[0];
|
||||||
Object minecraft = arguments[1];
|
Object minecraft = arguments[1];
|
||||||
|
|
||||||
@ -230,14 +230,14 @@ public class RegistryConversionTest {
|
|||||||
|
|
||||||
@Order(3)
|
@Order(3)
|
||||||
@RegistriesTest
|
@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.checkValidBukkitToMinecraft(clazz);
|
||||||
this.checkValidHandle(clazz);
|
this.checkValidHandle(clazz);
|
||||||
|
|
||||||
Map<Object, Object> notMatching = new HashMap<>();
|
Map<Object, Object> notMatching = new HashMap<>();
|
||||||
Method method = RegistryConversionTest.BUKKIT_TO_MINECRAFT_METHODS.get(clazz);
|
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];
|
Keyed bukkit = (Keyed) arguments[0];
|
||||||
Object minecraft = arguments[1];
|
Object minecraft = arguments[1];
|
||||||
|
|
||||||
@ -265,7 +265,7 @@ public class RegistryConversionTest {
|
|||||||
*/
|
*/
|
||||||
@Order(3)
|
@Order(3)
|
||||||
@RegistriesTest
|
@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 {
|
Class<? extends Keyed> craftClazz, Class<?> minecraftClazz) throws IllegalAccessException {
|
||||||
this.checkValidMinecraftToBukkit(clazz);
|
this.checkValidMinecraftToBukkit(clazz);
|
||||||
|
|
||||||
|
@ -39,22 +39,7 @@ public class AllFeaturesExtension extends BaseExtension {
|
|||||||
|
|
||||||
Bukkit.setServer(server);
|
Bukkit.setServer(server);
|
||||||
|
|
||||||
when(server.getRegistry(any()))
|
// Paper - Add RegistryAccess for managing registries - replaced with registry access
|
||||||
.then(invocation -> {
|
|
||||||
Class<? extends Keyed> keyed = invocation.getArgument(0);
|
|
||||||
if (spyRegistries.containsKey(keyed)) {
|
|
||||||
return spyRegistries.get(keyed);
|
|
||||||
}
|
|
||||||
|
|
||||||
Registry<?> registry = CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry());
|
|
||||||
realRegistries.put(keyed, registry);
|
|
||||||
|
|
||||||
Registry<?> spy = mock(registry.getClass(), withSettings().stubOnly().spiedInstance(registry).defaultAnswer(CALLS_REAL_METHODS));
|
|
||||||
|
|
||||||
spyRegistries.put(keyed, spy);
|
|
||||||
|
|
||||||
return spy;
|
|
||||||
});
|
|
||||||
|
|
||||||
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
|
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,7 @@ public class LegacyExtension extends BaseExtension {
|
|||||||
|
|
||||||
Bukkit.setServer(server);
|
Bukkit.setServer(server);
|
||||||
|
|
||||||
when(server.getRegistry(any()))
|
// Paper - Add RegistryAccess for managing registries - replaced with registry access
|
||||||
.then(invocation -> {
|
|
||||||
Class<? extends Keyed> keyed = invocation.getArgument(0);
|
|
||||||
return registries.computeIfAbsent(keyed, k -> CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry()));
|
|
||||||
});
|
|
||||||
|
|
||||||
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
|
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,7 @@ public class SlowExtension extends BaseExtension {
|
|||||||
|
|
||||||
Bukkit.setServer(server);
|
Bukkit.setServer(server);
|
||||||
|
|
||||||
when(server.getRegistry(any()))
|
// Paper - Add RegistryAccess for managing registries - replaced with registry access
|
||||||
.then(invocation -> {
|
|
||||||
Class<? extends Keyed> keyed = invocation.getArgument(0);
|
|
||||||
return registries.computeIfAbsent(keyed, k -> CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry()));
|
|
||||||
});
|
|
||||||
|
|
||||||
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
|
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,7 @@ public class VanillaFeatureExtension extends BaseExtension {
|
|||||||
|
|
||||||
Bukkit.setServer(server);
|
Bukkit.setServer(server);
|
||||||
|
|
||||||
when(server.getRegistry(any()))
|
// Paper - Add RegistryAccess for managing registries - replaced with registry access
|
||||||
.then(invocation -> {
|
|
||||||
Class<? extends Keyed> keyed = invocation.getArgument(0);
|
|
||||||
return registries.computeIfAbsent(keyed, k -> CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry()));
|
|
||||||
});
|
|
||||||
|
|
||||||
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
|
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.bukkit.support.provider;
|
package org.bukkit.support.provider;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import io.papermc.paper.registry.RegistryKey;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
@ -73,41 +74,40 @@ public class RegistriesArgumentProvider implements ArgumentsProvider {
|
|||||||
private static final List<Arguments> DATA = Lists.newArrayList();
|
private static final List<Arguments> DATA = Lists.newArrayList();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// Order: Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class
|
// Order: RegistryKey, Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class
|
||||||
register(Art.class, Registries.PAINTING_VARIANT, CraftArt.class, PaintingVariant.class);
|
register(RegistryKey.PAINTING_VARIANT, Art.class, Registries.PAINTING_VARIANT, CraftArt.class, PaintingVariant.class);
|
||||||
register(Attribute.class, Registries.ATTRIBUTE, CraftAttribute.class, net.minecraft.world.entity.ai.attributes.Attribute.class);
|
register(RegistryKey.ATTRIBUTE, Attribute.class, Registries.ATTRIBUTE, CraftAttribute.class, net.minecraft.world.entity.ai.attributes.Attribute.class);
|
||||||
register(Biome.class, Registries.BIOME, CraftBiome.class, net.minecraft.world.level.biome.Biome.class);
|
register(RegistryKey.BIOME, Biome.class, Registries.BIOME, CraftBiome.class, net.minecraft.world.level.biome.Biome.class);
|
||||||
register(Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class);
|
register(RegistryKey.ENCHANTMENT, Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class);
|
||||||
register(Fluid.class, Registries.FLUID, CraftFluid.class, net.minecraft.world.level.material.Fluid.class);
|
register(RegistryKey.FLUID, Fluid.class, Registries.FLUID, CraftFluid.class, net.minecraft.world.level.material.Fluid.class);
|
||||||
register(GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class);
|
register(RegistryKey.GAME_EVENT, GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class);
|
||||||
register(MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class);
|
register(RegistryKey.INSTRUMENT, MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class);
|
||||||
register(MenuType.class, Registries.MENU, CraftMenuType.class, net.minecraft.world.inventory.MenuType.class);
|
register(RegistryKey.MOB_EFFECT, PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class);
|
||||||
register(PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class);
|
register(RegistryKey.SOUND_EVENT, Sound.class, Registries.SOUND_EVENT, CraftSound.class, SoundEvent.class);
|
||||||
register(Sound.class, Registries.SOUND_EVENT, CraftSound.class, SoundEvent.class);
|
register(RegistryKey.STRUCTURE, Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class);
|
||||||
register(Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class);
|
register(RegistryKey.STRUCTURE_TYPE, StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class);
|
||||||
register(StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class);
|
register(RegistryKey.VILLAGER_TYPE, Villager.Type.class, Registries.VILLAGER_TYPE, CraftVillager.CraftType.class, VillagerType.class);
|
||||||
register(Villager.Type.class, Registries.VILLAGER_TYPE, CraftVillager.CraftType.class, VillagerType.class);
|
register(RegistryKey.VILLAGER_PROFESSION, Villager.Profession.class, Registries.VILLAGER_PROFESSION, CraftVillager.CraftProfession.class, VillagerProfession.class);
|
||||||
register(Villager.Profession.class, Registries.VILLAGER_PROFESSION, CraftVillager.CraftProfession.class, VillagerProfession.class);
|
register(RegistryKey.TRIM_MATERIAL, TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.equipment.trim.TrimMaterial.class);
|
||||||
register(TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.equipment.trim.TrimMaterial.class);
|
register(RegistryKey.TRIM_PATTERN, TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.equipment.trim.TrimPattern.class);
|
||||||
register(TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.equipment.trim.TrimPattern.class);
|
register(RegistryKey.DAMAGE_TYPE, DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class);
|
||||||
register(DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class);
|
register(RegistryKey.JUKEBOX_SONG, JukeboxSong.class, Registries.JUKEBOX_SONG, CraftJukeboxSong.class, net.minecraft.world.item.JukeboxSong.class);
|
||||||
register(JukeboxSong.class, Registries.JUKEBOX_SONG, CraftJukeboxSong.class, net.minecraft.world.item.JukeboxSong.class);
|
register(RegistryKey.WOLF_VARIANT, Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, WolfVariant.class);
|
||||||
register(Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, WolfVariant.class);
|
register(RegistryKey.ITEM, ItemType.class, Registries.ITEM, CraftItemType.class, net.minecraft.world.item.Item.class, true);
|
||||||
register(ItemType.class, Registries.ITEM, CraftItemType.class, net.minecraft.world.item.Item.class, true);
|
register(RegistryKey.BLOCK, BlockType.class, Registries.BLOCK, CraftBlockType.class, net.minecraft.world.level.block.Block.class, true);
|
||||||
register(BlockType.class, Registries.BLOCK, CraftBlockType.class, net.minecraft.world.level.block.Block.class, true);
|
register(RegistryKey.FROG_VARIANT, Frog.Variant.class, Registries.FROG_VARIANT, CraftFrog.CraftVariant.class, FrogVariant.class);
|
||||||
register(Frog.Variant.class, Registries.FROG_VARIANT, CraftFrog.CraftVariant.class, FrogVariant.class);
|
register(RegistryKey.CAT_VARIANT, Cat.Type.class, Registries.CAT_VARIANT, CraftCat.CraftType.class, CatVariant.class);
|
||||||
register(Cat.Type.class, Registries.CAT_VARIANT, CraftCat.CraftType.class, CatVariant.class);
|
register(RegistryKey.MAP_DECORATION_TYPE, MapCursor.Type.class, Registries.MAP_DECORATION_TYPE, CraftMapCursor.CraftType.class, MapDecorationType.class);
|
||||||
register(MapCursor.Type.class, Registries.MAP_DECORATION_TYPE, CraftMapCursor.CraftType.class, MapDecorationType.class);
|
register(RegistryKey.BANNER_PATTERN, PatternType.class, Registries.BANNER_PATTERN, CraftPatternType.class, BannerPattern.class);
|
||||||
register(PatternType.class, Registries.BANNER_PATTERN, CraftPatternType.class, BannerPattern.class);
|
register(RegistryKey.MENU, MenuType.class, Registries.MENU, CraftMenuType.class, net.minecraft.world.inventory.MenuType.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void register(Class bukkit, ResourceKey registry, Class craft, Class minecraft) {
|
private static void register(RegistryKey registryKey, Class bukkit, ResourceKey registry, Class craft, Class minecraft) { // Paper
|
||||||
RegistriesArgumentProvider.register(bukkit, registry, craft, minecraft, false);
|
RegistriesArgumentProvider.register(registryKey, bukkit, registry, craft, minecraft, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void register(Class bukkit, ResourceKey registry, Class craft, Class minecraft, boolean newClass) {
|
private static void register(RegistryKey registryKey, Class bukkit, ResourceKey registry, Class craft, Class minecraft, boolean newClass) { // Paper
|
||||||
RegistriesArgumentProvider.DATA.add(Arguments.of(bukkit, registry, craft, minecraft, newClass));
|
RegistriesArgumentProvider.DATA.add(Arguments.of(registryKey, bukkit, registry, craft, minecraft, newClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -22,11 +22,11 @@ public class RegistryArgumentProvider implements ArgumentsProvider, AnnotationCo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) throws Exception {
|
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) {
|
public static Stream<? extends Arguments> getValues(io.papermc.paper.registry.RegistryKey<? extends Keyed> registryType) { // Paper
|
||||||
Registry<?> registry = Bukkit.getRegistry(registryType);
|
Registry<?> registry = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(registryType); // Paper
|
||||||
return registry.stream().map(keyed -> (Handleable<?>) keyed)
|
return registry.stream().map(keyed -> (Handleable<?>) keyed)
|
||||||
.map(handleAble -> Arguments.of(handleAble, handleAble.getHandle()));
|
.map(handleAble -> Arguments.of(handleAble, handleAble.getHandle()));
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren