steel_registry/
jukebox_song.rs1use rustc_hash::FxHashMap;
2use std::io::{Cursor, Result, Write};
3
4use simdnbt::owned::{NbtCompound, NbtTag};
5use simdnbt::{FromNbtTag, ToNbtTag};
6use steel_utils::Identifier;
7use steel_utils::hash::{ComponentHasher, HashComponent};
8use steel_utils::nbt::NbtNumeric as _;
9use steel_utils::serial::{ReadFrom, WriteTo};
10use text_components::TextComponent;
11
12use crate::sound_event::SoundEventHolder;
13use crate::{REGISTRY, RegistryExt, RegistryHolderEntry, RegistryTags};
14
15#[derive(Debug, Clone)]
16pub struct JukeboxSongValue {
17 pub sound_event: SoundEventHolder,
18 pub description: TextComponent,
19 pub length_in_seconds: f32,
20 pub comparator_output: i32,
21}
22
23impl PartialEq for JukeboxSongValue {
24 fn eq(&self, other: &Self) -> bool {
25 self.sound_event == other.sound_event
26 && self.description == other.description
27 && ((self.length_in_seconds.is_nan() && other.length_in_seconds.is_nan())
28 || self.length_in_seconds.to_bits() == other.length_in_seconds.to_bits())
29 && self.comparator_output == other.comparator_output
30 }
31}
32
33impl WriteTo for JukeboxSongValue {
34 fn write(&self, writer: &mut impl Write) -> Result<()> {
35 self.sound_event.write(writer)?;
36 self.description.write(writer)?;
37 self.length_in_seconds.write(writer)?;
38 steel_utils::codec::VarInt(self.comparator_output).write(writer)
39 }
40}
41
42impl ReadFrom for JukeboxSongValue {
43 fn read(data: &mut Cursor<&[u8]>) -> Result<Self> {
44 Ok(Self {
45 sound_event: SoundEventHolder::read(data)?,
46 description: TextComponent::read(data)?,
47 length_in_seconds: f32::read(data)?,
48 comparator_output: steel_utils::codec::VarInt::read(data)?.0,
49 })
50 }
51}
52
53impl ToNbtTag for JukeboxSongValue {
54 fn to_nbt_tag(self) -> NbtTag {
55 let mut compound = NbtCompound::new();
56 compound.insert("sound_event", self.sound_event.to_nbt_tag());
57 compound.insert("description", self.description.to_codec_nbt());
58 compound.insert("length_in_seconds", self.length_in_seconds);
59 compound.insert("comparator_output", self.comparator_output);
60 NbtTag::Compound(compound)
61 }
62}
63
64impl FromNbtTag for JukeboxSongValue {
65 fn from_nbt_tag(tag: simdnbt::borrow::NbtTag) -> Option<Self> {
66 let compound = tag.compound()?;
67 let length_in_seconds = compound.get("length_in_seconds")?.codec_f32()?;
68 let comparator_output = compound.get("comparator_output")?.codec_i32()?;
69 if !length_in_seconds.is_finite()
70 || length_in_seconds <= 0.0
71 || !(0..=15).contains(&comparator_output)
72 {
73 return None;
74 }
75 Some(Self {
76 sound_event: SoundEventHolder::from_nbt_tag(compound.get("sound_event")?)?,
77 description: TextComponent::from_nbt(&compound.get("description")?.to_owned())?,
78 length_in_seconds,
79 comparator_output,
80 })
81 }
82}
83
84impl HashComponent for JukeboxSongValue {
85 fn hash_component(&self, hasher: &mut ComponentHasher) {
86 self.clone().to_nbt_tag().hash_component(hasher);
87 }
88}
89
90#[derive(Debug)]
92pub struct JukeboxSong {
93 pub key: Identifier,
94 value: JukeboxSongValue,
95}
96
97impl JukeboxSong {
98 #[must_use]
99 pub const fn new(key: Identifier, value: JukeboxSongValue) -> Self {
100 Self { key, value }
101 }
102 #[must_use]
103 pub const fn value(&self) -> &JukeboxSongValue {
104 &self.value
105 }
106}
107
108impl ToNbtTag for &JukeboxSong {
109 fn to_nbt_tag(self) -> NbtTag {
110 self.value.clone().to_nbt_tag()
111 }
112}
113
114pub type JukeboxSongRef = &'static JukeboxSong;
115
116pub struct JukeboxSongRegistry {
117 jukebox_songs_by_id: Vec<JukeboxSongRef>,
118 jukebox_songs_by_key: FxHashMap<Identifier, usize>,
119 tags: RegistryTags,
120 allows_registering: bool,
121}
122
123impl JukeboxSongRegistry {
124 #[must_use]
125 pub fn new() -> Self {
126 Self {
127 jukebox_songs_by_id: Vec::new(),
128 jukebox_songs_by_key: FxHashMap::default(),
129 tags: RegistryTags::default(),
130 allows_registering: true,
131 }
132 }
133}
134
135crate::impl_standard_methods!(
136 JukeboxSongRegistry,
137 JukeboxSongRef,
138 jukebox_songs_by_id,
139 jukebox_songs_by_key,
140 allows_registering
141);
142
143crate::impl_registry!(
144 JukeboxSongRegistry,
145 JukeboxSong,
146 jukebox_songs_by_id,
147 jukebox_songs_by_key,
148 jukebox_songs
149);
150crate::impl_tagged_registry!(JukeboxSongRegistry, jukebox_songs_by_key, "jukebox song");
151
152impl RegistryHolderEntry for JukeboxSong {
153 type Value = JukeboxSongValue;
154 const REGISTRY_NAME: &'static str = "jukebox song";
155 fn holder_value(&self) -> &Self::Value {
156 &self.value
157 }
158 fn holder_by_id(id: usize) -> Option<&'static Self> {
159 REGISTRY.jukebox_songs.by_id(id)
160 }
161 fn holder_by_key(key: &Identifier) -> Option<&'static Self> {
162 REGISTRY.jukebox_songs.by_key(key)
163 }
164}