SPIGOT-7648, SPIGOT-7927: Allow creating of not registered Instruments

This commit is contained in:
DerFrZocker 2024-12-10 20:33:03 +11:00 committed by md_5
parent a7eb3fdfd8
commit d628417978
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11
5 changed files with 111 additions and 59 deletions

View File

@ -1,24 +1,40 @@
package org.bukkit.craftbukkit;
import com.google.common.base.Preconditions;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.RegistryOps;
import net.minecraft.world.item.Instrument;
import org.bukkit.MusicInstrument;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.util.HolderHandleable;
import org.jetbrains.annotations.NotNull;
public class CraftMusicInstrument extends MusicInstrument implements Handleable<Instrument> {
public class CraftMusicInstrument extends MusicInstrument implements HolderHandleable<Instrument> {
public static MusicInstrument minecraftToBukkit(Instrument minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.INSTRUMENT, Registry.INSTRUMENT);
}
public static MusicInstrument minecraftHolderToBukkit(Holder<Instrument> minecraft) {
return minecraftToBukkit(minecraft.value());
Preconditions.checkArgument(minecraft != null);
if (minecraft instanceof Holder.c<Instrument> holder) {
MusicInstrument bukkit = Registry.INSTRUMENT.get(CraftNamespacedKey.fromMinecraft(holder.key().location()));
Preconditions.checkArgument(bukkit != null);
return bukkit;
}
return new CraftMusicInstrument(null, minecraft);
}
public static Instrument bukkitToMinecraft(MusicInstrument bukkit) {
@ -26,69 +42,91 @@ public class CraftMusicInstrument extends MusicInstrument implements Handleable<
}
public static Holder<Instrument> bukkitToMinecraftHolder(MusicInstrument bukkit) {
Preconditions.checkArgument(bukkit != null);
IRegistry<Instrument> registry = CraftRegistry.getMinecraftRegistry(Registries.INSTRUMENT);
if (registry.wrapAsHolder(bukkitToMinecraft(bukkit)) instanceof Holder.c<Instrument> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own instrument without properly registering it.");
return ((HolderHandleable<Instrument>) bukkit).getHandleHolder();
}
public static String bukkitToString(MusicInstrument bukkit) {
Preconditions.checkArgument(bukkit != null);
return bukkit.getKey().toString();
Holder<Instrument> holder = bukkitToMinecraftHolder(bukkit);
return Instrument.CODEC.encodeStart(RegistryOps.create(JsonOps.INSTANCE, CraftRegistry.getMinecraftRegistry()), holder).result().get().toString();
}
public static MusicInstrument stringToBukkit(String string) {
Preconditions.checkArgument(string != null);
return Registry.INSTRUMENT.get(NamespacedKey.fromString(string));
NamespacedKey key = NamespacedKey.fromString(string);
if (key != null) {
MusicInstrument bukkit = Registry.INSTRUMENT.get(key);
if (bukkit != null) {
return bukkit;
}
}
JsonElement json = JsonParser.parseString(string);
DataResult<Pair<Holder<Instrument>, JsonElement>> result = Instrument.CODEC.decode(RegistryOps.create(JsonOps.INSTANCE, CraftRegistry.getMinecraftRegistry()), json);
return CraftMusicInstrument.minecraftHolderToBukkit(result.getOrThrow().getFirst());
}
private final NamespacedKey key;
private final Instrument handle;
private final Holder<Instrument> handle;
public CraftMusicInstrument(NamespacedKey key, Instrument handle) {
public CraftMusicInstrument(NamespacedKey key, Holder<Instrument> handle) {
this.key = key;
this.handle = handle;
}
@Override
public Instrument getHandle() {
return handle.value();
}
@Override
public Holder<Instrument> getHandleHolder() {
return handle;
}
@NotNull
@Override
public NamespacedKey getKey() {
if (key == null) {
throw new IllegalStateException("Music instrument is not registered.");
}
return key;
}
@Override
public boolean equals(Object other) {
if (this == other) {
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(other instanceof CraftMusicInstrument)) {
if (!(o instanceof CraftMusicInstrument other)) {
return false;
}
return getKey().equals(((MusicInstrument) other).getKey());
if (this.key != null && other.key != null) {
return this.key.equals(other.key);
}
return getHandle().equals(other.getHandle());
}
@Override
public int hashCode() {
return getKey().hashCode();
if (key != null) {
return key.hashCode();
}
return getHandle().hashCode();
}
@Override
public String toString() {
return "CraftMusicInstrument{key=" + key + "}";
return "CraftMusicInstrument{key=" + key + ", handle=" + handle + "}";
}
}

View File

@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.particles.ColorParticleOption;
import net.minecraft.core.particles.DustColorTransitionOptions;
@ -221,14 +222,14 @@ public abstract class CraftParticle<D> implements Keyed {
}
@Override
public CraftParticle<?> createBukkit(NamespacedKey namespacedKey, net.minecraft.core.particles.Particle<?> particle) {
public CraftParticle<?> createBukkit(NamespacedKey namespacedKey, Holder<net.minecraft.core.particles.Particle<?>> particle) {
if (particle == null) {
return null;
}
BiFunction<NamespacedKey, net.minecraft.core.particles.Particle<?>, CraftParticle<?>> function = PARTICLE_MAP.getOrDefault(namespacedKey, VOID_FUNCTION);
return function.apply(namespacedKey, particle);
return function.apply(namespacedKey, particle.value());
}
}
}

View File

@ -128,6 +128,10 @@ 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.");
}
private static <M, B> BiFunction<NamespacedKey, Holder<M>, B> wrap(BiFunction<NamespacedKey, M, B> minecraftToBukkit) {
return ((namespacedKey, holder) -> minecraftToBukkit.apply(namespacedKey, holder.value()));
}
/**
* Note: Newly added registries should also be added to RegistriesArgumentProvider in the test package
*
@ -137,79 +141,79 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
*/
public static <B extends Keyed> Registry<?> createRegistry(Class<? super B> bukkitClass, IRegistryCustom registryHolder) {
if (bukkitClass == Art.class) {
return new CraftRegistry<>(Art.class, registryHolder.lookupOrThrow(Registries.PAINTING_VARIANT), CraftArt::new, FieldRename.NONE);
return new CraftRegistry<>(Art.class, registryHolder.lookupOrThrow(Registries.PAINTING_VARIANT), wrap(CraftArt::new), FieldRename.NONE);
}
if (bukkitClass == Attribute.class) {
return new CraftRegistry<>(Attribute.class, registryHolder.lookupOrThrow(Registries.ATTRIBUTE), CraftAttribute::new, FieldRename.ATTRIBUTE_RENAME);
return new CraftRegistry<>(Attribute.class, registryHolder.lookupOrThrow(Registries.ATTRIBUTE), wrap(CraftAttribute::new), FieldRename.ATTRIBUTE_RENAME);
}
if (bukkitClass == Biome.class) {
return new CraftRegistry<>(Biome.class, registryHolder.lookupOrThrow(Registries.BIOME), CraftBiome::new, FieldRename.BIOME_RENAME);
return new CraftRegistry<>(Biome.class, registryHolder.lookupOrThrow(Registries.BIOME), wrap(CraftBiome::new), FieldRename.BIOME_RENAME);
}
if (bukkitClass == Enchantment.class) {
return new CraftRegistry<>(Enchantment.class, registryHolder.lookupOrThrow(Registries.ENCHANTMENT), CraftEnchantment::new, FieldRename.ENCHANTMENT_RENAME);
return new CraftRegistry<>(Enchantment.class, registryHolder.lookupOrThrow(Registries.ENCHANTMENT), wrap(CraftEnchantment::new), FieldRename.ENCHANTMENT_RENAME);
}
if (bukkitClass == Fluid.class) {
return new CraftRegistry<>(Fluid.class, registryHolder.lookupOrThrow(Registries.FLUID), CraftFluid::new, FieldRename.NONE);
return new CraftRegistry<>(Fluid.class, registryHolder.lookupOrThrow(Registries.FLUID), wrap(CraftFluid::new), FieldRename.NONE);
}
if (bukkitClass == GameEvent.class) {
return new CraftRegistry<>(GameEvent.class, registryHolder.lookupOrThrow(Registries.GAME_EVENT), CraftGameEvent::new, FieldRename.NONE);
return new CraftRegistry<>(GameEvent.class, registryHolder.lookupOrThrow(Registries.GAME_EVENT), wrap(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);
return new CraftRegistry<>(MenuType.class, registryHolder.lookupOrThrow(Registries.MENU), wrap(CraftMenuType::new), FieldRename.NONE);
}
if (bukkitClass == PotionEffectType.class) {
return new CraftRegistry<>(PotionEffectType.class, registryHolder.lookupOrThrow(Registries.MOB_EFFECT), CraftPotionEffectType::new, FieldRename.NONE);
return new CraftRegistry<>(PotionEffectType.class, registryHolder.lookupOrThrow(Registries.MOB_EFFECT), wrap(CraftPotionEffectType::new), FieldRename.NONE);
}
if (bukkitClass == Sound.class) {
return new CraftRegistry<>(Sound.class, registryHolder.lookupOrThrow(Registries.SOUND_EVENT), CraftSound::new, FieldRename.NONE);
return new CraftRegistry<>(Sound.class, registryHolder.lookupOrThrow(Registries.SOUND_EVENT), wrap(CraftSound::new), FieldRename.NONE);
}
if (bukkitClass == Structure.class) {
return new CraftRegistry<>(Structure.class, registryHolder.lookupOrThrow(Registries.STRUCTURE), CraftStructure::new, FieldRename.NONE);
return new CraftRegistry<>(Structure.class, registryHolder.lookupOrThrow(Registries.STRUCTURE), wrap(CraftStructure::new), FieldRename.NONE);
}
if (bukkitClass == StructureType.class) {
return new CraftRegistry<>(StructureType.class, registryHolder.lookupOrThrow(Registries.STRUCTURE_TYPE), CraftStructureType::new, FieldRename.NONE);
return new CraftRegistry<>(StructureType.class, registryHolder.lookupOrThrow(Registries.STRUCTURE_TYPE), wrap(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);
return new CraftRegistry<>(Villager.Type.class, registryHolder.lookupOrThrow(Registries.VILLAGER_TYPE), wrap(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);
return new CraftRegistry<>(Villager.Profession.class, registryHolder.lookupOrThrow(Registries.VILLAGER_PROFESSION), wrap(CraftVillager.CraftProfession::new), FieldRename.NONE);
}
if (bukkitClass == TrimMaterial.class) {
return new CraftRegistry<>(TrimMaterial.class, registryHolder.lookupOrThrow(Registries.TRIM_MATERIAL), CraftTrimMaterial::new, FieldRename.NONE);
return new CraftRegistry<>(TrimMaterial.class, registryHolder.lookupOrThrow(Registries.TRIM_MATERIAL), wrap(CraftTrimMaterial::new), FieldRename.NONE);
}
if (bukkitClass == TrimPattern.class) {
return new CraftRegistry<>(TrimPattern.class, registryHolder.lookupOrThrow(Registries.TRIM_PATTERN), CraftTrimPattern::new, FieldRename.NONE);
return new CraftRegistry<>(TrimPattern.class, registryHolder.lookupOrThrow(Registries.TRIM_PATTERN), wrap(CraftTrimPattern::new), FieldRename.NONE);
}
if (bukkitClass == DamageType.class) {
return new CraftRegistry<>(DamageType.class, registryHolder.lookupOrThrow(Registries.DAMAGE_TYPE), CraftDamageType::new, FieldRename.NONE);
return new CraftRegistry<>(DamageType.class, registryHolder.lookupOrThrow(Registries.DAMAGE_TYPE), wrap(CraftDamageType::new), FieldRename.NONE);
}
if (bukkitClass == JukeboxSong.class) {
return new CraftRegistry<>(JukeboxSong.class, registryHolder.lookupOrThrow(Registries.JUKEBOX_SONG), CraftJukeboxSong::new, FieldRename.NONE);
return new CraftRegistry<>(JukeboxSong.class, registryHolder.lookupOrThrow(Registries.JUKEBOX_SONG), wrap(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);
return new CraftRegistry<>(Wolf.Variant.class, registryHolder.lookupOrThrow(Registries.WOLF_VARIANT), wrap(CraftWolf.CraftVariant::new), FieldRename.NONE);
}
if (bukkitClass == BlockType.class) {
return new CraftRegistry<>(BlockType.class, registryHolder.lookupOrThrow(Registries.BLOCK), CraftBlockType::new, FieldRename.NONE);
return new CraftRegistry<>(BlockType.class, registryHolder.lookupOrThrow(Registries.BLOCK), wrap(CraftBlockType::new), FieldRename.NONE);
}
if (bukkitClass == ItemType.class) {
return new CraftRegistry<>(ItemType.class, registryHolder.lookupOrThrow(Registries.ITEM), CraftItemType::new, FieldRename.NONE);
return new CraftRegistry<>(ItemType.class, registryHolder.lookupOrThrow(Registries.ITEM), wrap(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);
return new CraftRegistry<>(Frog.Variant.class, registryHolder.lookupOrThrow(Registries.FROG_VARIANT), wrap(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);
return new CraftRegistry<>(Cat.Type.class, registryHolder.lookupOrThrow(Registries.CAT_VARIANT), wrap(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);
return new CraftRegistry<>(MapCursor.Type.class, registryHolder.lookupOrThrow(Registries.MAP_DECORATION_TYPE), wrap(CraftMapCursor.CraftType::new), FieldRename.NONE);
}
if (bukkitClass == PatternType.class) {
return new CraftRegistry<>(PatternType.class, registryHolder.lookupOrThrow(Registries.BANNER_PATTERN), CraftPatternType::new, FieldRename.NONE);
return new CraftRegistry<>(PatternType.class, registryHolder.lookupOrThrow(Registries.BANNER_PATTERN), wrap(CraftPatternType::new), FieldRename.NONE);
}
return null;
@ -238,11 +242,11 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
private final Class<? super B> bukkitClass;
private final Map<NamespacedKey, B> cache = new HashMap<>();
private final IRegistry<M> minecraftRegistry;
private final BiFunction<NamespacedKey, M, B> minecraftToBukkit;
private final BiFunction<NamespacedKey, Holder<M>, B> minecraftToBukkit;
private final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater;
private boolean init;
public CraftRegistry(Class<? super B> bukkitClass, IRegistry<M> minecraftRegistry, BiFunction<NamespacedKey, M, B> minecraftToBukkit, BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater) {
public CraftRegistry(Class<? super B> bukkitClass, IRegistry<M> minecraftRegistry, BiFunction<NamespacedKey, Holder<M>, B> minecraftToBukkit, BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater) {
this.bukkitClass = bukkitClass;
this.minecraftRegistry = minecraftRegistry;
this.minecraftToBukkit = minecraftToBukkit;
@ -281,7 +285,7 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return get(namespacedKey);
}
B bukkit = createBukkit(namespacedKey, minecraftRegistry.getOptional(CraftNamespacedKey.toMinecraft(namespacedKey)).orElse(null));
B bukkit = createBukkit(namespacedKey, minecraftRegistry.get(CraftNamespacedKey.toMinecraft(namespacedKey)).orElse(null));
if (bukkit == null) {
return null;
}
@ -312,7 +316,7 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return stream().iterator();
}
public B createBukkit(NamespacedKey namespacedKey, M minecraft) {
public B createBukkit(NamespacedKey namespacedKey, Holder<M> minecraft) {
if (minecraft == null) {
return null;
}

View File

@ -0,0 +1,8 @@
package org.bukkit.craftbukkit.util;
import net.minecraft.core.Holder;
public interface HolderHandleable<M> extends Handleable<M> {
Holder<M> getHandleHolder();
}

View File

@ -6,6 +6,7 @@ import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.stream.Stream;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.RegistrationInfo;
import net.minecraft.core.RegistryMaterials;
@ -33,14 +34,14 @@ public class RegistryLoadOrderTest {
Arguments.of(
(Supplier<Boolean>) () -> initInterface,
BukkitInterfaceTestType.class,
(BiFunction<NamespacedKey, MinecraftTestType, Keyed>) CraftBukkitInterfaceTestType::new,
(BiFunction<NamespacedKey, Holder<MinecraftTestType>, Keyed>) CraftBukkitInterfaceTestType::new,
(Supplier<Keyed>) () -> BukkitInterfaceTestType.TEST_ONE,
(Supplier<Keyed>) () -> BukkitInterfaceTestType.TEST_TWO
),
Arguments.of(
(Supplier<Boolean>) () -> initAbstract,
BukkitAbstractTestType.class,
(BiFunction<NamespacedKey, MinecraftTestType, Keyed>) CraftBukkitAbstractTestType::new,
(BiFunction<NamespacedKey, Holder<MinecraftTestType>, Keyed>) CraftBukkitAbstractTestType::new,
(Supplier<Keyed>) () -> BukkitAbstractTestType.TEST_ONE,
(Supplier<Keyed>) () -> BukkitAbstractTestType.TEST_TWO
)
@ -49,7 +50,7 @@ public class RegistryLoadOrderTest {
@ParameterizedTest
@MethodSource("data")
public void testRegistryLoadOrder(Supplier<Boolean> init, Class<Keyed> keyedClass, BiFunction<NamespacedKey, MinecraftTestType, Keyed> minecraftToBukkit, Supplier<Keyed> first, Supplier<Keyed> second) {
public void testRegistryLoadOrder(Supplier<Boolean> init, Class<Keyed> keyedClass, BiFunction<NamespacedKey, Holder<MinecraftTestType>, Keyed> minecraftToBukkit, Supplier<Keyed> first, Supplier<Keyed> second) {
testClassNotLoaded(init.get());
ResourceKey<IRegistry<MinecraftTestType>> resourceKey = ResourceKey.createRegistryKey(MinecraftKey.tryBuild("bukkit", "test-registry"));
@ -106,7 +107,7 @@ public class RegistryLoadOrderTest {
private final NamespacedKey key;
public CraftBukkitInterfaceTestType(NamespacedKey key, MinecraftTestType minecraftTestType) {
public CraftBukkitInterfaceTestType(NamespacedKey key, Holder<MinecraftTestType> minecraftTestType) {
this.key = key;
}
@ -135,7 +136,7 @@ public class RegistryLoadOrderTest {
private final NamespacedKey key;
public CraftBukkitAbstractTestType(NamespacedKey key, MinecraftTestType minecraftTestType) {
public CraftBukkitAbstractTestType(NamespacedKey key, Holder<MinecraftTestType> minecraftTestType) {
this.key = key;
}