diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/InlinedRegistryBuilderProvider.java b/paper-api/src/main/java/io/papermc/paper/registry/data/InlinedRegistryBuilderProvider.java index 974e3b43dfd..68b56dcd11e 100644 --- a/paper-api/src/main/java/io/papermc/paper/registry/data/InlinedRegistryBuilderProvider.java +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/InlinedRegistryBuilderProvider.java @@ -4,7 +4,7 @@ import io.papermc.paper.registry.RegistryBuilderFactory; import java.util.Optional; import java.util.ServiceLoader; import java.util.function.Consumer; -import org.bukkit.Art; +import org.bukkit.MusicInstrument; import org.jetbrains.annotations.ApiStatus; @ApiStatus.Internal @@ -18,4 +18,5 @@ public interface InlinedRegistryBuilderProvider { return Holder.INSTANCE.orElseThrow(); } + MusicInstrument createInstrument(Consumer> value); } diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/InstrumentRegistryEntry.java b/paper-api/src/main/java/io/papermc/paper/registry/data/InstrumentRegistryEntry.java new file mode 100644 index 00000000000..3ae55ffe6af --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/InstrumentRegistryEntry.java @@ -0,0 +1,149 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.RegistryBuilder; +import io.papermc.paper.registry.RegistryBuilderFactory; +import io.papermc.paper.registry.TypedKey; +import io.papermc.paper.registry.holder.RegistryHolder; +import net.kyori.adventure.text.Component; +import org.bukkit.MusicInstrument; +import org.bukkit.Sound; +import org.checkerframework.checker.index.qual.Positive; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import java.util.function.Consumer; + +/** + * A data-centric version-specific registry entry for the {@link org.bukkit.MusicInstrument} type. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface InstrumentRegistryEntry { + + /** + * Provides the sound event of the instrument. + * + * @return the sound event. + * @see MusicInstrument#getSound() + */ + @Contract(pure = true) + RegistryHolder soundEvent(); + + /** + * Provides the duration of the instrument, which is time to use. + * + * @return the duration. + * @see MusicInstrument#getDuration() + */ + @Contract(pure = true) + @Positive float duration(); + + /** + * Provides the range of the instrument, which is range of the sound. + * + * @return the range. + * @see MusicInstrument#getRange() + */ + @Contract(pure = true) + @Positive float range(); + + /** + * Provides the description of the instrument, which is used in the item tooltip. + * + * @return the description. + * @see MusicInstrument#description() + */ + @Contract(pure = true) + Component description(); + + /** + * A mutable builder for the {@link InstrumentRegistryEntry} plugins may change in applicable registry events. + *

+ * The following values are required for each builder: + *

+ */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends InstrumentRegistryEntry, RegistryBuilder { + + /** + * Sets the sound event for this instrument to a sound event present + * in the {@link io.papermc.paper.registry.RegistryKey#SOUND_EVENT} registry. + *

This will override both {@link #soundEvent(Consumer)} and {@link #soundEvent(RegistryHolder)}

+ * + * @param soundEvent the sound event + * @return this builder + * @see #soundEvent(Consumer) + * @see InstrumentRegistryEntry#soundEvent() + * @see MusicInstrument#getSound() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder soundEvent(TypedKey soundEvent); + + /** + * Sets the sound event for this instrument to a new sound event. + *

This will override both {@link #soundEvent(TypedKey)} and {@link #soundEvent(RegistryHolder)}

+ * + * @param soundEvent the sound event + * @return this builder + * @see #soundEvent(TypedKey) + * @see InstrumentRegistryEntry#soundEvent() + * @see MusicInstrument#getSound() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder soundEvent(Consumer> soundEvent); + + /** + * Sets the sound event for this instrument. + *

This will override both {@link #soundEvent(Consumer)} and {@link #soundEvent(TypedKey)}

+ * + * @param soundEvent the sound event + * @return this builder + * @see #soundEvent(TypedKey) + * @see #soundEvent(Consumer) + * @see InstrumentRegistryEntry#soundEvent() + * @see MusicInstrument#getSound() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder soundEvent(RegistryHolder soundEvent); + + /** + * Sets the duration of use for this instrument. + * + * @param duration the duration (positive) + * @return this builder + * @see InstrumentRegistryEntry#duration() + * @see MusicInstrument#getDuration() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder duration(@Positive float duration); + + /** + * Sets the range for this instrument. + * + * @param range the range (positive) + * @return this builder + * @see InstrumentRegistryEntry#range() + * @see MusicInstrument#getRange() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder range(@Positive float range); + + /** + * Sets the description for this instrument. + * + * @param description the description + * @return this builder + * @see InstrumentRegistryEntry#description() + * @see MusicInstrument#description() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder description(Component description); + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java b/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java index 39759e2150e..eb7d5efd040 100644 --- a/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java +++ b/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java @@ -9,6 +9,7 @@ import io.papermc.paper.registry.data.DamageTypeRegistryEntry; import io.papermc.paper.registry.data.EnchantmentRegistryEntry; import io.papermc.paper.registry.data.FrogVariantRegistryEntry; import io.papermc.paper.registry.data.GameEventRegistryEntry; +import io.papermc.paper.registry.data.InstrumentRegistryEntry; import io.papermc.paper.registry.data.JukeboxSongRegistryEntry; import io.papermc.paper.registry.data.PaintingVariantRegistryEntry; import io.papermc.paper.registry.data.PigVariantRegistryEntry; @@ -16,6 +17,7 @@ import io.papermc.paper.registry.data.WolfVariantRegistryEntry; import org.bukkit.Art; import org.bukkit.GameEvent; import org.bukkit.JukeboxSong; +import org.bukkit.MusicInstrument; import org.bukkit.block.banner.PatternType; import org.bukkit.damage.DamageType; import org.bukkit.enchantments.Enchantment; @@ -43,6 +45,7 @@ public final class RegistryEvents { public static final RegistryEventProvider JUKEBOX_SONG = create(RegistryKey.JUKEBOX_SONG); public static final RegistryEventProvider BANNER_PATTERN = create(RegistryKey.BANNER_PATTERN); public static final RegistryEventProvider PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT); + public static final RegistryEventProvider INSTRUMENT = create(RegistryKey.INSTRUMENT); public static final RegistryEventProvider CAT_VARIANT = create(RegistryKey.CAT_VARIANT); public static final RegistryEventProvider FROG_VARIANT = create(RegistryKey.FROG_VARIANT); public static final RegistryEventProvider CHICKEN_VARIANT = create(RegistryKey.CHICKEN_VARIANT); diff --git a/paper-api/src/main/java/org/bukkit/MusicInstrument.java b/paper-api/src/main/java/org/bukkit/MusicInstrument.java index 4d031f4fd82..46c50b49af6 100644 --- a/paper-api/src/main/java/org/bukkit/MusicInstrument.java +++ b/paper-api/src/main/java/org/bukkit/MusicInstrument.java @@ -2,16 +2,32 @@ package org.bukkit; import com.google.common.collect.Lists; import io.papermc.paper.registry.RegistryAccess; +import io.papermc.paper.registry.RegistryBuilderFactory; import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.data.InlinedRegistryBuilderProvider; +import io.papermc.paper.registry.data.InstrumentRegistryEntry; import java.util.Collection; import java.util.Collections; +import java.util.function.Consumer; import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; @NullMarked public abstract class MusicInstrument implements Keyed, net.kyori.adventure.translation.Translatable { + /** + * Creates an inlined music instrument. + * + * @param value a consumer for the builder factory + * @return the created music instrument + */ + @ApiStatus.Experimental + public static MusicInstrument create(final Consumer> value) { + return InlinedRegistryBuilderProvider.instance().createInstrument(value); + } + // Start generate - MusicInstrument // @GeneratedFrom 1.21.7 public static final MusicInstrument ADMIRE_GOAT_HORN = getInstrument("admire_goat_horn"); @@ -31,12 +47,16 @@ public abstract class MusicInstrument implements Keyed, net.kyori.adventure.tran public static final MusicInstrument YEARN_GOAT_HORN = getInstrument("yearn_goat_horn"); // End generate - MusicInstrument + private static MusicInstrument getInstrument(final String key) { + return RegistryAccess.registryAccess().getRegistry(RegistryKey.INSTRUMENT).getOrThrow(NamespacedKey.minecraft(key)); + } + /** * Returns a {@link MusicInstrument} by a {@link NamespacedKey}. * * @param namespacedKey the key * @return the event or null - * @deprecated Use {@link Registry#get(NamespacedKey)} instead. + * @deprecated use {@link Registry#get(NamespacedKey)} instead */ @Nullable @Deprecated(since = "1.20.1") @@ -45,38 +65,34 @@ public abstract class MusicInstrument implements Keyed, net.kyori.adventure.tran } /** - * Returns all known MusicInstruments. + * Returns all known music instruments. * - * @return the memoryKeys - * @deprecated use {@link Registry#iterator()}. + * @return the music instruments + * @deprecated use {@link Registry#iterator()} */ @Deprecated(since = "1.20.1") public static Collection values() { return Collections.unmodifiableCollection(Lists.newArrayList(Registry.INSTRUMENT)); } - private static MusicInstrument getInstrument(final String key) { - return RegistryAccess.registryAccess().getRegistry(RegistryKey.INSTRUMENT).getOrThrow(NamespacedKey.minecraft(key)); - } - /** * Gets the use duration of this music instrument. * - * @return the duration expressed in seconds. + * @return the duration expressed in seconds */ public abstract float getDuration(); /** * Gets the range of the sound. * - * @return the range of the sound. + * @return the range of the sound */ public abstract float getRange(); /** - * Provides the description of this instrument as displayed to the client. + * Gets the description of this instrument as displayed to the client. * - * @return the description component. + * @return the description component */ public abstract Component description(); diff --git a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java index 4dd12254615..e792cd56693 100644 --- a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java +++ b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java @@ -11,6 +11,7 @@ import io.papermc.paper.registry.data.DamageTypeRegistryEntry; import io.papermc.paper.registry.data.EnchantmentRegistryEntry; import io.papermc.paper.registry.data.FrogVariantRegistryEntry; import io.papermc.paper.registry.data.GameEventRegistryEntry; +import io.papermc.paper.registry.data.InstrumentRegistryEntry; import io.papermc.paper.registry.data.JukeboxSongRegistryEntry; import io.papermc.paper.registry.data.PaintingVariantRegistryEntry; import io.papermc.paper.registry.data.PigVariantRegistryEntry; @@ -175,7 +176,7 @@ public final class RegistryEntries { entry(Registries.JUKEBOX_SONG, JukeboxSongs.class, JukeboxSong.class).writableApiRegistryBuilder(JukeboxSongRegistryEntry.Builder.class, "PaperJukeboxSongRegistryEntry.PaperBuilder").delayed(), entry(Registries.BANNER_PATTERN, BannerPatterns.class, PatternType.class).allowDirect().writableApiRegistryBuilder(BannerPatternRegistryEntry.Builder.class, "PaperBannerPatternRegistryEntry.PaperBuilder").delayed(), entry(Registries.PAINTING_VARIANT, PaintingVariants.class, Art.class).writableApiRegistryBuilder(PaintingVariantRegistryEntry.Builder.class, "PaperPaintingVariantRegistryEntry.PaperBuilder").apiRegistryField("ART").delayed(), - entry(Registries.INSTRUMENT, Instruments.class, MusicInstrument.class).allowDirect().delayed(), + entry(Registries.INSTRUMENT, Instruments.class, MusicInstrument.class).allowDirect().writableApiRegistryBuilder(InstrumentRegistryEntry.Builder.class, "PaperInstrumentRegistryEntry.PaperBuilder").delayed(), entry(Registries.CAT_VARIANT, CatVariants.class, Cat.Type.class).writableApiRegistryBuilder(CatTypeRegistryEntry.Builder.class, "PaperCatTypeRegistryEntry.PaperBuilder").delayed(), entry(Registries.FROG_VARIANT, FrogVariants.class, Frog.Variant.class).writableApiRegistryBuilder(FrogVariantRegistryEntry.Builder.class, "PaperFrogVariantRegistryEntry.PaperBuilder").delayed(), entry(Registries.CHICKEN_VARIANT, ChickenVariants.class, Chicken.Variant.class).writableApiRegistryBuilder(ChickenVariantRegistryEntry.Builder.class, "PaperChickenVariantRegistryEntry.PaperBuilder"), diff --git a/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java index c23c67f2976..4a0d5da6766 100644 --- a/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java +++ b/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java @@ -12,6 +12,7 @@ import io.papermc.paper.registry.data.PaperDamageTypeRegistryEntry; import io.papermc.paper.registry.data.PaperEnchantmentRegistryEntry; import io.papermc.paper.registry.data.PaperFrogVariantRegistryEntry; import io.papermc.paper.registry.data.PaperGameEventRegistryEntry; +import io.papermc.paper.registry.data.PaperInstrumentRegistryEntry; import io.papermc.paper.registry.data.PaperJukeboxSongRegistryEntry; import io.papermc.paper.registry.data.PaperPaintingVariantRegistryEntry; import io.papermc.paper.registry.data.PaperPigVariantRegistryEntry; @@ -125,7 +126,7 @@ public final class PaperRegistries { start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).writable(PaperJukeboxSongRegistryEntry.PaperBuilder::new).delayed(), start(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN).craft(PatternType.class, CraftPatternType::new, true).writable(PaperBannerPatternRegistryEntry.PaperBuilder::new).delayed(), start(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT).craft(Art.class, CraftArt::new).writable(PaperPaintingVariantRegistryEntry.PaperBuilder::new).delayed(), - start(Registries.INSTRUMENT, RegistryKey.INSTRUMENT).craft(MusicInstrument.class, CraftMusicInstrument::new, true).build().delayed(), + start(Registries.INSTRUMENT, RegistryKey.INSTRUMENT).craft(MusicInstrument.class, CraftMusicInstrument::new, true).writable(PaperInstrumentRegistryEntry.PaperBuilder::new).delayed(), start(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT).craft(Cat.Type.class, CraftCat.CraftType::new).writable(PaperCatTypeRegistryEntry.PaperBuilder::new).delayed(), start(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT).craft(Frog.Variant.class, CraftFrog.CraftVariant::new).writable(PaperFrogVariantRegistryEntry.PaperBuilder::new).delayed(), start(Registries.CHICKEN_VARIANT, RegistryKey.CHICKEN_VARIANT).craft(Chicken.Variant.class, CraftChicken.CraftVariant::new).writable(PaperChickenVariantRegistryEntry.PaperBuilder::new), diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/InlinedRegistryBuilderProviderImpl.java b/paper-server/src/main/java/io/papermc/paper/registry/data/InlinedRegistryBuilderProviderImpl.java index dbde5b9913d..41539dc0459 100644 --- a/paper-server/src/main/java/io/papermc/paper/registry/data/InlinedRegistryBuilderProviderImpl.java +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/InlinedRegistryBuilderProviderImpl.java @@ -1,4 +1,15 @@ package io.papermc.paper.registry.data; +import io.papermc.paper.registry.RegistryBuilderFactory; +import io.papermc.paper.registry.data.util.Conversions; +import java.util.function.Consumer; +import net.minecraft.core.registries.Registries; +import org.bukkit.MusicInstrument; + public final class InlinedRegistryBuilderProviderImpl implements InlinedRegistryBuilderProvider { + + @Override + public MusicInstrument createInstrument(final Consumer> value) { + return Conversions.global().createApiInstanceFromBuilder(Registries.INSTRUMENT, value); + } } diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/PaperInstrumentRegistryEntry.java b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperInstrumentRegistryEntry.java new file mode 100644 index 00000000000..7d3e7980471 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperInstrumentRegistryEntry.java @@ -0,0 +1,118 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.PaperRegistries; +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.RegistryBuilderFactory; +import io.papermc.paper.registry.TypedKey; +import io.papermc.paper.registry.data.util.Conversions; +import io.papermc.paper.registry.holder.PaperRegistryHolders; +import io.papermc.paper.registry.holder.RegistryHolder; +import java.util.function.Consumer; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.item.Instrument; +import org.bukkit.MusicInstrument; +import org.bukkit.Sound; +import org.checkerframework.checker.index.qual.Positive; +import org.jspecify.annotations.Nullable; + +import static io.papermc.paper.registry.data.util.Checks.asArgument; +import static io.papermc.paper.registry.data.util.Checks.asArgumentMinExclusive; +import static io.papermc.paper.registry.data.util.Checks.asConfigured; + +public class PaperInstrumentRegistryEntry implements InstrumentRegistryEntry { + + protected final Conversions conversions; + protected @Nullable Holder soundEvent; + protected @Nullable Float useDuration; + protected @Nullable Float range; + protected @Nullable Component description; + + public PaperInstrumentRegistryEntry(final Conversions conversions, final @Nullable Instrument internal) { + this.conversions = conversions; + + if (internal == null) { + return; + } + this.soundEvent = internal.soundEvent(); + this.useDuration = internal.useDuration(); + this.range = internal.range(); + this.description = internal.description(); + } + + @Override + public RegistryHolder soundEvent() { + final Holder current = asConfigured(this.soundEvent, "soundEvent"); + return PaperRegistryHolders.create(current, e -> new PaperSoundEventRegistryEntry(this.conversions, e)); + } + + @Override + public @Positive float duration() { + return asConfigured(this.useDuration, "useDuration"); + } + + @Override + public @Positive float range() { + return asConfigured(this.range, "range"); + } + + @Override + public net.kyori.adventure.text.Component description() { + return this.conversions.asAdventure(asConfigured(this.description, "description")); + } + + public static final class PaperBuilder extends PaperInstrumentRegistryEntry implements Builder, PaperRegistryBuilder { + + public PaperBuilder(final Conversions conversions, final @Nullable Instrument internal) { + super(conversions, internal); + } + + @Override + public Builder soundEvent(final TypedKey soundEvent) { + this.soundEvent = this.conversions.getReferenceHolder(PaperRegistries.toNms(asArgument(soundEvent, "soundEvent"))); + return this; + } + + @Override + public Builder soundEvent(final Consumer> soundEvent) { + this.soundEvent = this.conversions.createHolderFromBuilder(Registries.SOUND_EVENT, asArgument(soundEvent, "soundEvent")); + return this; + } + + @Override + public Builder soundEvent(final RegistryHolder soundEvent) { + this.soundEvent = PaperRegistryHolders.convert(soundEvent, this.conversions); + return this; + } + + @Override + public Builder duration(final @Positive float duration) { + this.useDuration = asArgumentMinExclusive(duration, "useDuration", 0); + return this; + } + + @Override + public Builder range(final @Positive float range) { + this.range = asArgumentMinExclusive(range, "range", 0); + return this; + } + + @Override + public Builder description(final net.kyori.adventure.text.Component description) { + this.description = this.conversions.asVanilla(asArgument(description, "description")); + return this; + } + + @Override + public Instrument build() { + return new Instrument( + asConfigured(this.soundEvent, "soundEvent"), + this.duration(), + this.range(), + asConfigured(this.description, "description") + ); + } + } +}