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