Skip to content

Commit d182c26

Browse files
committed
Add registry builders for SoundEvent and JukeboxSong
1 parent d0d0efe commit d182c26

File tree

13 files changed

+408
-1
lines changed

13 files changed

+408
-1
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package io.papermc.paper.registry.data;
2+
3+
4+
import io.papermc.paper.registry.RegistryBuilder;
5+
import io.papermc.paper.registry.TypedKey;
6+
import io.papermc.paper.util.Either;
7+
import java.util.function.Consumer;
8+
import net.kyori.adventure.text.Component;
9+
import org.bukkit.JukeboxSong;
10+
import org.bukkit.Sound;
11+
import org.checkerframework.checker.index.qual.Positive;
12+
import org.jetbrains.annotations.ApiStatus;
13+
import org.jetbrains.annotations.Contract;
14+
import org.jetbrains.annotations.Range;
15+
16+
/**
17+
* A data-centric version-specific registry entry for the {@link JukeboxSong} type.
18+
*/
19+
@ApiStatus.Experimental
20+
@ApiStatus.NonExtendable
21+
public interface JukeboxSongRegistryEntry {
22+
23+
Either<TypedKey<Sound>, SoundEventRegistryEntry> soundEvent();
24+
25+
Component description();
26+
27+
@Positive float lengthInSeconds();
28+
29+
@Range(from = 0, to = 15) int comparatorOutput();
30+
31+
/**
32+
* A mutable builder for the {@link JukeboxSongRegistryEntry} plugins may change in applicable registry events.
33+
* <p>
34+
* The following values are required for each builder:
35+
* <ul>
36+
* <li>
37+
* {@link #soundEvent(TypedKey)} or {@link #soundEvent(Consumer)}
38+
* </li>
39+
* <li>{@link #description(Component)}</li>
40+
* <li>{@link #lengthInSeconds(float)}</li>
41+
* <li>{@link #comparatorOutput(int)}</li>
42+
* </ul>
43+
*/
44+
@ApiStatus.Experimental
45+
@ApiStatus.NonExtendable
46+
interface Builder extends JukeboxSongRegistryEntry, RegistryBuilder<JukeboxSong> {
47+
48+
@Contract(value = "_ -> this", mutates = "this")
49+
Builder soundEvent(TypedKey<Sound> soundEvent);
50+
51+
@Contract(value = "_ -> this", mutates = "this")
52+
Builder soundEvent(Consumer<? super SoundEventRegistryEntry.Builder> soundEvent);
53+
54+
@Contract(value = "_ -> this", mutates = "this")
55+
Builder description(Component description);
56+
57+
@Contract(value = "_ -> this", mutates = "this")
58+
Builder lengthInSeconds(@Positive float lengthInSeconds);
59+
60+
@Contract(value = "_ -> this", mutates = "this")
61+
Builder comparatorOutput(@Range(from = 0, to = 15) int comparatorOutput);
62+
}
63+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package io.papermc.paper.registry.data;
2+
3+
import io.papermc.paper.registry.RegistryBuilder;
4+
import net.kyori.adventure.key.Key;
5+
import org.bukkit.Sound;
6+
import org.jetbrains.annotations.ApiStatus;
7+
import org.jetbrains.annotations.Contract;
8+
import org.jspecify.annotations.Nullable;
9+
10+
/**
11+
* A data-centric version-specific registry entry for the {@link Sound} type.
12+
*/
13+
@ApiStatus.Experimental
14+
@ApiStatus.NonExtendable
15+
public interface SoundEventRegistryEntry {
16+
17+
@Contract(pure = true)
18+
Key location();
19+
20+
@Contract(pure = true)
21+
@Nullable Float fixedRange();
22+
23+
/**
24+
* A mutable builder for the {@link SoundEventRegistryEntry} plugins may change in applicable registry events.
25+
* <p>
26+
* The following values are required for each builder:
27+
* <ul>
28+
* <li>{@link #location(Key)}</li>
29+
* </ul>
30+
*/
31+
@ApiStatus.Experimental
32+
@ApiStatus.NonExtendable
33+
interface Builder extends SoundEventRegistryEntry, RegistryBuilder<Sound> {
34+
35+
@Contract(value = "_ -> this", mutates = "this")
36+
Builder location(Key location);
37+
38+
@Contract(value = "_ -> this", mutates = "this")
39+
Builder fixedRange(@Nullable Float fixedRange);
40+
}
41+
}

paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import io.papermc.paper.registry.RegistryKey;
44
import io.papermc.paper.registry.data.EnchantmentRegistryEntry;
55
import io.papermc.paper.registry.data.GameEventRegistryEntry;
6+
import io.papermc.paper.registry.data.JukeboxSongRegistryEntry;
67
import io.papermc.paper.registry.data.PaintingVariantRegistryEntry;
78
import org.bukkit.Art;
89
import org.bukkit.GameEvent;
10+
import org.bukkit.JukeboxSong;
911
import org.bukkit.enchantments.Enchantment;
1012
import org.jetbrains.annotations.ApiStatus;
1113
import org.jspecify.annotations.NullMarked;
@@ -23,6 +25,7 @@ public final class RegistryEvents {
2325
public static final RegistryEventProvider<GameEvent, GameEventRegistryEntry.Builder> GAME_EVENT = create(RegistryKey.GAME_EVENT);
2426
public static final RegistryEventProvider<Enchantment, EnchantmentRegistryEntry.Builder> ENCHANTMENT = create(RegistryKey.ENCHANTMENT);
2527
public static final RegistryEventProvider<Art, PaintingVariantRegistryEntry.Builder> PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT);
28+
public static final RegistryEventProvider<JukeboxSong, JukeboxSongRegistryEntry.Builder> JUKEBOX_SONG = create(RegistryKey.JUKEBOX_SONG);
2629

2730
private RegistryEvents() {
2831
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package io.papermc.paper.util;
2+
3+
import java.util.Optional;
4+
import org.jetbrains.annotations.Contract;
5+
import org.jspecify.annotations.NullMarked;
6+
7+
@NullMarked
8+
public sealed interface Either<L, R> permits Either.Left, Either.Right {
9+
10+
@Contract(value = "_ -> new", pure = true)
11+
static <L, R> Either.Left<L, R> left(final L value) {
12+
return new EitherLeft<>(value);
13+
}
14+
15+
@Contract(value = "_ -> new", pure = true)
16+
static <L, R> Either.Right<L, R> right(final R value) {
17+
return new EitherRight<>(value);
18+
}
19+
20+
Optional<L> left();
21+
22+
Optional<R> right();
23+
24+
sealed interface Left<L, R> extends Either<L, R> permits EitherLeft {
25+
L value();
26+
27+
@Override
28+
default Optional<L> left() {
29+
return Optional.of(this.value());
30+
}
31+
32+
@Override
33+
default Optional<R> right() {
34+
return Optional.empty();
35+
}
36+
}
37+
38+
sealed interface Right<L, R> extends Either<L, R> permits EitherRight {
39+
R value();
40+
41+
@Override
42+
default Optional<L> left() {
43+
return Optional.empty();
44+
}
45+
46+
@Override
47+
default Optional<R> right() {
48+
return Optional.of(this.value());
49+
}
50+
}
51+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.papermc.paper.util;
2+
3+
import org.jetbrains.annotations.ApiStatus;
4+
import org.jspecify.annotations.NullMarked;
5+
6+
@ApiStatus.Internal
7+
@NullMarked
8+
record EitherLeft<L, R>(L value) implements Either.Left<L, R> {
9+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package io.papermc.paper.util;
2+
3+
public record EitherRight<L, R>(R value) implements Either.Right<L, R> {
4+
}

paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.papermc.paper.datacomponent.PaperDataComponentType;
77
import io.papermc.paper.registry.data.PaperEnchantmentRegistryEntry;
88
import io.papermc.paper.registry.data.PaperGameEventRegistryEntry;
9+
import io.papermc.paper.registry.data.PaperJukeboxSongRegistryEntry;
910
import io.papermc.paper.registry.data.PaperPaintingVariantRegistryEntry;
1011
import io.papermc.paper.registry.entry.RegistryEntry;
1112
import io.papermc.paper.registry.tag.TagKey;
@@ -105,7 +106,7 @@ public final class PaperRegistries {
105106
start(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE).craft(DamageType.class, CraftDamageType::new).build().delayed(),
106107
start(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT).craft(Wolf.Variant.class, CraftWolf.CraftVariant::new).build().delayed(),
107108
start(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT).craft(Enchantment.class, CraftEnchantment::new).serializationUpdater(FieldRename.ENCHANTMENT_RENAME).writable(PaperEnchantmentRegistryEntry.PaperBuilder::new).delayed(),
108-
start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).build().delayed(),
109+
start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).writable(PaperJukeboxSongRegistryEntry.Builder::new).delayed(),
109110
start(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN).craft(PatternType.class, CraftPatternType::new).build().delayed(),
110111
start(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT).craft(Art.class, CraftArt::new).writable(PaperPaintingVariantRegistryEntry.PaperBuilder::new).delayed(),
111112
start(Registries.INSTRUMENT, RegistryKey.INSTRUMENT).craft(MusicInstrument.class, CraftMusicInstrument::new).build().delayed(),
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package io.papermc.paper.registry.data;
2+
3+
import io.papermc.paper.registry.PaperRegistries;
4+
import io.papermc.paper.registry.PaperRegistryBuilder;
5+
import io.papermc.paper.registry.TypedKey;
6+
import io.papermc.paper.registry.data.util.Conversions;
7+
import io.papermc.paper.util.Either;
8+
import java.util.OptionalInt;
9+
import java.util.function.Consumer;
10+
import net.minecraft.core.Holder;
11+
import net.minecraft.network.chat.Component;
12+
import net.minecraft.sounds.SoundEvent;
13+
import net.minecraft.world.item.JukeboxSong;
14+
import org.bukkit.Sound;
15+
import org.checkerframework.checker.index.qual.Positive;
16+
import org.jetbrains.annotations.Range;
17+
import org.jspecify.annotations.Nullable;
18+
19+
import static io.papermc.paper.registry.data.util.Checks.asArgument;
20+
import static io.papermc.paper.registry.data.util.Checks.asArgumentMinExclusive;
21+
import static io.papermc.paper.registry.data.util.Checks.asArgumentRange;
22+
import static io.papermc.paper.registry.data.util.Checks.asConfigured;
23+
24+
public class PaperJukeboxSongRegistryEntry implements JukeboxSongRegistryEntry {
25+
26+
protected final Conversions conversions;
27+
protected @Nullable Holder<SoundEvent> soundEvent;
28+
protected @Nullable Component description;
29+
protected @Nullable Float lengthInSeconds;
30+
protected OptionalInt comparatorOutput = OptionalInt.empty();
31+
32+
public PaperJukeboxSongRegistryEntry(final Conversions conversions, final @Nullable JukeboxSong internal) {
33+
this.conversions = conversions;
34+
35+
if (internal == null) {
36+
return;
37+
}
38+
this.soundEvent = internal.soundEvent();
39+
this.description = internal.description();
40+
this.lengthInSeconds = internal.lengthInSeconds();
41+
this.comparatorOutput = OptionalInt.of(internal.comparatorOutput());
42+
}
43+
44+
@Override
45+
public Either<TypedKey<Sound>, SoundEventRegistryEntry> soundEvent() {
46+
final Holder<SoundEvent> current = asConfigured(this.soundEvent, "soundEvent");
47+
return current.unwrap().map(
48+
l -> Either.left(PaperRegistries.fromNms(l)),
49+
r -> Either.right(new PaperSoundEventRegistryEntry(this.conversions, r))
50+
);
51+
}
52+
53+
@Override
54+
public net.kyori.adventure.text.Component description() {
55+
return this.conversions.asAdventure(asConfigured(this.description, "description"));
56+
}
57+
58+
@Override
59+
public float lengthInSeconds() {
60+
return asConfigured(this.lengthInSeconds, "lengthInSeconds");
61+
}
62+
63+
@Override
64+
public int comparatorOutput() {
65+
return asConfigured(this.comparatorOutput, "comparatorOutput");
66+
}
67+
68+
public static final class Builder extends PaperJukeboxSongRegistryEntry implements JukeboxSongRegistryEntry.Builder, PaperRegistryBuilder<JukeboxSong, org.bukkit.JukeboxSong> {
69+
70+
public Builder(final Conversions conversions, final @Nullable JukeboxSong internal) {
71+
super(conversions, internal);
72+
}
73+
74+
@Override
75+
public JukeboxSongRegistryEntry.Builder soundEvent(final TypedKey<Sound> soundEvent) {
76+
this.soundEvent = this.conversions.getReferenceHolder(PaperRegistries.toNms(asArgument(soundEvent, "soundEvent")));
77+
return this;
78+
}
79+
80+
@Override
81+
public JukeboxSongRegistryEntry.Builder soundEvent(final Consumer<? super SoundEventRegistryEntry.Builder> soundEvent) {
82+
final PaperSoundEventRegistryEntry.Builder builder = new PaperSoundEventRegistryEntry.Builder(this.conversions, null);
83+
asArgument(soundEvent, "soundEvent").accept(builder);
84+
this.soundEvent = Holder.direct(builder.build());
85+
return this;
86+
}
87+
88+
@Override
89+
public JukeboxSongRegistryEntry.Builder description(final net.kyori.adventure.text.Component description) {
90+
this.description = this.conversions.asVanilla(asArgument(description, "description"));
91+
return this;
92+
}
93+
94+
@Override
95+
public JukeboxSongRegistryEntry.Builder lengthInSeconds(final @Positive float lengthInSeconds) {
96+
this.lengthInSeconds = asArgumentMinExclusive(lengthInSeconds, "lengthInSeconds", 0);
97+
return this;
98+
}
99+
100+
@Override
101+
public JukeboxSongRegistryEntry.Builder comparatorOutput(final @Range(from = 0, to = 15) int comparatorOutput) {
102+
this.comparatorOutput = OptionalInt.of(asArgumentRange(comparatorOutput, "comparatorOutput", 0, 15));
103+
return this;
104+
}
105+
106+
@Override
107+
public JukeboxSong build() {
108+
return new JukeboxSong(
109+
asConfigured(this.soundEvent, "soundEvent"),
110+
asConfigured(this.description, "description"),
111+
this.lengthInSeconds(),
112+
this.comparatorOutput()
113+
);
114+
}
115+
}
116+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package io.papermc.paper.registry.data;
2+
3+
import io.papermc.paper.adventure.PaperAdventure;
4+
import io.papermc.paper.registry.PaperRegistryBuilder;
5+
import io.papermc.paper.registry.data.util.Conversions;
6+
import java.util.Optional;
7+
import net.kyori.adventure.key.Key;
8+
import net.minecraft.resources.ResourceLocation;
9+
import net.minecraft.sounds.SoundEvent;
10+
import org.bukkit.Sound;
11+
import org.jspecify.annotations.Nullable;
12+
13+
import static io.papermc.paper.registry.data.util.Checks.asArgument;
14+
import static io.papermc.paper.registry.data.util.Checks.asConfigured;
15+
16+
/**
17+
* Not actually used for modifying {@link net.minecraft.core.registries.Registries#SOUND_EVENT}
18+
* but for creating direct holders for other registries and direct {@link org.bukkit.craftbukkit.CraftSound}s.
19+
*/
20+
public class PaperSoundEventRegistryEntry implements SoundEventRegistryEntry {
21+
22+
protected final Conversions conversions;
23+
protected @Nullable ResourceLocation location;
24+
protected @Nullable Float fixedRange;
25+
26+
public PaperSoundEventRegistryEntry(final Conversions conversions, final @Nullable SoundEvent soundEvent) {
27+
this.conversions = conversions;
28+
if (soundEvent == null) {
29+
return;
30+
}
31+
32+
this.location = soundEvent.location();
33+
this.fixedRange = soundEvent.fixedRange().orElse(null);
34+
}
35+
36+
@Override
37+
public Key location() {
38+
return PaperAdventure.asAdventure(asConfigured(this.location, "location"));
39+
}
40+
41+
@Override
42+
public @Nullable Float fixedRange() {
43+
return this.fixedRange;
44+
}
45+
46+
public static final class Builder extends PaperSoundEventRegistryEntry implements SoundEventRegistryEntry.Builder, PaperRegistryBuilder<SoundEvent, Sound> {
47+
48+
public Builder(final Conversions conversions, final @Nullable SoundEvent soundEvent) {
49+
super(conversions, soundEvent);
50+
}
51+
52+
@Override
53+
public SoundEventRegistryEntry.Builder location(final Key location) {
54+
this.location = PaperAdventure.asVanilla(asArgument(location, "location"));
55+
return this;
56+
}
57+
58+
@Override
59+
public SoundEventRegistryEntry.Builder fixedRange(final @Nullable Float fixedRange) {
60+
this.fixedRange = fixedRange;
61+
return this;
62+
}
63+
64+
@Override
65+
public SoundEvent build() {
66+
return new SoundEvent(asConfigured(this.location, "location"), Optional.ofNullable(this.fixedRange));
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)