From d182c26bcff4fa9e05eb0a4391b05dda08ad1886 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Mon, 23 Dec 2024 22:09:31 -0800 Subject: [PATCH] Add registry builders for SoundEvent and JukeboxSong --- .../data/JukeboxSongRegistryEntry.java | 63 ++++++++++ .../data/SoundEventRegistryEntry.java | 41 +++++++ .../paper/registry/event/RegistryEvents.java | 3 + .../java/io/papermc/paper/util/Either.java | 51 ++++++++ .../io/papermc/paper/util/EitherLeft.java | 9 ++ .../io/papermc/paper/util/EitherRight.java | 4 + .../paper/registry/PaperRegistries.java | 3 +- .../data/PaperJukeboxSongRegistryEntry.java | 116 ++++++++++++++++++ .../data/PaperSoundEventRegistryEntry.java | 69 +++++++++++ .../paper/registry/data/util/Checks.java | 7 ++ .../paper/registry/data/util/Conversions.java | 5 + .../io/papermc/testplugin/TestPlugin.java | 19 +++ .../testplugin/TestPluginBootstrap.java | 19 +++ 13 files changed, 408 insertions(+), 1 deletion(-) create mode 100644 paper-api/src/main/java/io/papermc/paper/registry/data/JukeboxSongRegistryEntry.java create mode 100644 paper-api/src/main/java/io/papermc/paper/registry/data/SoundEventRegistryEntry.java create mode 100644 paper-api/src/main/java/io/papermc/paper/util/Either.java create mode 100644 paper-api/src/main/java/io/papermc/paper/util/EitherLeft.java create mode 100644 paper-api/src/main/java/io/papermc/paper/util/EitherRight.java create mode 100644 paper-server/src/main/java/io/papermc/paper/registry/data/PaperJukeboxSongRegistryEntry.java create mode 100644 paper-server/src/main/java/io/papermc/paper/registry/data/PaperSoundEventRegistryEntry.java diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/JukeboxSongRegistryEntry.java b/paper-api/src/main/java/io/papermc/paper/registry/data/JukeboxSongRegistryEntry.java new file mode 100644 index 0000000000..3e64bdeb5b --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/JukeboxSongRegistryEntry.java @@ -0,0 +1,63 @@ +package io.papermc.paper.registry.data; + + +import io.papermc.paper.registry.RegistryBuilder; +import io.papermc.paper.registry.TypedKey; +import io.papermc.paper.util.Either; +import java.util.function.Consumer; +import net.kyori.adventure.text.Component; +import org.bukkit.JukeboxSong; +import org.bukkit.Sound; +import org.checkerframework.checker.index.qual.Positive; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Range; + +/** + * A data-centric version-specific registry entry for the {@link JukeboxSong} type. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface JukeboxSongRegistryEntry { + + Either, SoundEventRegistryEntry> soundEvent(); + + Component description(); + + @Positive float lengthInSeconds(); + + @Range(from = 0, to = 15) int comparatorOutput(); + + /** + * A mutable builder for the {@link JukeboxSongRegistryEntry} plugins may change in applicable registry events. + *

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

+ */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends JukeboxSongRegistryEntry, RegistryBuilder { + + @Contract(value = "_ -> this", mutates = "this") + Builder soundEvent(TypedKey soundEvent); + + @Contract(value = "_ -> this", mutates = "this") + Builder soundEvent(Consumer soundEvent); + + @Contract(value = "_ -> this", mutates = "this") + Builder description(Component description); + + @Contract(value = "_ -> this", mutates = "this") + Builder lengthInSeconds(@Positive float lengthInSeconds); + + @Contract(value = "_ -> this", mutates = "this") + Builder comparatorOutput(@Range(from = 0, to = 15) int comparatorOutput); + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/SoundEventRegistryEntry.java b/paper-api/src/main/java/io/papermc/paper/registry/data/SoundEventRegistryEntry.java new file mode 100644 index 0000000000..4eb377a3c3 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/SoundEventRegistryEntry.java @@ -0,0 +1,41 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.RegistryBuilder; +import net.kyori.adventure.key.Key; +import org.bukkit.Sound; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jspecify.annotations.Nullable; + +/** + * A data-centric version-specific registry entry for the {@link Sound} type. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface SoundEventRegistryEntry { + + @Contract(pure = true) + Key location(); + + @Contract(pure = true) + @Nullable Float fixedRange(); + + /** + * A mutable builder for the {@link SoundEventRegistryEntry} plugins may change in applicable registry events. + *

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

    + *
  • {@link #location(Key)}
  • + *
+ */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends SoundEventRegistryEntry, RegistryBuilder { + + @Contract(value = "_ -> this", mutates = "this") + Builder location(Key location); + + @Contract(value = "_ -> this", mutates = "this") + Builder fixedRange(@Nullable Float fixedRange); + } +} 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 40deffbd09..51343f8550 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 @@ -3,9 +3,11 @@ package io.papermc.paper.registry.event; import io.papermc.paper.registry.RegistryKey; import io.papermc.paper.registry.data.EnchantmentRegistryEntry; import io.papermc.paper.registry.data.GameEventRegistryEntry; +import io.papermc.paper.registry.data.JukeboxSongRegistryEntry; import io.papermc.paper.registry.data.PaintingVariantRegistryEntry; import org.bukkit.Art; import org.bukkit.GameEvent; +import org.bukkit.JukeboxSong; import org.bukkit.enchantments.Enchantment; import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; @@ -23,6 +25,7 @@ public final class RegistryEvents { public static final RegistryEventProvider GAME_EVENT = create(RegistryKey.GAME_EVENT); public static final RegistryEventProvider ENCHANTMENT = create(RegistryKey.ENCHANTMENT); public static final RegistryEventProvider PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT); + public static final RegistryEventProvider JUKEBOX_SONG = create(RegistryKey.JUKEBOX_SONG); private RegistryEvents() { } diff --git a/paper-api/src/main/java/io/papermc/paper/util/Either.java b/paper-api/src/main/java/io/papermc/paper/util/Either.java new file mode 100644 index 0000000000..bdc1174169 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/util/Either.java @@ -0,0 +1,51 @@ +package io.papermc.paper.util; + +import java.util.Optional; +import org.jetbrains.annotations.Contract; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public sealed interface Either permits Either.Left, Either.Right { + + @Contract(value = "_ -> new", pure = true) + static Either.Left left(final L value) { + return new EitherLeft<>(value); + } + + @Contract(value = "_ -> new", pure = true) + static Either.Right right(final R value) { + return new EitherRight<>(value); + } + + Optional left(); + + Optional right(); + + sealed interface Left extends Either permits EitherLeft { + L value(); + + @Override + default Optional left() { + return Optional.of(this.value()); + } + + @Override + default Optional right() { + return Optional.empty(); + } + } + + sealed interface Right extends Either permits EitherRight { + R value(); + + @Override + default Optional left() { + return Optional.empty(); + } + + @Override + default Optional right() { + return Optional.of(this.value()); + } + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/util/EitherLeft.java b/paper-api/src/main/java/io/papermc/paper/util/EitherLeft.java new file mode 100644 index 0000000000..a5bb921158 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/util/EitherLeft.java @@ -0,0 +1,9 @@ +package io.papermc.paper.util; + +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +@ApiStatus.Internal +@NullMarked +record EitherLeft(L value) implements Either.Left { +} diff --git a/paper-api/src/main/java/io/papermc/paper/util/EitherRight.java b/paper-api/src/main/java/io/papermc/paper/util/EitherRight.java new file mode 100644 index 0000000000..0b14391b3d --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/util/EitherRight.java @@ -0,0 +1,4 @@ +package io.papermc.paper.util; + +public record EitherRight(R value) implements Either.Right { +} 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 a41356e136..c1e0d34ebb 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 @@ -6,6 +6,7 @@ import io.papermc.paper.datacomponent.DataComponentTypes; import io.papermc.paper.datacomponent.PaperDataComponentType; import io.papermc.paper.registry.data.PaperEnchantmentRegistryEntry; import io.papermc.paper.registry.data.PaperGameEventRegistryEntry; +import io.papermc.paper.registry.data.PaperJukeboxSongRegistryEntry; import io.papermc.paper.registry.data.PaperPaintingVariantRegistryEntry; import io.papermc.paper.registry.entry.RegistryEntry; import io.papermc.paper.registry.tag.TagKey; @@ -105,7 +106,7 @@ public final class PaperRegistries { 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).serializationUpdater(FieldRename.ENCHANTMENT_RENAME).writable(PaperEnchantmentRegistryEntry.PaperBuilder::new).delayed(), - start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).build().delayed(), + start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).writable(PaperJukeboxSongRegistryEntry.Builder::new).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).writable(PaperPaintingVariantRegistryEntry.PaperBuilder::new).delayed(), start(Registries.INSTRUMENT, RegistryKey.INSTRUMENT).craft(MusicInstrument.class, CraftMusicInstrument::new).build().delayed(), diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/PaperJukeboxSongRegistryEntry.java b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperJukeboxSongRegistryEntry.java new file mode 100644 index 0000000000..eda1b113ab --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperJukeboxSongRegistryEntry.java @@ -0,0 +1,116 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.PaperRegistries; +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.TypedKey; +import io.papermc.paper.registry.data.util.Conversions; +import io.papermc.paper.util.Either; +import java.util.OptionalInt; +import java.util.function.Consumer; +import net.minecraft.core.Holder; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.item.JukeboxSong; +import org.bukkit.Sound; +import org.checkerframework.checker.index.qual.Positive; +import org.jetbrains.annotations.Range; +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.asArgumentRange; +import static io.papermc.paper.registry.data.util.Checks.asConfigured; + +public class PaperJukeboxSongRegistryEntry implements JukeboxSongRegistryEntry { + + protected final Conversions conversions; + protected @Nullable Holder soundEvent; + protected @Nullable Component description; + protected @Nullable Float lengthInSeconds; + protected OptionalInt comparatorOutput = OptionalInt.empty(); + + public PaperJukeboxSongRegistryEntry(final Conversions conversions, final @Nullable JukeboxSong internal) { + this.conversions = conversions; + + if (internal == null) { + return; + } + this.soundEvent = internal.soundEvent(); + this.description = internal.description(); + this.lengthInSeconds = internal.lengthInSeconds(); + this.comparatorOutput = OptionalInt.of(internal.comparatorOutput()); + } + + @Override + public Either, SoundEventRegistryEntry> soundEvent() { + final Holder current = asConfigured(this.soundEvent, "soundEvent"); + return current.unwrap().map( + l -> Either.left(PaperRegistries.fromNms(l)), + r -> Either.right(new PaperSoundEventRegistryEntry(this.conversions, r)) + ); + } + + @Override + public net.kyori.adventure.text.Component description() { + return this.conversions.asAdventure(asConfigured(this.description, "description")); + } + + @Override + public float lengthInSeconds() { + return asConfigured(this.lengthInSeconds, "lengthInSeconds"); + } + + @Override + public int comparatorOutput() { + return asConfigured(this.comparatorOutput, "comparatorOutput"); + } + + public static final class Builder extends PaperJukeboxSongRegistryEntry implements JukeboxSongRegistryEntry.Builder, PaperRegistryBuilder { + + public Builder(final Conversions conversions, final @Nullable JukeboxSong internal) { + super(conversions, internal); + } + + @Override + public JukeboxSongRegistryEntry.Builder soundEvent(final TypedKey soundEvent) { + this.soundEvent = this.conversions.getReferenceHolder(PaperRegistries.toNms(asArgument(soundEvent, "soundEvent"))); + return this; + } + + @Override + public JukeboxSongRegistryEntry.Builder soundEvent(final Consumer soundEvent) { + final PaperSoundEventRegistryEntry.Builder builder = new PaperSoundEventRegistryEntry.Builder(this.conversions, null); + asArgument(soundEvent, "soundEvent").accept(builder); + this.soundEvent = Holder.direct(builder.build()); + return this; + } + + @Override + public JukeboxSongRegistryEntry.Builder description(final net.kyori.adventure.text.Component description) { + this.description = this.conversions.asVanilla(asArgument(description, "description")); + return this; + } + + @Override + public JukeboxSongRegistryEntry.Builder lengthInSeconds(final @Positive float lengthInSeconds) { + this.lengthInSeconds = asArgumentMinExclusive(lengthInSeconds, "lengthInSeconds", 0); + return this; + } + + @Override + public JukeboxSongRegistryEntry.Builder comparatorOutput(final @Range(from = 0, to = 15) int comparatorOutput) { + this.comparatorOutput = OptionalInt.of(asArgumentRange(comparatorOutput, "comparatorOutput", 0, 15)); + return this; + } + + @Override + public JukeboxSong build() { + return new JukeboxSong( + asConfigured(this.soundEvent, "soundEvent"), + asConfigured(this.description, "description"), + this.lengthInSeconds(), + this.comparatorOutput() + ); + } + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/PaperSoundEventRegistryEntry.java b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperSoundEventRegistryEntry.java new file mode 100644 index 0000000000..2a657db726 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperSoundEventRegistryEntry.java @@ -0,0 +1,69 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.adventure.PaperAdventure; +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.data.util.Conversions; +import java.util.Optional; +import net.kyori.adventure.key.Key; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; +import org.bukkit.Sound; +import org.jspecify.annotations.Nullable; + +import static io.papermc.paper.registry.data.util.Checks.asArgument; +import static io.papermc.paper.registry.data.util.Checks.asConfigured; + +/** + * Not actually used for modifying {@link net.minecraft.core.registries.Registries#SOUND_EVENT} + * but for creating direct holders for other registries and direct {@link org.bukkit.craftbukkit.CraftSound}s. + */ +public class PaperSoundEventRegistryEntry implements SoundEventRegistryEntry { + + protected final Conversions conversions; + protected @Nullable ResourceLocation location; + protected @Nullable Float fixedRange; + + public PaperSoundEventRegistryEntry(final Conversions conversions, final @Nullable SoundEvent soundEvent) { + this.conversions = conversions; + if (soundEvent == null) { + return; + } + + this.location = soundEvent.location(); + this.fixedRange = soundEvent.fixedRange().orElse(null); + } + + @Override + public Key location() { + return PaperAdventure.asAdventure(asConfigured(this.location, "location")); + } + + @Override + public @Nullable Float fixedRange() { + return this.fixedRange; + } + + public static final class Builder extends PaperSoundEventRegistryEntry implements SoundEventRegistryEntry.Builder, PaperRegistryBuilder { + + public Builder(final Conversions conversions, final @Nullable SoundEvent soundEvent) { + super(conversions, soundEvent); + } + + @Override + public SoundEventRegistryEntry.Builder location(final Key location) { + this.location = PaperAdventure.asVanilla(asArgument(location, "location")); + return this; + } + + @Override + public SoundEventRegistryEntry.Builder fixedRange(final @Nullable Float fixedRange) { + this.fixedRange = fixedRange; + return this; + } + + @Override + public SoundEvent build() { + return new SoundEvent(asConfigured(this.location, "location"), Optional.ofNullable(this.fixedRange)); + } + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/util/Checks.java b/paper-server/src/main/java/io/papermc/paper/registry/data/util/Checks.java index 9d61fad398..0c335f2252 100644 --- a/paper-server/src/main/java/io/papermc/paper/registry/data/util/Checks.java +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/util/Checks.java @@ -40,6 +40,13 @@ public final class Checks { return value; } + public static float asArgumentMinExclusive(final float value, final String field, final float min) { + if (value <= min) { + throw new IllegalArgumentException("argument " + field + " must be [" + min + ",+inf)"); + } + return value; + } + private Checks() { } } diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/util/Conversions.java b/paper-server/src/main/java/io/papermc/paper/registry/data/util/Conversions.java index b1710da835..1c05168702 100644 --- a/paper-server/src/main/java/io/papermc/paper/registry/data/util/Conversions.java +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/util/Conversions.java @@ -5,6 +5,7 @@ import com.mojang.serialization.JavaOps; import io.papermc.paper.adventure.WrapperAwareSerializer; import java.util.Optional; import net.kyori.adventure.text.Component; +import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.RegistryOps; @@ -46,6 +47,10 @@ public class Conversions { return this.lookup; } + public Holder.Reference getReferenceHolder(final ResourceKey key) { + return this.lookup.lookup(key.registryKey()).orElseThrow().getter().getOrThrow(key); + } + @Contract("null -> null; !null -> !null") public net.minecraft.network.chat.@Nullable Component asVanilla(final @Nullable Component adventure) { if (adventure == null) return null; diff --git a/test-plugin/src/main/java/io/papermc/testplugin/TestPlugin.java b/test-plugin/src/main/java/io/papermc/testplugin/TestPlugin.java index 671c37fa40..f76184e80c 100644 --- a/test-plugin/src/main/java/io/papermc/testplugin/TestPlugin.java +++ b/test-plugin/src/main/java/io/papermc/testplugin/TestPlugin.java @@ -1,6 +1,16 @@ package io.papermc.testplugin; +import io.papermc.paper.datacomponent.DataComponentTypes; +import io.papermc.paper.datacomponent.item.JukeboxPlayable; +import io.papermc.paper.event.player.ChatEvent; +import io.papermc.paper.registry.RegistryAccess; +import io.papermc.paper.registry.RegistryKey; +import org.bukkit.JukeboxSong; +import org.bukkit.Material; +import org.bukkit.Registry; +import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; public final class TestPlugin extends JavaPlugin implements Listener { @@ -12,4 +22,13 @@ public final class TestPlugin extends JavaPlugin implements Listener { // io.papermc.testplugin.brigtests.Registration.registerViaOnEnable(this); } + @EventHandler + public void onEvent(ChatEvent event) { + final ItemStack stick = new ItemStack(Material.STICK); + final Registry registry = RegistryAccess.registryAccess().getRegistry(RegistryKey.JUKEBOX_SONG); + final JukeboxSong orThrow = registry.getOrThrow(TestPluginBootstrap.NEW); + stick.setData(DataComponentTypes.JUKEBOX_PLAYABLE, JukeboxPlayable.jukeboxPlayable(orThrow)); + event.getPlayer().getInventory().addItem(stick); + } + } diff --git a/test-plugin/src/main/java/io/papermc/testplugin/TestPluginBootstrap.java b/test-plugin/src/main/java/io/papermc/testplugin/TestPluginBootstrap.java index fe2b287b25..3b80624619 100644 --- a/test-plugin/src/main/java/io/papermc/testplugin/TestPluginBootstrap.java +++ b/test-plugin/src/main/java/io/papermc/testplugin/TestPluginBootstrap.java @@ -2,13 +2,32 @@ package io.papermc.testplugin; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.bootstrap.PluginBootstrap; +import io.papermc.paper.registry.TypedKey; +import io.papermc.paper.registry.event.RegistryEvents; +import io.papermc.paper.registry.keys.JukeboxSongKeys; +import io.papermc.paper.registry.keys.SoundEventKeys; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import org.bukkit.JukeboxSong; import org.jetbrains.annotations.NotNull; public class TestPluginBootstrap implements PluginBootstrap { + static final TypedKey NEW = JukeboxSongKeys.create(Key.key("test:test")); + @Override public void bootstrap(@NotNull BootstrapContext context) { // io.papermc.testplugin.brigtests.Registration.registerViaBootstrap(context); + + context.getLifecycleManager().registerEventHandler(RegistryEvents.JUKEBOX_SONG.freeze(), event -> { + // Do something with the event + event.registry().register(NEW, b -> { + b.comparatorOutput(2) + .description(Component.text("EPIC CUSTOM SOUND SONG")) + .lengthInSeconds(2) + .soundEvent(sb -> sb.location(SoundEventKeys.BLOCK_STONE_BUTTON_CLICK_ON)); + }); + }); } }