azalea_registry/
lib.rs

1#![doc = include_str!("../README.md")]
2
3// The contents of the macros below are generated in
4// codegen/lib/code/registry.py, though the rest of the file isn't
5// auto-generated (so you can add doc comments to the registry enums if you
6// want).
7
8pub 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::{AzBuf, AzBufVar, BufReadError};
20#[cfg(feature = "serde")]
21use serde::Serialize;
22use simdnbt::{FromNbtTag, borrow::NbtTag};
23
24use crate::identifier::Identifier;
25
26// TODO: remove this next update
27macro_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: AzBuf + 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/// A registry that might not be present.
67///
68/// This is transmitted as a single varint in the protocol.
69#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
70pub struct OptionalRegistry<T: Registry>(pub Option<T>);
71
72impl<T: Registry> AzBuf 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    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
83        match &self.0 {
84            None => 0u32.azalea_write_var(buf),
85            Some(value) => (value.to_u32() + 1).azalea_write_var(buf),
86        }
87    }
88}
89
90/// A registry that will either take an ID or a resource location.
91#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
92pub enum CustomRegistry<D: Registry, C: AzBuf> {
93    Direct(D),
94    Custom(C),
95}
96
97impl<D: Registry, C: AzBuf> AzBuf for CustomRegistry<D, C> {
98    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
99        let direct_registry = OptionalRegistry::<D>::azalea_read(buf)?;
100        if let Some(direct_registry) = direct_registry.0 {
101            return Ok(CustomRegistry::Direct(direct_registry));
102        }
103        Ok(CustomRegistry::Custom(C::azalea_read(buf)?))
104    }
105    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
106        match self {
107            CustomRegistry::Direct(direct_registry) => {
108                // write the id + 1
109                (direct_registry.to_u32() + 1).azalea_write_var(buf)
110            }
111            CustomRegistry::Custom(custom_registry) => {
112                // write 0, then the custom registry
113                0u32.azalea_write_var(buf)?;
114                custom_registry.azalea_write(buf)
115            }
116        }
117    }
118}
119
120#[derive(Clone, PartialEq)]
121pub enum HolderSet<D: Registry, Identifier: AzBuf> {
122    Direct {
123        contents: Vec<D>,
124    },
125    Named {
126        key: Identifier,
127        contents: Vec<Identifier>,
128    },
129}
130impl<D: Registry, Identifier: AzBuf> AzBuf for HolderSet<D, Identifier> {
131    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
132        let size = i32::azalea_read_var(buf)?.wrapping_sub(1);
133        if size == -1 {
134            let key = Identifier::azalea_read(buf)?;
135            Ok(Self::Named {
136                key,
137                contents: Vec::new(),
138            })
139        } else {
140            let mut contents = Vec::new();
141            for _ in 0..size {
142                contents.push(D::azalea_read(buf)?);
143            }
144            Ok(Self::Direct { contents })
145        }
146    }
147    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
148        match self {
149            Self::Direct { contents } => {
150                (contents.len() as i32 + 1).azalea_write_var(buf)?;
151                for item in contents {
152                    item.azalea_write(buf)?;
153                }
154            }
155            Self::Named { key, contents: _ } => {
156                0i32.azalea_write_var(buf)?;
157                key.azalea_write(buf)?;
158            }
159        }
160        Ok(())
161    }
162}
163impl<D: Registry + Debug, Identifier: AzBuf + Debug> Debug for HolderSet<D, Identifier> {
164    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165        match self {
166            Self::Direct { contents } => f.debug_list().entries(contents).finish(),
167            Self::Named { key, contents } => f
168                .debug_struct("Named")
169                .field("key", key)
170                .field("contents", contents)
171                .finish(),
172        }
173    }
174}
175impl<D: Registry, Identifier: AzBuf> From<Vec<D>> for HolderSet<D, Identifier> {
176    fn from(contents: Vec<D>) -> Self {
177        Self::Direct { contents }
178    }
179}
180#[cfg(feature = "serde")]
181impl<D: Registry + Serialize, Identifier: AzBuf + Serialize> Serialize
182    for HolderSet<D, Identifier>
183{
184    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
185    where
186        S: serde::Serializer,
187    {
188        match self {
189            Self::Direct { contents } => {
190                if contents.len() == 1 {
191                    contents[0].serialize(serializer)
192                } else {
193                    contents.serialize(serializer)
194                }
195            }
196            Self::Named { key, contents: _ } => key.serialize(serializer),
197        }
198    }
199}
200impl<D: Registry, Identifier: AzBuf> Default for HolderSet<D, Identifier> {
201    fn default() -> Self {
202        Self::Direct {
203            contents: Vec::new(),
204        }
205    }
206}
207
208/// A reference to either a registry or a custom value (usually something with
209/// an `Identifier`).
210pub enum Holder<R: Registry, Direct: AzBuf> {
211    Reference(R),
212    Direct(Direct),
213}
214impl<R: Registry, Direct: AzBuf> AzBuf for Holder<R, Direct> {
215    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
216        let id = u32::azalea_read_var(buf)?;
217        if id == 0 {
218            Ok(Self::Direct(Direct::azalea_read(buf)?))
219        } else {
220            let id = id - 1;
221            let Some(value) = R::from_u32(id) else {
222                return Err(BufReadError::UnexpectedEnumVariant { id: id as i32 });
223            };
224            Ok(Self::Reference(value))
225        }
226    }
227    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
228        match self {
229            Self::Reference(value) => (value.to_u32() + 1).azalea_write_var(buf),
230            Self::Direct(value) => {
231                0u32.azalea_write_var(buf)?;
232                value.azalea_write(buf)
233            }
234        }
235    }
236}
237impl<R: Registry + Debug, Direct: AzBuf + Debug> Debug for Holder<R, Direct> {
238    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239        match self {
240            Self::Reference(value) => f.debug_tuple("Reference").field(value).finish(),
241            Self::Direct(value) => f.debug_tuple("Direct").field(value).finish(),
242        }
243    }
244}
245impl<R: Registry + Clone, Direct: AzBuf + Clone> Clone for Holder<R, Direct> {
246    fn clone(&self) -> Self {
247        match self {
248            Self::Reference(value) => Self::Reference(*value),
249            Self::Direct(value) => Self::Direct(value.clone()),
250        }
251    }
252}
253impl<R: Registry + PartialEq, Direct: AzBuf + PartialEq> PartialEq for Holder<R, Direct> {
254    fn eq(&self, other: &Self) -> bool {
255        match (self, other) {
256            (Self::Reference(a), Self::Reference(b)) => a == b,
257            (Self::Direct(a), Self::Direct(b)) => a == b,
258            _ => false,
259        }
260    }
261}
262impl<R: Registry + Default, Direct: AzBuf> Default for Holder<R, Direct> {
263    fn default() -> Self {
264        Self::Reference(R::default())
265    }
266}
267#[cfg(feature = "serde")]
268impl<R: Registry + Serialize, Direct: AzBuf + Serialize> Serialize for Holder<R, Direct> {
269    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
270    where
271        S: serde::Serializer,
272    {
273        match self {
274            Self::Reference(value) => value.serialize(serializer),
275            Self::Direct(value) => value.serialize(serializer),
276        }
277    }
278}
279
280impl<R: Registry + FromNbtTag, Direct: AzBuf + FromNbtTag> FromNbtTag for Holder<R, Direct> {
281    fn from_nbt_tag(tag: NbtTag) -> Option<Self> {
282        if let Some(reference) = R::from_nbt_tag(tag) {
283            return Some(Self::Reference(reference));
284        };
285        Direct::from_nbt_tag(tag).map(Self::Direct)
286    }
287}
288
289/// A registry which has its values decided by the server in the
290/// `ClientboundRegistryData` packet.
291///
292/// These can be resolved into their actual values with
293/// `ResolvableDataRegistry` from azalea-core.
294pub trait DataRegistry: AzBuf + PartialEq + PartialOrd + Ord + Copy + Hash {
295    const NAME: &'static str;
296    type Key: DataRegistryKey;
297
298    fn protocol_id(&self) -> u32;
299    fn new_raw(id: u32) -> Self;
300}
301pub trait DataRegistryKey {
302    type Borrow<'a>: DataRegistryKeyRef<'a>;
303
304    fn from_ident(ident: Identifier) -> Self;
305    fn into_ident(self) -> Identifier;
306}
307pub trait DataRegistryKeyRef<'a> {
308    type Owned: DataRegistryKey;
309
310    fn to_owned(self) -> Self::Owned;
311    fn from_ident(ident: &'a Identifier) -> Self;
312    fn into_ident(self) -> Identifier;
313}
314impl<T: DataRegistry> Registry for T {
315    fn from_u32(value: u32) -> Option<Self> {
316        Some(Self::new_raw(value))
317    }
318
319    fn to_u32(&self) -> u32 {
320        self.protocol_id()
321    }
322}