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::{AzBuf, AzBufVar, 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: 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#[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#[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 (direct_registry.to_u32() + 1).azalea_write_var(buf)
110 }
111 CustomRegistry::Custom(custom_registry) => {
112 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
208pub 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
289pub 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}