1use simdnbt::FromNbtTag as _;
6use steel_utils::{Identifier, nbt::NbtNumeric as _};
7use text_components::TextComponent;
8
9use super::component_data::ComponentData;
10use super::registry::DataComponentRegistry;
11pub use super::registry::DataComponentType;
12pub use crate::attribute::AttributeModifierOperation;
13pub use crate::equipment::{EquipmentSlot, EquipmentSlotGroup};
14
15pub use super::components::{
17 ArmorTrim, AttackRange, BannerPatternLayer, BannerPatternLayers, BeehiveOccupant, Bees,
18 BlockEntityData, BlockItemStateProperties, BlocksAttacks, BundleContents, ChargedProjectiles,
19 Consumable, CustomData, CustomModelData, DamageReduction, DamageResistant, DamageTypeComponent,
20 DeathProtection, DebugStickProperty, DebugStickState, DyedItemColor, Enchantable, EntityData,
21 Equippable, EquippableAllowedEntities, Filterable, FireworkExplosion, FireworkExplosionShape,
22 Fireworks, FoodProperties, GlobalPos, InstrumentComponent, InvalidEnchantableValue,
23 ItemAttributeModifierDisplay, ItemAttributeModifierEntry, ItemAttributeModifiers,
24 ItemContainerContents, ItemDamageFunction, ItemEnchantments, ItemLore, ItemLoreTooLong,
25 ItemUseAnimation, JukeboxPlayable, KineticWeapon, KineticWeaponCondition, LodestoneTracker,
26 MapDecorationEntry, MapDecorations, MapId, MapItemColor, MapPostProcessing,
27 OminousBottleAmplifier, PaintingVariantComponent, PiercingWeapon, PotDecorations,
28 PotionContents, ProvidesBannerPatterns, ProvidesTrimMaterial, Rarity, Recipes, Repairable,
29 SeededContainerLoot, SulfurCubeContent, SuspiciousStewEffect, SuspiciousStewEffects,
30 SwingAnimation, SwingAnimationType, Tool, ToolRule, ToolRuleBlocks, TooltipDisplay,
31 UseCooldown, UseEffects, UseRemainder, Weapon, WritableBookContent, WrittenBookContent,
32};
33pub use crate::ItemStackTemplate;
34pub use crate::cat_sound_variant::CatSoundVariant;
35pub use crate::cat_variant::CatVariant;
36pub use crate::chicken_sound_variant::ChickenSoundVariant;
37pub use crate::chicken_variant::ChickenVariant;
38pub use crate::cow_sound_variant::CowSoundVariant;
39pub use crate::cow_variant::CowVariant;
40pub use crate::frog_variant::FrogVariant;
41pub use crate::item_predicate::{AdventureModePredicate, BlockPredicate, ItemPredicate, LockCode};
42pub use crate::pig_sound_variant::PigSoundVariant;
43pub use crate::pig_variant::PigVariant;
44pub use crate::resolvable_profile::{
45 PartialProfile, PlayerModelType, PlayerSkinPatch, ProfileProperty, ResolvableProfile,
46 ResolvableProfileContents, StoredGameProfile,
47};
48pub use crate::sound_event::SoundEventHolder;
49pub use crate::villager_type::VillagerType;
50pub use crate::wolf_sound_variant::WolfSoundVariant;
51pub use crate::wolf_variant::WolfVariant;
52pub use crate::zombie_nautilus_variant::ZombieNautilusVariant;
53pub use crate::{
54 AxolotlVariant, DyeColor, FoxVariant, HorseVariant, LlamaVariant, MooshroomVariant,
55 ParrotVariant, RabbitVariant, RegistryReference, SalmonVariant, TropicalFishPattern,
56};
57
58pub const MAX_STACK_SIZE: DataComponentType<i32> =
59 DataComponentType::new(Identifier::vanilla_static("max_stack_size"));
60
61pub const MAX_DAMAGE: DataComponentType<i32> =
62 DataComponentType::new(Identifier::vanilla_static("max_damage"));
63
64pub const CUSTOM_NAME: DataComponentType<TextComponent> =
65 DataComponentType::new(Identifier::vanilla_static("custom_name"));
66
67pub const ITEM_NAME: DataComponentType<TextComponent> =
68 DataComponentType::new(Identifier::vanilla_static("item_name"));
69
70pub const DAMAGE: DataComponentType<i32> =
71 DataComponentType::new_ignoring_swap_animation(Identifier::vanilla_static("damage"));
72
73pub const REPAIR_COST: DataComponentType<i32> =
74 DataComponentType::new(Identifier::vanilla_static("repair_cost"));
75
76pub const UNBREAKABLE: DataComponentType<()> =
77 DataComponentType::new(Identifier::vanilla_static("unbreakable"));
78
79pub const TOOL: DataComponentType<Tool> =
80 DataComponentType::new(Identifier::vanilla_static("tool"));
81
82pub const WEAPON: DataComponentType<Weapon> =
83 DataComponentType::new(Identifier::vanilla_static("weapon"));
84
85pub const ATTACK_RANGE: DataComponentType<AttackRange> =
86 DataComponentType::new(Identifier::vanilla_static("attack_range"));
87
88pub const EQUIPPABLE: DataComponentType<Equippable> =
89 DataComponentType::new(Identifier::vanilla_static("equippable"));
90
91pub const GLIDER: DataComponentType<()> =
92 DataComponentType::new(Identifier::vanilla_static("glider"));
93
94pub const CREATIVE_SLOT_LOCK: DataComponentType<()> =
95 DataComponentType::new(Identifier::vanilla_static("creative_slot_lock"));
96
97pub const INTANGIBLE_PROJECTILE: DataComponentType<()> =
98 DataComponentType::new(Identifier::vanilla_static("intangible_projectile"));
99
100pub const ENCHANTMENT_GLINT_OVERRIDE: DataComponentType<bool> =
101 DataComponentType::new(Identifier::vanilla_static("enchantment_glint_override"));
102
103pub const POTION_DURATION_SCALE: DataComponentType<f32> =
104 DataComponentType::new(Identifier::vanilla_static("potion_duration_scale"));
105
106pub const CUSTOM_DATA: DataComponentType<CustomData> =
107 DataComponentType::new(Identifier::vanilla_static("custom_data"));
108
109pub const USE_EFFECTS: DataComponentType<UseEffects> =
110 DataComponentType::new(Identifier::vanilla_static("use_effects"));
111
112pub const MINIMUM_ATTACK_CHARGE: DataComponentType<f32> =
113 DataComponentType::new(Identifier::vanilla_static("minimum_attack_charge"));
114
115pub const DAMAGE_TYPE: DataComponentType<DamageTypeComponent> =
116 DataComponentType::new(Identifier::vanilla_static("damage_type"));
117
118pub const ITEM_MODEL: DataComponentType<Identifier> =
119 DataComponentType::new(Identifier::vanilla_static("item_model"));
120
121pub const LORE: DataComponentType<ItemLore> =
122 DataComponentType::new(Identifier::vanilla_static("lore"));
123
124pub const RARITY: DataComponentType<Rarity> =
125 DataComponentType::new(Identifier::vanilla_static("rarity"));
126
127pub const ENCHANTMENTS: DataComponentType<ItemEnchantments> =
128 DataComponentType::new(Identifier::vanilla_static("enchantments"));
129
130pub const CAN_PLACE_ON: DataComponentType<AdventureModePredicate> =
131 DataComponentType::new(Identifier::vanilla_static("can_place_on"));
132
133pub const CAN_BREAK: DataComponentType<AdventureModePredicate> =
134 DataComponentType::new(Identifier::vanilla_static("can_break"));
135
136pub const ATTRIBUTE_MODIFIERS: DataComponentType<ItemAttributeModifiers> =
137 DataComponentType::new(Identifier::vanilla_static("attribute_modifiers"));
138
139pub const CUSTOM_MODEL_DATA: DataComponentType<CustomModelData> =
140 DataComponentType::new(Identifier::vanilla_static("custom_model_data"));
141
142pub const TOOLTIP_DISPLAY: DataComponentType<TooltipDisplay> =
143 DataComponentType::new(Identifier::vanilla_static("tooltip_display"));
144
145pub const TOOLTIP_STYLE: DataComponentType<Identifier> =
146 DataComponentType::new(Identifier::vanilla_static("tooltip_style"));
147
148pub const NOTE_BLOCK_SOUND: DataComponentType<Identifier> =
149 DataComponentType::new(Identifier::vanilla_static("note_block_sound"));
150
151pub const FOOD: DataComponentType<FoodProperties> =
152 DataComponentType::new(Identifier::vanilla_static("food"));
153
154pub const CONSUMABLE: DataComponentType<Consumable> =
155 DataComponentType::new(Identifier::vanilla_static("consumable"));
156
157pub const USE_REMAINDER: DataComponentType<UseRemainder> =
158 DataComponentType::new(Identifier::vanilla_static("use_remainder"));
159
160pub const USE_COOLDOWN: DataComponentType<UseCooldown> =
161 DataComponentType::new(Identifier::vanilla_static("use_cooldown"));
162
163pub const DAMAGE_RESISTANT: DataComponentType<DamageResistant> =
164 DataComponentType::new(Identifier::vanilla_static("damage_resistant"));
165
166pub const ENCHANTABLE: DataComponentType<Enchantable> =
167 DataComponentType::new(Identifier::vanilla_static("enchantable"));
168
169pub const REPAIRABLE: DataComponentType<Repairable> =
170 DataComponentType::new(Identifier::vanilla_static("repairable"));
171
172pub const DEATH_PROTECTION: DataComponentType<DeathProtection> =
173 DataComponentType::new(Identifier::vanilla_static("death_protection"));
174
175pub const BLOCKS_ATTACKS: DataComponentType<BlocksAttacks> =
176 DataComponentType::new(Identifier::vanilla_static("blocks_attacks"));
177
178pub const PIERCING_WEAPON: DataComponentType<PiercingWeapon> =
179 DataComponentType::new(Identifier::vanilla_static("piercing_weapon"));
180
181pub const KINETIC_WEAPON: DataComponentType<KineticWeapon> =
182 DataComponentType::new(Identifier::vanilla_static("kinetic_weapon"));
183
184pub const SWING_ANIMATION: DataComponentType<SwingAnimation> =
185 DataComponentType::new(Identifier::vanilla_static("swing_animation"));
186
187pub const ADDITIONAL_TRADE_COST: DataComponentType<i32> =
188 DataComponentType::new(Identifier::vanilla_static("additional_trade_cost"));
189
190pub const STORED_ENCHANTMENTS: DataComponentType<ItemEnchantments> =
191 DataComponentType::new(Identifier::vanilla_static("stored_enchantments"));
192
193pub const DYE: DataComponentType<DyeColor> =
194 DataComponentType::new(Identifier::vanilla_static("dye"));
195
196pub const DYED_COLOR: DataComponentType<DyedItemColor> =
197 DataComponentType::new(Identifier::vanilla_static("dyed_color"));
198
199pub const MAP_COLOR: DataComponentType<MapItemColor> =
200 DataComponentType::new(Identifier::vanilla_static("map_color"));
201
202pub const MAP_ID: DataComponentType<MapId> =
203 DataComponentType::new(Identifier::vanilla_static("map_id"));
204
205pub const MAP_DECORATIONS: DataComponentType<MapDecorations> =
206 DataComponentType::new(Identifier::vanilla_static("map_decorations"));
207
208pub const MAP_POST_PROCESSING: DataComponentType<MapPostProcessing> =
209 DataComponentType::new(Identifier::vanilla_static("map_post_processing"));
210
211pub const CHARGED_PROJECTILES: DataComponentType<ChargedProjectiles> =
212 DataComponentType::new(Identifier::vanilla_static("charged_projectiles"));
213
214pub const BUNDLE_CONTENTS: DataComponentType<BundleContents> =
215 DataComponentType::new(Identifier::vanilla_static("bundle_contents"));
216
217pub const POTION_CONTENTS: DataComponentType<PotionContents> =
218 DataComponentType::new(Identifier::vanilla_static("potion_contents"));
219
220pub const SUSPICIOUS_STEW_EFFECTS: DataComponentType<SuspiciousStewEffects> =
221 DataComponentType::new(Identifier::vanilla_static("suspicious_stew_effects"));
222
223pub const WRITABLE_BOOK_CONTENT: DataComponentType<WritableBookContent> =
224 DataComponentType::new(Identifier::vanilla_static("writable_book_content"));
225
226pub const WRITTEN_BOOK_CONTENT: DataComponentType<WrittenBookContent> =
227 DataComponentType::new(Identifier::vanilla_static("written_book_content"));
228
229pub const TRIM: DataComponentType<ArmorTrim> =
230 DataComponentType::new(Identifier::vanilla_static("trim"));
231
232pub const DEBUG_STICK_STATE: DataComponentType<DebugStickState> =
233 DataComponentType::new(Identifier::vanilla_static("debug_stick_state"));
234
235pub const ENTITY_DATA: DataComponentType<EntityData> =
236 DataComponentType::new(Identifier::vanilla_static("entity_data"));
237
238pub const BUCKET_ENTITY_DATA: DataComponentType<CustomData> =
239 DataComponentType::new(Identifier::vanilla_static("bucket_entity_data"));
240
241pub const BLOCK_ENTITY_DATA: DataComponentType<BlockEntityData> =
242 DataComponentType::new(Identifier::vanilla_static("block_entity_data"));
243
244pub const INSTRUMENT: DataComponentType<InstrumentComponent> =
245 DataComponentType::new(Identifier::vanilla_static("instrument"));
246
247pub const PROVIDES_TRIM_MATERIAL: DataComponentType<ProvidesTrimMaterial> =
248 DataComponentType::new(Identifier::vanilla_static("provides_trim_material"));
249
250pub const OMINOUS_BOTTLE_AMPLIFIER: DataComponentType<OminousBottleAmplifier> =
251 DataComponentType::new(Identifier::vanilla_static("ominous_bottle_amplifier"));
252
253pub const JUKEBOX_PLAYABLE: DataComponentType<JukeboxPlayable> =
254 DataComponentType::new(Identifier::vanilla_static("jukebox_playable"));
255
256pub const PROVIDES_BANNER_PATTERNS: DataComponentType<ProvidesBannerPatterns> =
257 DataComponentType::new(Identifier::vanilla_static("provides_banner_patterns"));
258
259pub const RECIPES: DataComponentType<Recipes> =
260 DataComponentType::new(Identifier::vanilla_static("recipes"));
261
262pub const LODESTONE_TRACKER: DataComponentType<LodestoneTracker> =
263 DataComponentType::new(Identifier::vanilla_static("lodestone_tracker"));
264
265pub const FIREWORK_EXPLOSION: DataComponentType<FireworkExplosion> =
266 DataComponentType::new(Identifier::vanilla_static("firework_explosion"));
267
268pub const FIREWORKS: DataComponentType<Fireworks> =
269 DataComponentType::new(Identifier::vanilla_static("fireworks"));
270
271pub const PROFILE: DataComponentType<ResolvableProfile> =
272 DataComponentType::new(Identifier::vanilla_static("profile"));
273
274pub const BANNER_PATTERNS: DataComponentType<BannerPatternLayers> =
275 DataComponentType::new(Identifier::vanilla_static("banner_patterns"));
276
277pub const BASE_COLOR: DataComponentType<DyeColor> =
278 DataComponentType::new(Identifier::vanilla_static("base_color"));
279
280pub const POT_DECORATIONS: DataComponentType<PotDecorations> =
281 DataComponentType::new(Identifier::vanilla_static("pot_decorations"));
282
283pub const CONTAINER: DataComponentType<ItemContainerContents> =
284 DataComponentType::new(Identifier::vanilla_static("container"));
285
286pub const BLOCK_STATE: DataComponentType<BlockItemStateProperties> =
287 DataComponentType::new(Identifier::vanilla_static("block_state"));
288
289pub const BEES: DataComponentType<Bees> =
290 DataComponentType::new(Identifier::vanilla_static("bees"));
291
292pub const SULFUR_CUBE_CONTENT: DataComponentType<SulfurCubeContent> =
293 DataComponentType::new(Identifier::vanilla_static("sulfur_cube_content"));
294
295pub const LOCK: DataComponentType<LockCode> =
296 DataComponentType::new(Identifier::vanilla_static("lock"));
297
298pub const CONTAINER_LOOT: DataComponentType<SeededContainerLoot> =
299 DataComponentType::new(Identifier::vanilla_static("container_loot"));
300
301pub const BREAK_SOUND: DataComponentType<SoundEventHolder> =
302 DataComponentType::new(Identifier::vanilla_static("break_sound"));
303
304pub const VILLAGER_VARIANT: DataComponentType<RegistryReference<VillagerType>> =
306 DataComponentType::new(Identifier::vanilla_static("villager/variant"));
307
308pub const WOLF_VARIANT: DataComponentType<RegistryReference<WolfVariant>> =
309 DataComponentType::new(Identifier::vanilla_static("wolf/variant"));
310
311pub const WOLF_SOUND_VARIANT: DataComponentType<RegistryReference<WolfSoundVariant>> =
312 DataComponentType::new(Identifier::vanilla_static("wolf/sound_variant"));
313
314pub const WOLF_COLLAR: DataComponentType<DyeColor> =
315 DataComponentType::new(Identifier::vanilla_static("wolf/collar"));
316
317pub const FOX_VARIANT: DataComponentType<FoxVariant> =
318 DataComponentType::new(Identifier::vanilla_static("fox/variant"));
319
320pub const SALMON_SIZE: DataComponentType<SalmonVariant> =
321 DataComponentType::new(Identifier::vanilla_static("salmon/size"));
322
323pub const PARROT_VARIANT: DataComponentType<ParrotVariant> =
324 DataComponentType::new(Identifier::vanilla_static("parrot/variant"));
325
326pub const TROPICAL_FISH_PATTERN: DataComponentType<TropicalFishPattern> =
327 DataComponentType::new(Identifier::vanilla_static("tropical_fish/pattern"));
328
329pub const TROPICAL_FISH_BASE_COLOR: DataComponentType<DyeColor> =
330 DataComponentType::new(Identifier::vanilla_static("tropical_fish/base_color"));
331
332pub const TROPICAL_FISH_PATTERN_COLOR: DataComponentType<DyeColor> =
333 DataComponentType::new(Identifier::vanilla_static("tropical_fish/pattern_color"));
334
335pub const MOOSHROOM_VARIANT: DataComponentType<MooshroomVariant> =
336 DataComponentType::new(Identifier::vanilla_static("mooshroom/variant"));
337
338pub const RABBIT_VARIANT: DataComponentType<RabbitVariant> =
339 DataComponentType::new(Identifier::vanilla_static("rabbit/variant"));
340
341pub const PIG_VARIANT: DataComponentType<RegistryReference<PigVariant>> =
342 DataComponentType::new(Identifier::vanilla_static("pig/variant"));
343
344pub const PIG_SOUND_VARIANT: DataComponentType<RegistryReference<PigSoundVariant>> =
345 DataComponentType::new(Identifier::vanilla_static("pig/sound_variant"));
346
347pub const COW_VARIANT: DataComponentType<RegistryReference<CowVariant>> =
348 DataComponentType::new(Identifier::vanilla_static("cow/variant"));
349
350pub const COW_SOUND_VARIANT: DataComponentType<RegistryReference<CowSoundVariant>> =
351 DataComponentType::new(Identifier::vanilla_static("cow/sound_variant"));
352
353pub const CHICKEN_VARIANT: DataComponentType<RegistryReference<ChickenVariant>> =
354 DataComponentType::new(Identifier::vanilla_static("chicken/variant"));
355
356pub const CHICKEN_SOUND_VARIANT: DataComponentType<RegistryReference<ChickenSoundVariant>> =
357 DataComponentType::new(Identifier::vanilla_static("chicken/sound_variant"));
358
359pub const ZOMBIE_NAUTILUS_VARIANT: DataComponentType<RegistryReference<ZombieNautilusVariant>> =
360 DataComponentType::new(Identifier::vanilla_static("zombie_nautilus/variant"));
361
362pub const FROG_VARIANT: DataComponentType<RegistryReference<FrogVariant>> =
363 DataComponentType::new(Identifier::vanilla_static("frog/variant"));
364
365pub const HORSE_VARIANT: DataComponentType<HorseVariant> =
366 DataComponentType::new(Identifier::vanilla_static("horse/variant"));
367
368pub const PAINTING_VARIANT: DataComponentType<PaintingVariantComponent> =
369 DataComponentType::new(Identifier::vanilla_static("painting/variant"));
370
371pub const LLAMA_VARIANT: DataComponentType<LlamaVariant> =
372 DataComponentType::new(Identifier::vanilla_static("llama/variant"));
373
374pub const AXOLOTL_VARIANT: DataComponentType<AxolotlVariant> =
375 DataComponentType::new(Identifier::vanilla_static("axolotl/variant"));
376
377pub const CAT_VARIANT: DataComponentType<RegistryReference<CatVariant>> =
378 DataComponentType::new(Identifier::vanilla_static("cat/variant"));
379
380pub const CAT_SOUND_VARIANT: DataComponentType<RegistryReference<CatSoundVariant>> =
381 DataComponentType::new(Identifier::vanilla_static("cat/sound_variant"));
382
383pub const CAT_COLLAR: DataComponentType<DyeColor> =
384 DataComponentType::new(Identifier::vanilla_static("cat/collar"));
385
386pub const SHEEP_COLOR: DataComponentType<DyeColor> =
387 DataComponentType::new(Identifier::vanilla_static("sheep/color"));
388
389pub const SHULKER_COLOR: DataComponentType<DyeColor> =
390 DataComponentType::new(Identifier::vanilla_static("shulker/color"));
391
392fn varint_reader(cursor: &mut std::io::Cursor<&[u8]>) -> std::io::Result<ComponentData> {
394 use steel_utils::{codec::VarInt, serial::ReadFrom};
395 let value = VarInt::read(cursor)?;
396 Ok(ComponentData::new(value.0))
397}
398
399fn varint_writer(data: &ComponentData, writer: &mut Vec<u8>) -> std::io::Result<()> {
401 use steel_utils::{codec::VarInt, serial::WriteTo};
402 if let Some(v) = data.downcast_ref::<i32>() {
403 VarInt(*v).write(writer)
404 } else {
405 Err(std::io::Error::other("Component type mismatch"))
406 }
407}
408
409fn float_reader(cursor: &mut std::io::Cursor<&[u8]>) -> std::io::Result<ComponentData> {
410 use steel_utils::serial::ReadFrom;
411 Ok(ComponentData::new(f32::read(cursor)?))
412}
413
414fn float_writer(data: &ComponentData, writer: &mut Vec<u8>) -> std::io::Result<()> {
415 use steel_utils::serial::WriteTo;
416 let Some(value) = data.downcast_ref::<f32>() else {
417 return Err(std::io::Error::other("Component type mismatch"));
418 };
419 value.write(writer)
420}
421
422fn bool_reader(cursor: &mut std::io::Cursor<&[u8]>) -> std::io::Result<ComponentData> {
423 use steel_utils::serial::ReadFrom;
424 Ok(ComponentData::new(bool::read(cursor)?))
425}
426
427fn bool_writer(data: &ComponentData, writer: &mut Vec<u8>) -> std::io::Result<()> {
428 use steel_utils::serial::WriteTo;
429 let Some(value) = data.downcast_ref::<bool>() else {
430 return Err(std::io::Error::other("Component type mismatch"));
431 };
432 value.write(writer)
433}
434
435fn text_component_network_reader(
436 cursor: &mut std::io::Cursor<&[u8]>,
437) -> std::io::Result<ComponentData> {
438 use steel_utils::serial::ReadFrom as _;
439 TextComponent::read(cursor).map(ComponentData::new)
440}
441
442fn text_component_network_writer(
443 data: &ComponentData,
444 writer: &mut Vec<u8>,
445) -> std::io::Result<()> {
446 use steel_utils::serial::WriteTo as _;
447 let Some(value) = data.downcast_ref::<TextComponent>() else {
448 return Err(std::io::Error::other("Component type mismatch"));
449 };
450 value.write(writer)
451}
452
453fn text_component_nbt_reader(tag: simdnbt::borrow::NbtTag) -> Option<ComponentData> {
454 use simdnbt::FromNbtTag as _;
455 TextComponent::from_nbt_tag(tag).map(ComponentData::new)
456}
457
458fn text_component_nbt_writer(data: &ComponentData) -> std::io::Result<simdnbt::owned::NbtTag> {
459 let Some(value) = data.downcast_ref::<TextComponent>() else {
460 return Err(std::io::Error::other("Component type mismatch"));
461 };
462 Ok(value.to_codec_nbt())
463}
464
465fn custom_data_codec_reader(cursor: &mut std::io::Cursor<&[u8]>) -> std::io::Result<ComponentData> {
466 CustomData::read_codec_network(cursor).map(ComponentData::new)
467}
468
469fn custom_data_writer(data: &ComponentData, writer: &mut Vec<u8>) -> std::io::Result<()> {
470 use steel_utils::serial::WriteTo as _;
471 let Some(value) = data.downcast_ref::<CustomData>() else {
472 return Err(std::io::Error::other("Component type mismatch"));
473 };
474 value.write(writer)
475}
476
477#[expect(
478 clippy::unnecessary_wraps,
479 reason = "network reader function pointers return io::Result"
480)]
481fn unit_reader(_cursor: &mut std::io::Cursor<&[u8]>) -> std::io::Result<ComponentData> {
482 Ok(ComponentData::new(()))
483}
484
485fn unit_writer(data: &ComponentData, _writer: &mut Vec<u8>) -> std::io::Result<()> {
486 if data.downcast_ref::<()>().is_some() {
487 Ok(())
488 } else {
489 Err(std::io::Error::other("Component type mismatch"))
490 }
491}
492
493fn codec_unit_network_reader(
494 cursor: &mut std::io::Cursor<&[u8]>,
495) -> std::io::Result<ComponentData> {
496 let tag = simdnbt::owned::read_tag(cursor)
497 .map_err(|error| std::io::Error::other(format!("Invalid NBT: {error:?}")))?;
498 tag.compound()
499 .map(|_| ComponentData::new(()))
500 .ok_or_else(|| std::io::Error::other("Unit codec network value is not a compound"))
501}
502
503fn codec_unit_network_writer(data: &ComponentData, writer: &mut Vec<u8>) -> std::io::Result<()> {
504 unit_nbt_writer(data)?.write(writer);
505 Ok(())
506}
507
508fn ranged_i32_nbt_reader<const MIN: i32, const MAX: i32>(
509 tag: simdnbt::borrow::NbtTag,
510) -> Option<ComponentData> {
511 let value = tag.codec_i32()?;
512 (MIN..=MAX)
513 .contains(&value)
514 .then(|| ComponentData::new(value))
515}
516
517fn ranged_i32_nbt_writer<const MIN: i32, const MAX: i32>(
518 data: &ComponentData,
519) -> std::io::Result<simdnbt::owned::NbtTag> {
520 let Some(value) = data.downcast_ref::<i32>() else {
521 return Err(std::io::Error::other("Component type mismatch"));
522 };
523 if !(MIN..=MAX).contains(value) {
524 return Err(std::io::Error::other(format!(
525 "Value {value} outside of range [{MIN}:{MAX}]"
526 )));
527 }
528 Ok(simdnbt::owned::NbtTag::Int(*value))
529}
530
531fn minimum_attack_charge_nbt_reader(tag: simdnbt::borrow::NbtTag) -> Option<ComponentData> {
532 let value = tag.codec_f32()?;
533 (value.is_finite() && !value.is_sign_negative() && value <= 1.0)
534 .then(|| ComponentData::new(value))
535}
536
537fn potion_duration_scale_nbt_reader(tag: simdnbt::borrow::NbtTag) -> Option<ComponentData> {
538 let value = tag.codec_f32()?;
539 (value.is_finite() && !value.is_sign_negative()).then(|| ComponentData::new(value))
540}
541
542fn minimum_attack_charge_nbt_writer(
543 data: &ComponentData,
544) -> std::io::Result<simdnbt::owned::NbtTag> {
545 let Some(value) = data.downcast_ref::<f32>() else {
546 return Err(std::io::Error::other("Component type mismatch"));
547 };
548 if !value.is_finite() || value.is_sign_negative() || *value > 1.0 {
549 return Err(std::io::Error::other(format!(
550 "Value {value} outside of range [0:1]"
551 )));
552 }
553 Ok(simdnbt::owned::NbtTag::Float(*value))
554}
555
556fn potion_duration_scale_nbt_writer(
557 data: &ComponentData,
558) -> std::io::Result<simdnbt::owned::NbtTag> {
559 let Some(value) = data.downcast_ref::<f32>() else {
560 return Err(std::io::Error::other("Component type mismatch"));
561 };
562 if !value.is_finite() || value.is_sign_negative() {
563 return Err(std::io::Error::other(format!(
564 "Value {value} must be non-negative and finite"
565 )));
566 }
567 Ok(simdnbt::owned::NbtTag::Float(*value))
568}
569
570fn bool_nbt_reader(tag: simdnbt::borrow::NbtTag) -> Option<ComponentData> {
571 tag.codec_bool().map(ComponentData::new)
572}
573
574fn bool_nbt_writer(data: &ComponentData) -> std::io::Result<simdnbt::owned::NbtTag> {
575 let Some(value) = data.downcast_ref::<bool>() else {
576 return Err(std::io::Error::other("Component type mismatch"));
577 };
578 Ok(simdnbt::owned::NbtTag::Byte(i8::from(*value)))
579}
580
581fn unit_nbt_reader(tag: simdnbt::borrow::NbtTag) -> Option<ComponentData> {
582 tag.compound().map(|_| ComponentData::new(()))
583}
584
585fn unit_nbt_writer(data: &ComponentData) -> std::io::Result<simdnbt::owned::NbtTag> {
586 if data.downcast_ref::<()>().is_none() {
587 return Err(std::io::Error::other("Component type mismatch"));
588 }
589 Ok(simdnbt::owned::NbtTag::Compound(
590 simdnbt::owned::NbtCompound::new(),
591 ))
592}
593
594fn jukebox_playable_network_reader(
595 cursor: &mut std::io::Cursor<&[u8]>,
596) -> std::io::Result<ComponentData> {
597 use steel_utils::serial::ReadFrom;
598 JukeboxPlayable::read(cursor).map(ComponentData::new)
599}
600
601fn jukebox_playable_network_writer(
602 data: &ComponentData,
603 writer: &mut Vec<u8>,
604) -> std::io::Result<()> {
605 use steel_utils::serial::WriteTo;
606 let Some(value) = data.downcast_ref::<JukeboxPlayable>() else {
607 return Err(std::io::Error::other("Component type mismatch"));
608 };
609 value.write(writer)
610}
611
612fn jukebox_playable_nbt_reader(tag: simdnbt::borrow::NbtTag) -> Option<ComponentData> {
613 JukeboxPlayable::from_persistent_nbt(tag).map(ComponentData::new)
614}
615
616fn jukebox_playable_nbt_writer(data: &ComponentData) -> std::io::Result<simdnbt::owned::NbtTag> {
617 let Some(value) = data.downcast_ref::<JukeboxPlayable>() else {
618 return Err(std::io::Error::other("Component type mismatch"));
619 };
620 value.to_persistent_nbt()
621}
622
623fn fireworks_nbt_reader(tag: simdnbt::borrow::NbtTag) -> Option<ComponentData> {
624 Fireworks::from_nbt_tag(tag).map(ComponentData::new)
625}
626
627fn fireworks_network_reader(cursor: &mut std::io::Cursor<&[u8]>) -> std::io::Result<ComponentData> {
628 use steel_utils::serial::ReadFrom as _;
629 Fireworks::read(cursor).map(ComponentData::new)
630}
631
632fn fireworks_network_writer(data: &ComponentData, writer: &mut Vec<u8>) -> std::io::Result<()> {
633 use steel_utils::serial::WriteTo as _;
634 let Some(value) = data.downcast_ref::<Fireworks>() else {
635 return Err(std::io::Error::other("Component type mismatch"));
636 };
637 value.write(writer)
638}
639
640fn fireworks_nbt_writer(data: &ComponentData) -> std::io::Result<simdnbt::owned::NbtTag> {
641 let Some(value) = data.downcast_ref::<Fireworks>() else {
642 return Err(std::io::Error::other("Component type mismatch"));
643 };
644 value.try_to_persistent_nbt()
645}
646
647fn painting_variant_network_reader(
648 cursor: &mut std::io::Cursor<&[u8]>,
649) -> std::io::Result<ComponentData> {
650 use steel_utils::serial::ReadFrom as _;
651 PaintingVariantComponent::read(cursor).map(ComponentData::new)
652}
653
654fn painting_variant_network_writer(
655 data: &ComponentData,
656 writer: &mut Vec<u8>,
657) -> std::io::Result<()> {
658 use steel_utils::serial::WriteTo as _;
659 let Some(value) = data.downcast_ref::<PaintingVariantComponent>() else {
660 return Err(std::io::Error::other("Component type mismatch"));
661 };
662 value.write(writer)
663}
664
665fn painting_variant_nbt_reader(tag: simdnbt::borrow::NbtTag) -> Option<ComponentData> {
666 PaintingVariantComponent::from_nbt_tag(tag).map(ComponentData::new)
667}
668
669fn painting_variant_nbt_writer(data: &ComponentData) -> std::io::Result<simdnbt::owned::NbtTag> {
670 let Some(value) = data.downcast_ref::<PaintingVariantComponent>() else {
671 return Err(std::io::Error::other("Component type mismatch"));
672 };
673 value.try_to_persistent_nbt()
674}
675
676macro_rules! register_ranged_i32 {
677 ($registry:expr, $component:expr, $min:expr, $max:expr) => {
678 $registry.register_with_codecs(
679 $component,
680 varint_reader,
681 varint_writer,
682 ranged_i32_nbt_reader::<{ $min }, { $max }>,
683 ranged_i32_nbt_writer::<{ $min }, { $max }>,
684 );
685 };
686}
687
688macro_rules! register_stream_unit {
689 ($registry:expr, $component:expr) => {
690 $registry.register_with_codecs(
691 $component,
692 unit_reader,
693 unit_writer,
694 unit_nbt_reader,
695 unit_nbt_writer,
696 );
697 };
698}
699
700pub fn register_vanilla_data_components(registry: &mut DataComponentRegistry) {
705 registry.register_custom_network(CUSTOM_DATA, custom_data_codec_reader, custom_data_writer);
708 register_ranged_i32!(registry, MAX_STACK_SIZE, 1, 99);
710 register_ranged_i32!(registry, MAX_DAMAGE, 1, i32::MAX);
712 register_ranged_i32!(registry, DAMAGE, 0, i32::MAX);
714 register_stream_unit!(registry, UNBREAKABLE);
716 registry.register(USE_EFFECTS);
718 registry.register_with_codecs(
720 CUSTOM_NAME,
721 text_component_network_reader,
722 text_component_network_writer,
723 text_component_nbt_reader,
724 text_component_nbt_writer,
725 );
726 registry.register_with_codecs(
728 MINIMUM_ATTACK_CHARGE,
729 float_reader,
730 float_writer,
731 minimum_attack_charge_nbt_reader,
732 minimum_attack_charge_nbt_writer,
733 );
734 registry.register(DAMAGE_TYPE);
736 registry.register_with_codecs(
738 ITEM_NAME,
739 text_component_network_reader,
740 text_component_network_writer,
741 text_component_nbt_reader,
742 text_component_nbt_writer,
743 );
744 registry.register(ITEM_MODEL);
746 registry.register(LORE);
748 registry.register(RARITY);
750 registry.register(ENCHANTMENTS);
752 registry.register(CAN_PLACE_ON);
754 registry.register(CAN_BREAK);
756 registry.register(ATTRIBUTE_MODIFIERS);
758 registry.register(CUSTOM_MODEL_DATA);
760 registry.register(TOOLTIP_DISPLAY);
762 register_ranged_i32!(registry, REPAIR_COST, 0, i32::MAX);
764 registry.register_transient(CREATIVE_SLOT_LOCK);
766 registry.register_with_codecs(
768 ENCHANTMENT_GLINT_OVERRIDE,
769 bool_reader,
770 bool_writer,
771 bool_nbt_reader,
772 bool_nbt_writer,
773 );
774 registry.register_with_codecs(
776 INTANGIBLE_PROJECTILE,
777 codec_unit_network_reader,
778 codec_unit_network_writer,
779 unit_nbt_reader,
780 unit_nbt_writer,
781 );
782 registry.register(FOOD);
784 registry.register(CONSUMABLE);
786 registry.register_validated(USE_REMAINDER);
788 registry.register(USE_COOLDOWN);
790 registry.register(DAMAGE_RESISTANT);
792 registry.register(TOOL);
794 registry.register(WEAPON);
796 registry.register(ATTACK_RANGE);
798 registry.register(ENCHANTABLE);
800 registry.register(EQUIPPABLE);
802 registry.register(REPAIRABLE);
804 register_stream_unit!(registry, GLIDER);
806 registry.register(TOOLTIP_STYLE);
808 registry.register(DEATH_PROTECTION);
810 registry.register(BLOCKS_ATTACKS);
812 registry.register(PIERCING_WEAPON);
814 registry.register(KINETIC_WEAPON);
816 registry.register(SWING_ANIMATION);
818 registry.register_transient_with_codecs(ADDITIONAL_TRADE_COST, varint_reader, varint_writer);
820 registry.register(STORED_ENCHANTMENTS);
822 registry.register(DYE);
824 registry.register(DYED_COLOR);
826 registry.register(MAP_COLOR);
828 registry.register(MAP_ID);
830 registry.register(MAP_DECORATIONS);
832 registry.register_transient(MAP_POST_PROCESSING);
834 registry.register_validated(CHARGED_PROJECTILES);
836 registry.register_validated(BUNDLE_CONTENTS);
838 registry.register(POTION_CONTENTS);
840 registry.register_with_codecs(
842 POTION_DURATION_SCALE,
843 float_reader,
844 float_writer,
845 potion_duration_scale_nbt_reader,
846 potion_duration_scale_nbt_writer,
847 );
848 registry.register(SUSPICIOUS_STEW_EFFECTS);
850 registry.register(WRITABLE_BOOK_CONTENT);
852 registry.register(WRITTEN_BOOK_CONTENT);
854 registry.register(TRIM);
856 registry.register(DEBUG_STICK_STATE);
858 registry.register(ENTITY_DATA);
860 registry.register(BUCKET_ENTITY_DATA);
862 registry.register(BLOCK_ENTITY_DATA);
864 registry.register(INSTRUMENT);
866 registry.register(PROVIDES_TRIM_MATERIAL);
868 registry.register(OMINOUS_BOTTLE_AMPLIFIER);
870 registry.register_with_codecs(
872 JUKEBOX_PLAYABLE,
873 jukebox_playable_network_reader,
874 jukebox_playable_network_writer,
875 jukebox_playable_nbt_reader,
876 jukebox_playable_nbt_writer,
877 );
878 registry.register(PROVIDES_BANNER_PATTERNS);
880 registry.register(RECIPES);
882 registry.register(LODESTONE_TRACKER);
884 registry.register(FIREWORK_EXPLOSION);
886 registry.register_with_codecs(
888 FIREWORKS,
889 fireworks_network_reader,
890 fireworks_network_writer,
891 fireworks_nbt_reader,
892 fireworks_nbt_writer,
893 );
894 registry.register(PROFILE);
896 registry.register(NOTE_BLOCK_SOUND);
898 registry.register(BANNER_PATTERNS);
900 registry.register(BASE_COLOR);
902 registry.register(POT_DECORATIONS);
904 registry.register_validated(CONTAINER);
906 registry.register(BLOCK_STATE);
908 registry.register(BEES);
910 registry.register_validated(SULFUR_CUBE_CONTENT);
912 registry.register(LOCK);
914 registry.register(CONTAINER_LOOT);
916 registry.register(BREAK_SOUND);
918 registry.register(VILLAGER_VARIANT);
920 registry.register(WOLF_VARIANT);
922 registry.register(WOLF_SOUND_VARIANT);
924 registry.register(WOLF_COLLAR);
926 registry.register(FOX_VARIANT);
928 registry.register(SALMON_SIZE);
930 registry.register(PARROT_VARIANT);
932 registry.register(TROPICAL_FISH_PATTERN);
934 registry.register(TROPICAL_FISH_BASE_COLOR);
936 registry.register(TROPICAL_FISH_PATTERN_COLOR);
938 registry.register(MOOSHROOM_VARIANT);
940 registry.register(RABBIT_VARIANT);
942 registry.register(PIG_VARIANT);
944 registry.register(PIG_SOUND_VARIANT);
946 registry.register(COW_VARIANT);
948 registry.register(COW_SOUND_VARIANT);
950 registry.register(CHICKEN_VARIANT);
952 registry.register(CHICKEN_SOUND_VARIANT);
954 registry.register(ZOMBIE_NAUTILUS_VARIANT);
956 registry.register(FROG_VARIANT);
958 registry.register(HORSE_VARIANT);
960 registry.register_with_codecs(
962 PAINTING_VARIANT,
963 painting_variant_network_reader,
964 painting_variant_network_writer,
965 painting_variant_nbt_reader,
966 painting_variant_nbt_writer,
967 );
968 registry.register(LLAMA_VARIANT);
970 registry.register(AXOLOTL_VARIANT);
972 registry.register(CAT_VARIANT);
974 registry.register(CAT_SOUND_VARIANT);
976 registry.register(CAT_COLLAR);
978 registry.register(SHEEP_COLOR);
980 registry.register(SHULKER_COLOR);
982}
983
984#[cfg(test)]
985mod tests;