1#![doc = include_str!("../README.md")]
2
3pub mod builtin;
9pub mod data;
10pub mod identifier;
11pub mod tags;
12
13use std::{
14 fmt::{self, Debug},
15 hash::Hash,
16 io::{self, Cursor, Write},
17};
18
19use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError};
20#[cfg(feature = "serde")]
21use serde::Serialize;
22use simdnbt::{FromNbtTag, borrow::NbtTag};
23
24use crate::identifier::Identifier;
25
26macro_rules! define_deprecated_builtin {
28 ($($r:ident) *) => {
29 $(
30 #[doc(hidden)]
31 #[deprecated = concat!("moved to `azalea_registry::builtin::", stringify!($r), "`")]
32 pub type $r = builtin::$r;
33 )*
34 };
35}
36define_deprecated_builtin!(Activity Attribute BlockEntityKind BlockPredicateKind ChunkStatus CommandArgumentKind CustomStat EntityKind FloatProviderKind Fluid GameEvent HeightProviderKind IntProviderKind LootConditionKind LootFunctionKind LootNbtProviderKind LootNumberProviderKind LootPoolEntryKind LootScoreProviderKind MemoryModuleKind MobEffect ParticleKind PointOfInterestKind PosRuleTest PositionSourceKind Potion RecipeSerializer RecipeKind RuleTest SensorKind SoundEvent StatKind VillagerProfession VillagerKind WorldgenBiomeSource WorldgenBlockStateProviderKind WorldgenCarver WorldgenChunkGenerator WorldgenDensityFunctionKind WorldgenFeature WorldgenFeatureSizeKind WorldgenFoliagePlacerKind WorldgenMaterialCondition WorldgenMaterialRule WorldgenPlacementModifierKind WorldgenRootPlacerKind WorldgenStructurePiece WorldgenStructurePlacement WorldgenStructurePoolElement WorldgenStructureProcessor WorldgenStructureKind WorldgenTreeDecoratorKind WorldgenTrunkPlacerKind RuleBlockEntityModifier CreativeModeTab MenuKind WorldgenPoolAliasBinding TriggerKind NumberFormatKind DataComponentKind EntitySubPredicateKind MapDecorationKind EnchantmentEffectComponentKind EnchantmentEntityEffectKind EnchantmentLevelBasedValueKind EnchantmentLocationBasedEffectKind EnchantmentProviderKind EnchantmentValueEffectKind DecoratedPotPattern ConsumeEffectKind RecipeBookCategory RecipeDisplay SlotDisplay TicketKind TestEnvironmentDefinitionKind TestFunction TestInstanceKind DataComponentPredicateKind SpawnConditionKind DialogBodyKind DialogKind InputControlKind DialogActionKind DebugSubscription IncomingRpcMethods OutgoingRpcMethods AttributeKind EnvironmentAttribute GameRule PermissionCheckKind PermissionKind SlotSourceKind);
37macro_rules! define_deprecated_data {
38 ($($r:ident) *) => {
39 $(
40 #[doc(hidden)]
41 #[deprecated = concat!("moved to `azalea_registry::data::", stringify!($r), "`")]
42 pub type $r = data::$r;
43 )*
44 };
45}
46define_deprecated_data!(Enchantment DamageKind Dialog WolfSoundVariant CowVariant ChickenVariant FrogVariant CatVariant PigVariant PaintingVariant WolfVariant ZombieNautilusVariant Biome);
47
48#[doc(hidden)]
49#[deprecated = "renamed to `azalea_registry::builtin::ItemKind`"]
50pub type Item = builtin::ItemKind;
51#[doc(hidden)]
52#[deprecated = "renamed to `azalea_registry::builtin::BlockKind`"]
53pub type Block = builtin::BlockKind;
54#[doc(hidden)]
55#[deprecated = "renamed to `azalea_registry::data::DimensionKind`"]
56pub type DimensionType = data::DimensionKind;
57
58pub trait Registry: AzaleaRead + AzaleaWrite + PartialEq + PartialOrd + Ord + Copy + Hash
59where
60 Self: Sized,
61{
62 fn from_u32(value: u32) -> Option<Self>;
63 fn to_u32(&self) -> u32;
64}
65
66#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
70pub struct OptionalRegistry<T: Registry>(pub Option<T>);
71
72impl<T: Registry> AzaleaRead for OptionalRegistry<T> {
73 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
74 Ok(OptionalRegistry(match u32::azalea_read_var(buf)? {
75 0 => None,
76 value => Some(
77 T::from_u32(value - 1)
78 .ok_or(BufReadError::UnexpectedEnumVariant { id: value as i32 })?,
79 ),
80 }))
81 }
82}
83impl<T: Registry> AzaleaWrite for OptionalRegistry<T> {
84 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
85 match &self.0 {
86 None => 0u32.azalea_write_var(buf),
87 Some(value) => (value.to_u32() + 1).azalea_write_var(buf),
88 }
89 }
90}
91
92#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
94pub enum CustomRegistry<D: Registry, C: AzaleaRead + AzaleaWrite> {
95 Direct(D),
96 Custom(C),
97}
98
99impl<D: Registry, C: AzaleaRead + AzaleaWrite> AzaleaRead for CustomRegistry<D, C> {
100 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
101 let direct_registry = OptionalRegistry::<D>::azalea_read(buf)?;
102 if let Some(direct_registry) = direct_registry.0 {
103 return Ok(CustomRegistry::Direct(direct_registry));
104 }
105 Ok(CustomRegistry::Custom(C::azalea_read(buf)?))
106 }
107}
108impl<D: Registry, C: AzaleaRead + AzaleaWrite> AzaleaWrite for CustomRegistry<D, C> {
109 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
110 match self {
111 CustomRegistry::Direct(direct_registry) => {
112 (direct_registry.to_u32() + 1).azalea_write_var(buf)
114 }
115 CustomRegistry::Custom(custom_registry) => {
116 0u32.azalea_write_var(buf)?;
118 custom_registry.azalea_write(buf)
119 }
120 }
121 }
122}
123
124#[derive(Clone, PartialEq)]
125pub enum HolderSet<D: Registry, Identifier: AzaleaRead + AzaleaWrite> {
126 Direct {
127 contents: Vec<D>,
128 },
129 Named {
130 key: Identifier,
131 contents: Vec<Identifier>,
132 },
133}
134impl<D: Registry, Identifier: AzaleaRead + AzaleaWrite> AzaleaRead for HolderSet<D, Identifier> {
135 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
136 let size = i32::azalea_read_var(buf)? - 1;
137 if size == -1 {
138 let key = Identifier::azalea_read(buf)?;
139 Ok(Self::Named {
140 key,
141 contents: Vec::new(),
142 })
143 } else {
144 let mut contents = Vec::new();
145 for _ in 0..size {
146 contents.push(D::azalea_read(buf)?);
147 }
148 Ok(Self::Direct { contents })
149 }
150 }
151}
152impl<D: Registry, Identifier: AzaleaRead + AzaleaWrite> AzaleaWrite for HolderSet<D, Identifier> {
153 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
154 match self {
155 Self::Direct { contents } => {
156 (contents.len() as i32 + 1).azalea_write_var(buf)?;
157 for item in contents {
158 item.azalea_write(buf)?;
159 }
160 }
161 Self::Named { key, contents: _ } => {
162 0i32.azalea_write_var(buf)?;
163 key.azalea_write(buf)?;
164 }
165 }
166 Ok(())
167 }
168}
169impl<D: Registry + Debug, Identifier: AzaleaRead + AzaleaWrite + Debug> Debug
170 for HolderSet<D, Identifier>
171{
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 match self {
174 Self::Direct { contents } => f.debug_list().entries(contents).finish(),
175 Self::Named { key, contents } => f
176 .debug_struct("Named")
177 .field("key", key)
178 .field("contents", contents)
179 .finish(),
180 }
181 }
182}
183impl<D: Registry, Identifier: AzaleaRead + AzaleaWrite> From<Vec<D>> for HolderSet<D, Identifier> {
184 fn from(contents: Vec<D>) -> Self {
185 Self::Direct { contents }
186 }
187}
188#[cfg(feature = "serde")]
189impl<D: Registry + Serialize, Identifier: AzaleaRead + AzaleaWrite + Serialize> Serialize
190 for HolderSet<D, Identifier>
191{
192 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
193 where
194 S: serde::Serializer,
195 {
196 match self {
197 Self::Direct { contents } => {
198 if contents.len() == 1 {
199 contents[0].serialize(serializer)
200 } else {
201 contents.serialize(serializer)
202 }
203 }
204 Self::Named { key, contents: _ } => key.serialize(serializer),
205 }
206 }
207}
208impl<D: Registry, Identifier: AzaleaRead + AzaleaWrite> Default for HolderSet<D, Identifier> {
209 fn default() -> Self {
210 Self::Direct {
211 contents: Vec::new(),
212 }
213 }
214}
215
216pub enum Holder<R: Registry, Direct: AzaleaRead + AzaleaWrite> {
219 Reference(R),
220 Direct(Direct),
221}
222impl<R: Registry, Direct: AzaleaRead + AzaleaWrite> AzaleaRead for Holder<R, Direct> {
223 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
224 let id = u32::azalea_read_var(buf)?;
225 if id == 0 {
226 Ok(Self::Direct(Direct::azalea_read(buf)?))
227 } else {
228 let id = id - 1;
229 let Some(value) = R::from_u32(id) else {
230 return Err(BufReadError::UnexpectedEnumVariant { id: id as i32 });
231 };
232 Ok(Self::Reference(value))
233 }
234 }
235}
236impl<R: Registry, Direct: AzaleaRead + AzaleaWrite> AzaleaWrite for Holder<R, Direct> {
237 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
238 match self {
239 Self::Reference(value) => (value.to_u32() + 1).azalea_write_var(buf),
240 Self::Direct(value) => {
241 0u32.azalea_write_var(buf)?;
242 value.azalea_write(buf)
243 }
244 }
245 }
246}
247impl<R: Registry + Debug, Direct: AzaleaRead + AzaleaWrite + Debug> Debug for Holder<R, Direct> {
248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
249 match self {
250 Self::Reference(value) => f.debug_tuple("Reference").field(value).finish(),
251 Self::Direct(value) => f.debug_tuple("Direct").field(value).finish(),
252 }
253 }
254}
255impl<R: Registry + Clone, Direct: AzaleaRead + AzaleaWrite + Clone> Clone for Holder<R, Direct> {
256 fn clone(&self) -> Self {
257 match self {
258 Self::Reference(value) => Self::Reference(*value),
259 Self::Direct(value) => Self::Direct(value.clone()),
260 }
261 }
262}
263impl<R: Registry + PartialEq, Direct: AzaleaRead + AzaleaWrite + PartialEq> PartialEq
264 for Holder<R, Direct>
265{
266 fn eq(&self, other: &Self) -> bool {
267 match (self, other) {
268 (Self::Reference(a), Self::Reference(b)) => a == b,
269 (Self::Direct(a), Self::Direct(b)) => a == b,
270 _ => false,
271 }
272 }
273}
274impl<R: Registry + Default, Direct: AzaleaRead + AzaleaWrite> Default for Holder<R, Direct> {
275 fn default() -> Self {
276 Self::Reference(R::default())
277 }
278}
279#[cfg(feature = "serde")]
280impl<R: Registry + Serialize, Direct: AzaleaRead + AzaleaWrite + Serialize> Serialize
281 for Holder<R, Direct>
282{
283 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
284 where
285 S: serde::Serializer,
286 {
287 match self {
288 Self::Reference(value) => value.serialize(serializer),
289 Self::Direct(value) => value.serialize(serializer),
290 }
291 }
292}
293
294impl<
295 R: Registry + Serialize + FromNbtTag,
296 Direct: AzaleaRead + AzaleaWrite + Serialize + FromNbtTag,
297> FromNbtTag for Holder<R, Direct>
298{
299 fn from_nbt_tag(tag: NbtTag) -> Option<Self> {
300 if let Some(reference) = R::from_nbt_tag(tag) {
301 return Some(Self::Reference(reference));
302 };
303 Direct::from_nbt_tag(tag).map(Self::Direct)
304 }
305}
306
307pub trait DataRegistry:
313 AzaleaRead + AzaleaWrite + PartialEq + PartialOrd + Ord + Copy + Hash
314{
315 const NAME: &'static str;
316 type Key: DataRegistryKey;
317
318 fn protocol_id(&self) -> u32;
319 fn new_raw(id: u32) -> Self;
320}
321pub trait DataRegistryKey {
322 type Borrow<'a>: DataRegistryKeyRef<'a>;
323
324 fn into_ident(self) -> Identifier;
325}
326pub trait DataRegistryKeyRef<'a> {
327 type Owned: DataRegistryKey;
328
329 fn to_owned(self) -> Self::Owned;
330 fn from_ident(ident: &'a Identifier) -> Self;
331 fn into_ident(self) -> Identifier;
332}
333impl<T: DataRegistry> Registry for T {
334 fn from_u32(value: u32) -> Option<Self> {
335 Some(Self::new_raw(value))
336 }
337
338 fn to_u32(&self) -> u32 {
339 self.protocol_id()
340 }
341}