Add registry builder for Instrument (#12682)

Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
This commit is contained in:
Pedro
2025-06-30 15:33:02 -04:00
committed by GitHub
parent 6e021c8272
commit 5661fbbab9
8 changed files with 315 additions and 15 deletions

View File

@@ -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<RegistryBuilderFactory<MusicInstrument, ? extends InstrumentRegistryEntry.Builder>> value);
}

View File

@@ -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<Sound, SoundEventRegistryEntry> 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.
* <p>
* The following values are required for each builder:
* <ul>
* <li>
* {@link #soundEvent(TypedKey)}, {@link #soundEvent(Consumer)} or {@link #soundEvent(RegistryHolder)}
* </li>
* <li>{@link #duration(float)}</li>
* <li>{@link #range(float)}</li>
* <li>{@link #description(Component)}</li>
* </ul>
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends InstrumentRegistryEntry, RegistryBuilder<MusicInstrument> {
/**
* Sets the sound event for this instrument to a sound event present
* in the {@link io.papermc.paper.registry.RegistryKey#SOUND_EVENT} registry.
* <p>This will override both {@link #soundEvent(Consumer)} and {@link #soundEvent(RegistryHolder)}</p>
*
* @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<Sound> soundEvent);
/**
* Sets the sound event for this instrument to a new sound event.
* <p>This will override both {@link #soundEvent(TypedKey)} and {@link #soundEvent(RegistryHolder)}</p>
*
* @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<RegistryBuilderFactory<Sound, ? extends SoundEventRegistryEntry.Builder>> soundEvent);
/**
* Sets the sound event for this instrument.
* <p>This will override both {@link #soundEvent(Consumer)} and {@link #soundEvent(TypedKey)}</p>
*
* @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<Sound, SoundEventRegistryEntry> 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);
}
}

View File

@@ -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<JukeboxSong, JukeboxSongRegistryEntry.Builder> JUKEBOX_SONG = create(RegistryKey.JUKEBOX_SONG);
public static final RegistryEventProvider<PatternType, BannerPatternRegistryEntry.Builder> BANNER_PATTERN = create(RegistryKey.BANNER_PATTERN);
public static final RegistryEventProvider<Art, PaintingVariantRegistryEntry.Builder> PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT);
public static final RegistryEventProvider<MusicInstrument, InstrumentRegistryEntry.Builder> INSTRUMENT = create(RegistryKey.INSTRUMENT);
public static final RegistryEventProvider<Cat.Type, CatTypeRegistryEntry.Builder> CAT_VARIANT = create(RegistryKey.CAT_VARIANT);
public static final RegistryEventProvider<Frog.Variant, FrogVariantRegistryEntry.Builder> FROG_VARIANT = create(RegistryKey.FROG_VARIANT);
public static final RegistryEventProvider<Chicken.Variant, ChickenVariantRegistryEntry.Builder> CHICKEN_VARIANT = create(RegistryKey.CHICKEN_VARIANT);

View File

@@ -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<RegistryBuilderFactory<MusicInstrument, ? extends InstrumentRegistryEntry.Builder>> 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<MusicInstrument> 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();

View File

@@ -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"),

View File

@@ -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),

View File

@@ -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<RegistryBuilderFactory<MusicInstrument, ? extends InstrumentRegistryEntry.Builder>> value) {
return Conversions.global().createApiInstanceFromBuilder(Registries.INSTRUMENT, value);
}
}

View File

@@ -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> 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<Sound, SoundEventRegistryEntry> soundEvent() {
final Holder<SoundEvent> 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<Instrument, MusicInstrument> {
public PaperBuilder(final Conversions conversions, final @Nullable Instrument internal) {
super(conversions, internal);
}
@Override
public Builder soundEvent(final TypedKey<Sound> soundEvent) {
this.soundEvent = this.conversions.getReferenceHolder(PaperRegistries.toNms(asArgument(soundEvent, "soundEvent")));
return this;
}
@Override
public Builder soundEvent(final Consumer<RegistryBuilderFactory<Sound, ? extends SoundEventRegistryEntry.Builder>> soundEvent) {
this.soundEvent = this.conversions.createHolderFromBuilder(Registries.SOUND_EVENT, asArgument(soundEvent, "soundEvent"));
return this;
}
@Override
public Builder soundEvent(final RegistryHolder<Sound, SoundEventRegistryEntry> 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")
);
}
}
}