1#![feature(const_trait_impl, const_cmp, derive_const)]
2
3use crate::game_events::GameEventRegistry;
4use crate::world_clock::WorldClockRegistry;
5use crate::{
6 attribute::AttributeRegistry,
7 banner_pattern::BannerPatternRegistry,
8 biome::BiomeRegistry,
9 block_entity_type::BlockEntityTypeRegistry,
10 blocks::BlockRegistry,
11 carver::ConfiguredCarverRegistry,
12 cat_sound_variant::CatSoundVariantRegistry,
13 cat_variant::CatVariantRegistry,
14 chat_type::ChatTypeRegistry,
15 chicken_sound_variant::ChickenSoundVariantRegistry,
16 chicken_variant::ChickenVariantRegistry,
17 cow_sound_variant::CowSoundVariantRegistry,
18 cow_variant::CowVariantRegistry,
19 damage_type::DamageTypeRegistry,
20 data_components::{DataComponentRegistry, vanilla_components},
21 dialog::DialogRegistry,
22 dimension_type::DimensionTypeRegistry,
23 enchantment::EnchantmentRegistry,
24 entity_data::{EntityDataSerializerRegistry, register_vanilla_entity_data_serializers},
25 entity_type::EntityTypeRegistry,
26 feature::{
27 ConfiguredFeatureKind, ConfiguredFeatureRef, ConfiguredFeatureRegistry, PlacedFeatureData,
28 PlacedFeatureRef, PlacedFeatureRegistry,
29 },
30 fluid::FluidRegistry,
31 frog_variant::FrogVariantRegistry,
32 game_rules::GameRuleRegistry,
33 instrument::InstrumentRegistry,
34 items::ItemRegistry,
35 jukebox_song::JukeboxSongRegistry,
36 loot_table::LootTableRegistry,
37 menu_type::MenuTypeRegistry,
38 mob_effect::MobEffectRegistry,
39 painting_variant::PaintingVariantRegistry,
40 particle_type::ParticleTypeRegistry,
41 pig_sound_variant::PigSoundVariantRegistry,
42 pig_variant::PigVariantRegistry,
43 poi::PoiTypeRegistry,
44 recipe::RecipeRegistry,
45 sound_event::SoundEventRegistry,
46 structure::StructureRegistry,
47 structure_processor::StructureProcessorListRegistry,
48 timeline::TimelineRegistry,
49 trim_material::TrimMaterialRegistry,
50 trim_pattern::TrimPatternRegistry,
51 villager_profession::VillagerProfessionRegistry,
52 villager_type::VillagerTypeRegistry,
53 wolf_sound_variant::WolfSoundVariantRegistry,
54 wolf_variant::WolfVariantRegistry,
55 zombie_nautilus_variant::ZombieNautilusVariantRegistry,
56};
57use std::{fmt::Debug, ops::Deref, sync::OnceLock};
58use steel_utils::Identifier;
59pub mod attribute;
60pub mod banner_pattern;
61pub mod biome;
62pub mod block_entity_type;
63pub mod blocks;
64pub mod carver;
65pub mod cat_sound_variant;
66pub mod cat_variant;
67pub mod chat_type;
68pub mod chicken_sound_variant;
69pub mod chicken_variant;
70pub mod cow_sound_variant;
71pub mod cow_variant;
72pub mod damage_type;
73pub mod data_components;
74pub mod dialog;
75pub mod dimension_type;
76pub mod enchantment;
77pub mod entity_data;
78pub mod entity_type;
79pub mod feature;
80pub mod fluid;
81pub mod frog_variant;
82pub mod game_events;
83pub mod game_rules;
84pub mod instrument;
85pub mod item_stack;
86pub mod items;
87pub mod jukebox_song;
88pub mod loot_table;
89mod macros;
90pub mod menu_type;
91pub mod mob_effect;
92pub mod painting_variant;
93pub mod particle_type;
94pub mod pig_sound_variant;
95pub mod pig_variant;
96pub mod poi;
97pub mod recipe;
98pub mod sound_event;
99pub mod structure;
100pub mod structure_processor;
101pub mod structure_set;
102pub mod template_pool;
103pub mod timeline;
104pub mod trim_material;
105pub mod trim_pattern;
106pub mod villager_profession;
107pub mod villager_type;
108pub mod wolf_sound_variant;
109pub mod wolf_variant;
110pub mod world_clock;
111pub mod zombie_nautilus_variant;
112
113#[expect(warnings)]
114#[rustfmt::skip]
115#[path = "generated/vanilla_attributes.rs"]
116pub mod vanilla_attributes;
117
118#[expect(warnings)]
119#[rustfmt::skip]
120#[path = "generated/vanilla_blocks.rs"]
121pub mod vanilla_blocks;
122
123#[expect(warnings)]
124#[rustfmt::skip]
125#[path = "generated/vanilla_block_tags.rs"]
126pub mod vanilla_block_tags;
127
128#[expect(warnings)]
129#[rustfmt::skip]
130#[path = "generated/vanilla_banner_patterns.rs"]
131pub mod vanilla_banner_patterns;
132
133#[expect(warnings)]
134#[rustfmt::skip]
135#[path = "generated/vanilla_items.rs"]
136pub mod vanilla_items;
137
138#[expect(warnings)]
139#[rustfmt::skip]
140#[path = "generated/vanilla_item_tags.rs"]
141pub mod vanilla_item_tags;
142
143#[expect(warnings)]
144#[rustfmt::skip]
145#[path = "generated/vanilla_biomes.rs"]
146pub mod vanilla_biomes;
147
148#[expect(warnings)]
149#[rustfmt::skip]
150#[path = "generated/vanilla_biome_tags.rs"]
151pub mod vanilla_biome_tags;
152
153#[expect(warnings)]
154#[rustfmt::skip]
155#[path = "generated/vanilla_chat_types.rs"]
156pub mod vanilla_chat_types;
157
158#[expect(warnings)]
159#[rustfmt::skip]
160#[path = "generated/vanilla_trim_patterns.rs"]
161pub mod vanilla_trim_patterns;
162
163#[expect(warnings)]
164#[rustfmt::skip]
165#[path = "generated/vanilla_trim_materials.rs"]
166pub mod vanilla_trim_materials;
167
168#[expect(warnings)]
169#[rustfmt::skip]
170#[path = "generated/vanilla_wolf_variants.rs"]
171pub mod vanilla_wolf_variants;
172
173#[expect(warnings)]
174#[rustfmt::skip]
175#[path = "generated/vanilla_wolf_sound_variants.rs"]
176pub mod vanilla_wolf_sound_variants;
177
178#[expect(warnings)]
179#[rustfmt::skip]
180#[path = "generated/vanilla_pig_variants.rs"]
181pub mod vanilla_pig_variants;
182
183#[expect(warnings)]
184#[rustfmt::skip]
185#[path = "generated/vanilla_pig_sound_variants.rs"]
186pub mod vanilla_pig_sound_variants;
187
188#[allow(warnings)]
189#[rustfmt::skip]
190#[path = "generated/vanilla_chicken_sound_variants.rs"]
191pub mod vanilla_chicken_sound_variants;
192
193#[allow(warnings)]
194#[rustfmt::skip]
195#[path = "generated/vanilla_cat_sound_variants.rs"]
196pub mod vanilla_cat_sound_variants;
197
198#[allow(warnings)]
199#[rustfmt::skip]
200#[path = "generated/vanilla_cow_sound_variants.rs"]
201pub mod vanilla_cow_sound_variants;
202
203#[allow(warnings)]
204#[rustfmt::skip]
205#[path = "generated/vanilla_frog_variants.rs"]
206pub mod vanilla_frog_variants;
207
208#[expect(warnings)]
209#[rustfmt::skip]
210#[path = "generated/vanilla_cat_variants.rs"]
211pub mod vanilla_cat_variants;
212
213#[expect(warnings)]
214#[rustfmt::skip]
215#[path = "generated/vanilla_cow_variants.rs"]
216pub mod vanilla_cow_variants;
217
218#[expect(warnings)]
219#[rustfmt::skip]
220#[path = "generated/vanilla_chicken_variants.rs"]
221pub mod vanilla_chicken_variants;
222
223#[expect(warnings)]
224#[rustfmt::skip]
225#[path = "generated/vanilla_painting_variants.rs"]
226pub mod vanilla_painting_variants;
227
228#[expect(warnings)]
229#[rustfmt::skip]
230#[path = "generated/vanilla_particle_types.rs"]
231pub mod vanilla_particle_types;
232
233#[expect(warnings)]
234#[rustfmt::skip]
235#[path = "generated/vanilla_villager_types.rs"]
236pub mod vanilla_villager_types;
237
238#[expect(warnings)]
239#[rustfmt::skip]
240#[path = "generated/vanilla_villager_professions.rs"]
241pub mod vanilla_villager_professions;
242
243#[expect(warnings)]
244#[rustfmt::skip]
245#[path = "generated/vanilla_dimension_types.rs"]
246pub mod vanilla_dimension_types;
247
248#[expect(warnings)]
249#[rustfmt::skip]
250#[path = "generated/vanilla_damage_types.rs"]
251pub mod vanilla_damage_types;
252
253#[expect(warnings)]
254#[rustfmt::skip]
255#[path = "generated/vanilla_damage_type_tags.rs"]
256pub mod vanilla_damage_type_tags;
257
258#[expect(warnings)]
259#[rustfmt::skip]
260#[path = "generated/vanilla_jukebox_songs.rs"]
261pub mod vanilla_jukebox_songs;
262
263#[expect(warnings)]
264#[rustfmt::skip]
265#[path = "generated/vanilla_instruments.rs"]
266pub mod vanilla_instruments;
267
268#[expect(warnings)]
269#[rustfmt::skip]
270#[path = "generated/vanilla_dialogs.rs"]
271pub mod vanilla_dialogs;
272
273#[expect(warnings)]
274#[rustfmt::skip]
275#[path = "generated/vanilla_dialog_tags.rs"]
276pub mod vanilla_dialog_tags;
277
278#[expect(warnings)]
279#[rustfmt::skip]
280#[path = "generated/vanilla_menu_types.rs"]
281pub mod vanilla_menu_types;
282
283#[expect(warnings)]
284#[rustfmt::skip]
285#[path = "generated/vanilla_mob_effects.rs"]
286pub mod vanilla_mob_effects;
287
288#[expect(warnings)]
289#[rustfmt::skip]
290#[path = "generated/vanilla_zombie_nautilus_variants.rs"]
291pub mod vanilla_zombie_nautilus_variants;
292
293#[expect(warnings)]
294#[rustfmt::skip]
295#[path = "generated/vanilla_timelines.rs"]
296pub mod vanilla_timelines;
297
298#[expect(warnings)]
299#[rustfmt::skip]
300#[path = "generated/vanilla_timeline_tags.rs"]
301pub mod vanilla_timeline_tags;
302
303#[expect(warnings)]
304#[rustfmt::skip]
305#[path = "generated/vanilla_recipes.rs"]
306pub mod vanilla_recipes;
307
308#[expect(warnings)]
309#[rustfmt::skip]
310#[path = "generated/vanilla_entities.rs"]
311pub mod vanilla_entities;
312
313#[expect(warnings)]
314#[rustfmt::skip]
315#[path = "generated/vanilla_entity_data.rs"]
316pub mod vanilla_entity_data;
317
318#[expect(warnings)]
319#[rustfmt::skip]
320#[path = "generated/vanilla_fluids.rs"]
321pub mod vanilla_fluids;
322
323#[expect(warnings)]
324#[rustfmt::skip]
325#[path = "generated/vanilla_poi_types.rs"]
326pub mod vanilla_poi_types;
327
328#[expect(warnings)]
329#[rustfmt::skip]
330#[path = "generated/vanilla_banner_pattern_tags.rs"]
331pub mod vanilla_banner_pattern_tags;
332
333#[expect(warnings)]
334#[rustfmt::skip]
335#[path = "generated/vanilla_entity_type_tags.rs"]
336pub mod vanilla_entity_type_tags;
337
338#[expect(warnings)]
339#[rustfmt::skip]
340#[path = "generated/vanilla_enchantment_tags.rs"]
341pub mod vanilla_enchantment_tags;
342#[expect(warnings)]
343#[rustfmt::skip]
344#[path = "generated/vanilla_enchantments.rs"]
345pub mod vanilla_enchantments;
346
347#[allow(warnings)]
348#[rustfmt::skip]
349#[path = "generated/vanilla_instrument_tags.rs"]
350pub mod vanilla_instrument_tags;
351
352#[expect(warnings)]
353#[rustfmt::skip]
354#[path = "generated/vanilla_painting_variant_tags.rs"]
355pub mod vanilla_painting_variant_tags;
356
357#[expect(warnings)]
358#[rustfmt::skip]
359#[path = "generated/vanilla_poi_type_tags.rs"]
360pub mod vanilla_poi_type_tags;
361
362#[expect(warnings)]
363#[rustfmt::skip]
364#[path = "generated/vanilla_fluid_tags.rs"]
365pub mod vanilla_fluid_tags;
366
367#[expect(warnings)]
368#[rustfmt::skip]
369#[path = "generated/vanilla_loot_tables.rs"]
370pub mod vanilla_loot_tables;
371
372#[expect(warnings)]
373#[rustfmt::skip]
374#[path = "generated/vanilla_block_entity_types.rs"]
375pub mod vanilla_block_entity_types;
376
377#[expect(warnings)]
378#[rustfmt::skip]
379#[path = "generated/vanilla_game_rules.rs"]
380pub mod vanilla_game_rules;
381
382#[expect(warnings)]
383#[rustfmt::skip]
384#[path = "generated/vanilla_game_events.rs"]
385pub mod vanilla_game_events;
386
387#[expect(warnings)]
388#[rustfmt::skip]
389#[path = "generated/vanilla_level_events.rs"]
390pub mod level_events;
391
392#[expect(warnings)]
393#[rustfmt::skip]
394#[path = "generated/vanilla_sound_events.rs"]
395pub mod sound_events;
396
397#[expect(warnings)]
398#[rustfmt::skip]
399#[path = "generated/vanilla_sound_types.rs"]
400pub mod sound_types;
401
402#[expect(warnings)]
403#[rustfmt::skip]
404#[path = "generated/vanilla_structures.rs"]
405pub mod vanilla_structures;
406
407#[expect(warnings)]
408#[rustfmt::skip]
409#[path = "generated/vanilla_structure_tags.rs"]
410pub mod vanilla_structure_tags;
411
412#[expect(warnings)]
413#[rustfmt::skip]
414#[path = "generated/vanilla_structure_sets.rs"]
415pub mod vanilla_structure_sets;
416
417#[expect(warnings)]
418#[rustfmt::skip]
419#[path = "generated/vanilla_structure_processors.rs"]
420pub mod vanilla_structure_processors;
421
422#[rustfmt::skip]
423#[path = "generated/vanilla_template_pools.rs"]
424pub mod vanilla_template_pools;
425
426#[allow(warnings)]
427#[rustfmt::skip]
428#[path = "generated/vanilla_packets.rs"]
429pub mod packets;
430
431#[allow(warnings)]
432#[rustfmt::skip]
433#[path = "generated/vanilla_world_clocks.rs"]
434pub mod vanilla_world_clocks;
435pub mod shared_structs;
436
437#[expect(warnings)]
438#[rustfmt::skip]
439#[path = "generated/vanilla_configured_carvers.rs"]
440pub mod vanilla_configured_carvers;
441
442#[expect(warnings)]
443#[rustfmt::skip]
444#[path = "generated/vanilla_configured_features.rs"]
445pub mod vanilla_configured_features;
446
447#[expect(warnings)]
448#[rustfmt::skip]
449#[path = "generated/vanilla_placed_features.rs"]
450pub mod vanilla_placed_features;
451
452pub struct RegistryLock(OnceLock<Registry>);
453
454impl RegistryLock {
455 #[expect(clippy::result_large_err)]
456 pub fn init(&self, value: Registry) -> Result<(), Registry> {
457 self.0.set(value)
458 }
459
460 #[cfg(test)]
461 pub(crate) fn get_or_init(&self, f: impl FnOnce() -> Registry) -> &Registry {
462 self.0.get_or_init(f)
463 }
464}
465
466impl Deref for RegistryLock {
467 type Target = Registry;
468
469 fn deref(&self) -> &Self::Target {
470 self.0.get().expect("Registry not init")
471 }
472}
473
474pub static REGISTRY: RegistryLock = RegistryLock(OnceLock::new());
475
476#[cfg(any(test, feature = "test-utils"))]
477pub mod test_support {
478 use std::sync::Once;
479
480 use crate::{REGISTRY, Registry};
481
482 static INIT_REGISTRY: Once = Once::new();
483
484 pub fn init_test_registry() {
486 INIT_REGISTRY.call_once(|| {
487 let mut registry = Registry::new_vanilla();
488 registry.freeze();
489 let _ = REGISTRY.init(registry);
490 });
491 }
492}
493
494pub trait RegistryEntry: 'static {
496 fn key(&self) -> &Identifier;
497 fn try_id(&self) -> Option<usize>;
498
499 fn id(&self) -> usize {
502 self.try_id().expect("entry not found in registry")
503 }
504}
505
506pub trait RegistryExt {
511 type Entry: RegistryEntry;
512
513 fn freeze(&mut self);
514 fn by_id(&self, id: usize) -> Option<&'static Self::Entry>;
515 fn by_key(&self, key: &Identifier) -> Option<&'static Self::Entry>;
516 fn id_from_key(&self, key: &Identifier) -> Option<usize>;
517 fn len(&self) -> usize;
518 fn is_empty(&self) -> bool;
519}
520
521pub trait TaggedRegistryExt: RegistryExt {
523 fn register_tag(&mut self, tag: Identifier, keys: &[&'static str]);
524 fn modify_tag(&mut self, tag: &Identifier, f: impl FnOnce(Vec<Identifier>) -> Vec<Identifier>);
525 fn is_in_tag(&self, entry: &'static Self::Entry, tag: &Identifier) -> bool;
526 fn get_tag(&self, tag: &Identifier) -> Option<Vec<&'static Self::Entry>>;
527 fn iter_tag(&self, tag: &Identifier) -> impl Iterator<Item = &'static Self::Entry> + '_;
528 fn tag_keys(&self) -> impl Iterator<Item = &Identifier> + '_;
529}
530
531pub const BLOCKS_REGISTRY: Identifier = Identifier::vanilla_static("block");
532pub const ITEMS_REGISTRY: Identifier = Identifier::vanilla_static("item");
533pub const BIOMES_REGISTRY: Identifier = Identifier::vanilla_static("worldgen/biome");
534pub const CHAT_TYPE_REGISTRY: Identifier = Identifier::vanilla_static("chat_type");
535pub const TRIM_PATTERN_REGISTRY: Identifier = Identifier::vanilla_static("trim_pattern");
536pub const TRIM_MATERIAL_REGISTRY: Identifier = Identifier::vanilla_static("trim_material");
537pub const WOLF_VARIANT_REGISTRY: Identifier = Identifier::vanilla_static("wolf_variant");
538pub const WOLF_SOUND_VARIANT_REGISTRY: Identifier =
539 Identifier::vanilla_static("wolf_sound_variant");
540pub const PIG_VARIANT_REGISTRY: Identifier = Identifier::vanilla_static("pig_variant");
541pub const PIG_SOUND_VARIANT_REGISTRY: Identifier = Identifier::vanilla_static("pig_sound_variant");
542pub const CHICKEN_SOUND_VARIANT_REGISTRY: Identifier =
543 Identifier::vanilla_static("chicken_sound_variant");
544pub const CAT_SOUND_VARIANT_REGISTRY: Identifier = Identifier::vanilla_static("cat_sound_variant");
545pub const COW_SOUND_VARIANT_REGISTRY: Identifier = Identifier::vanilla_static("cow_sound_variant");
546pub const FROG_VARIANT_REGISTRY: Identifier = Identifier::vanilla_static("frog_variant");
547pub const CAT_VARIANT_REGISTRY: Identifier = Identifier::vanilla_static("cat_variant");
548pub const COW_VARIANT_REGISTRY: Identifier = Identifier::vanilla_static("cow_variant");
549pub const CHICKEN_VARIANT_REGISTRY: Identifier = Identifier::vanilla_static("chicken_variant");
550pub const PAINTING_VARIANT_REGISTRY: Identifier = Identifier::vanilla_static("painting_variant");
551pub const PARTICLE_TYPE_REGISTRY: Identifier = Identifier::vanilla_static("particle_type");
552pub const VILLAGER_TYPE_REGISTRY: Identifier = Identifier::vanilla_static("villager_type");
553pub const VILLAGER_PROFESSION_REGISTRY: Identifier =
554 Identifier::vanilla_static("villager_profession");
555pub const DIMENSION_TYPE_REGISTRY: Identifier = Identifier::vanilla_static("dimension_type");
556pub const DAMAGE_TYPE_REGISTRY: Identifier = Identifier::vanilla_static("damage_type");
557pub const BANNER_PATTERN_REGISTRY: Identifier = Identifier::vanilla_static("banner_pattern");
558pub const ENCHANTMENT_REGISTRY: Identifier = Identifier::vanilla_static("enchantment");
559pub const JUKEBOX_SONG_REGISTRY: Identifier = Identifier::vanilla_static("jukebox_song");
560pub const INSTRUMENT_REGISTRY: Identifier = Identifier::vanilla_static("instrument");
561pub const DIALOG_REGISTRY: Identifier = Identifier::vanilla_static("dialog");
562pub const MENU_TYPE_REGISTRY: Identifier = Identifier::vanilla_static("menu");
563pub const MOB_EFFECT_REGISTRY: Identifier = Identifier::vanilla_static("mob_effect");
564pub const ZOMBIE_NAUTILUS_VARIANT_REGISTRY: Identifier =
565 Identifier::vanilla_static("zombie_nautilus_variant");
566pub const TIMELINE_REGISTRY: Identifier = Identifier::vanilla_static("timeline");
567pub const LOOT_TABLE_REGISTRY: Identifier = Identifier::vanilla_static("loot_table");
568pub const BLOCK_ENTITY_TYPE_REGISTRY: Identifier = Identifier::vanilla_static("block_entity_type");
569pub const FLUID_REGISTRY: Identifier = Identifier::vanilla_static("fluid");
570pub const ENTITY_TYPE_REGISTRY: Identifier = Identifier::vanilla_static("entity_type");
571pub const SOUND_EVENT_REGISTRY: Identifier = Identifier::vanilla_static("sound_event");
572pub const POI_TYPE_REGISTRY: Identifier = Identifier::vanilla_static("point_of_interest_type");
573pub const WORLD_CLOCK_REGISTRY: Identifier = Identifier::vanilla_static("world_clock");
574pub const CONFIGURED_CARVER_REGISTRY: Identifier =
575 Identifier::vanilla_static("worldgen/configured_carver");
576pub const CONFIGURED_FEATURE_REGISTRY: Identifier =
577 Identifier::vanilla_static("worldgen/configured_feature");
578pub const PLACED_FEATURE_REGISTRY: Identifier =
579 Identifier::vanilla_static("worldgen/placed_feature");
580pub const STRUCTURE_REGISTRY: Identifier = Identifier::vanilla_static("worldgen/structure");
581pub const STRUCTURE_PROCESSOR_LIST_REGISTRY: Identifier =
582 Identifier::vanilla_static("worldgen/processor_list");
583
584pub struct Registry {
585 pub attributes: AttributeRegistry,
586 pub blocks: BlockRegistry,
587 pub items: ItemRegistry,
588 pub data_components: DataComponentRegistry,
589 pub entity_data_serializers: EntityDataSerializerRegistry,
590 pub biomes: BiomeRegistry,
591 pub chat_types: ChatTypeRegistry,
592 pub trim_patterns: TrimPatternRegistry,
593 pub trim_materials: TrimMaterialRegistry,
594 pub wolf_variants: WolfVariantRegistry,
595 pub wolf_sound_variants: WolfSoundVariantRegistry,
596 pub pig_sound_variants: PigSoundVariantRegistry,
597 pub chicken_sound_variants: ChickenSoundVariantRegistry,
598 pub cat_sound_variants: CatSoundVariantRegistry,
599 pub cow_sound_variants: CowSoundVariantRegistry,
600 pub pig_variants: PigVariantRegistry,
601 pub frog_variants: FrogVariantRegistry,
602 pub cat_variants: CatVariantRegistry,
603 pub cow_variants: CowVariantRegistry,
604 pub chicken_variants: ChickenVariantRegistry,
605 pub painting_variants: PaintingVariantRegistry,
606 pub particle_types: ParticleTypeRegistry,
607 pub villager_types: VillagerTypeRegistry,
608 pub villager_professions: VillagerProfessionRegistry,
609 pub dimension_types: DimensionTypeRegistry,
610 pub damage_types: DamageTypeRegistry,
611 pub banner_patterns: BannerPatternRegistry,
612 pub jukebox_songs: JukeboxSongRegistry,
613 pub instruments: InstrumentRegistry,
614 pub dialogs: DialogRegistry,
615 pub menu_types: MenuTypeRegistry,
616 pub mob_effects: MobEffectRegistry,
617 pub zombie_nautilus_variants: ZombieNautilusVariantRegistry,
618 pub timelines: TimelineRegistry,
619 pub recipes: RecipeRegistry,
620 pub entity_types: EntityTypeRegistry,
621 pub loot_tables: LootTableRegistry,
622 pub block_entity_types: BlockEntityTypeRegistry,
623 pub game_rules: GameRuleRegistry,
624 pub game_events: GameEventRegistry,
625 pub sound_events: SoundEventRegistry,
626 pub fluids: FluidRegistry,
627 pub poi_types: PoiTypeRegistry,
628 pub enchantments: EnchantmentRegistry,
629 pub world_clocks: WorldClockRegistry,
630 pub configured_carvers: ConfiguredCarverRegistry,
631 pub configured_features: ConfiguredFeatureRegistry,
632 pub placed_features: PlacedFeatureRegistry,
633 pub structures: StructureRegistry,
634 pub structure_processors: StructureProcessorListRegistry,
635}
636
637impl Debug for Registry {
638 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
639 f.write_str("Registry {")
640 .and_then(|_| f.write_fmt(format_args!("Blocks Loaded: {}", self.blocks.len())))
641 .and_then(|_| f.write_str("}"))
642 }
643}
644
645impl Registry {
646 #[must_use]
647 pub fn new_vanilla() -> Self {
648 let mut registry = Self::new_empty();
649
650 vanilla_attributes::register_attributes(&mut registry.attributes);
651
652 vanilla_blocks::register_blocks(&mut registry.blocks);
653 vanilla_block_tags::BlockTag::register_block_tags(&mut registry.blocks);
654
655 vanilla_components::register_vanilla_data_components(&mut registry.data_components);
656
657 register_vanilla_entity_data_serializers(&mut registry.entity_data_serializers);
658
659 vanilla_items::register_items(&mut registry.items);
660 vanilla_item_tags::ItemTag::register_item_tags(&mut registry.items);
661
662 vanilla_biomes::register_biomes(&mut registry.biomes);
663 vanilla_biome_tags::BiomeTag::register_biome_tags(&mut registry.biomes);
664 vanilla_chat_types::register_chat_types(&mut registry.chat_types);
665 vanilla_trim_patterns::register_trim_patterns(&mut registry.trim_patterns);
666 vanilla_trim_materials::register_trim_materials(&mut registry.trim_materials);
667 vanilla_wolf_variants::register_wolf_variants(&mut registry.wolf_variants);
668 vanilla_wolf_sound_variants::register_wolf_sound_variants(
669 &mut registry.wolf_sound_variants,
670 );
671 vanilla_pig_variants::register_pig_variants(&mut registry.pig_variants);
672 vanilla_pig_sound_variants::register_pig_sound_variants(&mut registry.pig_sound_variants);
673 vanilla_chicken_sound_variants::register_chicken_sound_variants(
674 &mut registry.chicken_sound_variants,
675 );
676 vanilla_cat_sound_variants::register_cat_sound_variants(&mut registry.cat_sound_variants);
677 vanilla_cow_sound_variants::register_cow_sound_variants(&mut registry.cow_sound_variants);
678 vanilla_frog_variants::register_frog_variants(&mut registry.frog_variants);
679 vanilla_cat_variants::register_cat_variants(&mut registry.cat_variants);
680 vanilla_cow_variants::register_cow_variants(&mut registry.cow_variants);
681 vanilla_chicken_variants::register_chicken_variants(&mut registry.chicken_variants);
682 vanilla_painting_variants::register_painting_variants(&mut registry.painting_variants);
683 vanilla_particle_types::register_particle_types(&mut registry.particle_types);
684 vanilla_villager_types::register_villager_types(&mut registry.villager_types);
685 vanilla_villager_professions::register_villager_professions(
686 &mut registry.villager_professions,
687 );
688 vanilla_painting_variant_tags::PaintingVariantTag::register_painting_variant_tags(
689 &mut registry.painting_variants,
690 );
691 vanilla_dimension_types::register_dimension_types(&mut registry.dimension_types);
692 vanilla_damage_types::register_damage_types(&mut registry.damage_types);
693 vanilla_damage_type_tags::DamageTypeTag::register_damage_type_tags(
694 &mut registry.damage_types,
695 );
696 vanilla_banner_patterns::register_banner_patterns(&mut registry.banner_patterns);
697 vanilla_banner_pattern_tags::BannerPatternTag::register_banner_pattern_tags(
698 &mut registry.banner_patterns,
699 );
700 vanilla_jukebox_songs::register_jukebox_songs(&mut registry.jukebox_songs);
701 vanilla_instruments::register_instruments(&mut registry.instruments);
702 vanilla_instrument_tags::InstrumentTag::register_instrument_tags(&mut registry.instruments);
703 vanilla_dialogs::register_dialogs(&mut registry.dialogs);
704 vanilla_dialog_tags::DialogTag::register_dialog_tags(&mut registry.dialogs);
705 vanilla_menu_types::register_menu_types(&mut registry.menu_types);
706 vanilla_mob_effects::register_mob_effects(&mut registry.mob_effects);
707 vanilla_zombie_nautilus_variants::register_zombie_nautilus_variants(
708 &mut registry.zombie_nautilus_variants,
709 );
710 vanilla_timelines::register_timelines(&mut registry.timelines);
711 vanilla_timeline_tags::TimelineTag::register_timeline_tags(&mut registry.timelines);
712 vanilla_recipes::register_recipes(&mut registry.recipes);
713 vanilla_entities::register_entity_types(&mut registry.entity_types);
714 vanilla_entity_type_tags::EntityTypeTag::register_entity_type_tags(
715 &mut registry.entity_types,
716 );
717 vanilla_loot_tables::register_loot_tables(&mut registry.loot_tables);
718 vanilla_block_entity_types::register_block_entity_types(&mut registry.block_entity_types);
719 vanilla_game_rules::register_game_rules(&mut registry.game_rules);
720 vanilla_game_events::register_game_events(&mut registry.game_events);
721 sound_events::register_sound_events(&mut registry.sound_events);
722
723 vanilla_fluids::register_fluids(&mut registry.fluids);
724 vanilla_fluid_tags::FluidTag::register_fluid_tags(&mut registry.fluids);
725
726 vanilla_poi_types::register_poi_types(&mut registry.poi_types);
727 vanilla_poi_type_tags::PoiTag::register_poi_tags(&mut registry.poi_types);
728
729 vanilla_enchantments::register_enchantments(&mut registry.enchantments);
730 vanilla_enchantment_tags::EnchantmentTag::register_enchantment_tags(
731 &mut registry.enchantments,
732 );
733
734 vanilla_world_clocks::register_world_clocks(&mut registry.world_clocks);
735 vanilla_structures::register_structures(&mut registry.structures);
736 vanilla_structure_tags::StructureTag::register_structure_tags(&mut registry.structures);
737 vanilla_structure_processors::register_structure_processor_lists(
738 &mut registry.structure_processors,
739 );
740
741 vanilla_configured_carvers::register_configured_carvers(&mut registry.configured_carvers);
742 vanilla_configured_features::register_configured_features(
743 &mut registry.configured_features,
744 );
745 vanilla_placed_features::register_placed_features(&mut registry.placed_features);
746
747 registry
748 }
749
750 pub fn freeze(&mut self) {
751 self.validate_references();
752
753 self.attributes.freeze();
754 self.blocks.freeze();
755 self.data_components.freeze();
756 self.entity_data_serializers.freeze();
757 self.items.freeze();
758 self.biomes.freeze();
759 self.chat_types.freeze();
760 self.trim_patterns.freeze();
761 self.trim_materials.freeze();
762 self.wolf_variants.freeze();
763 self.wolf_sound_variants.freeze();
764 self.pig_variants.freeze();
765 self.pig_sound_variants.freeze();
766 self.chicken_sound_variants.freeze();
767 self.cat_sound_variants.freeze();
768 self.cow_sound_variants.freeze();
769 self.frog_variants.freeze();
770 self.cat_variants.freeze();
771 self.cow_variants.freeze();
772 self.chicken_variants.freeze();
773 self.painting_variants.freeze();
774 self.particle_types.freeze();
775 self.villager_types.freeze();
776 self.villager_professions.freeze();
777 self.dimension_types.freeze();
778 self.damage_types.freeze();
779 self.banner_patterns.freeze();
780 self.jukebox_songs.freeze();
781 self.instruments.freeze();
782 self.dialogs.freeze();
783 self.menu_types.freeze();
784 self.mob_effects.freeze();
785 self.zombie_nautilus_variants.freeze();
786 self.timelines.freeze();
787 self.recipes.freeze();
788 self.entity_types.freeze();
789 self.loot_tables.freeze();
790 self.block_entity_types.freeze();
791 self.game_rules.freeze();
792 self.game_events.freeze();
793 self.sound_events.freeze();
794 self.fluids.freeze();
795 self.poi_types.freeze();
796 self.enchantments.freeze();
797 self.world_clocks.freeze();
798 self.configured_carvers.freeze();
799 self.configured_features.freeze();
800 self.placed_features.freeze();
801 self.structures.freeze();
802 self.structure_processors.freeze();
803 }
804
805 fn validate_references(&self) {
806 for (_, biome) in self.biomes.iter() {
807 for carver_key in &biome.carvers {
808 assert!(
809 self.configured_carvers.by_key(carver_key).is_some(),
810 "biome {} references unknown configured carver {}",
811 biome.key,
812 carver_key
813 );
814 }
815
816 for feature_stage in &biome.features {
817 for placed_feature_key in feature_stage {
818 assert!(
819 self.placed_features.by_key(placed_feature_key).is_some(),
820 "biome {} references unknown placed feature {}",
821 biome.key,
822 placed_feature_key
823 );
824 }
825 }
826 }
827
828 for (_, placed_feature) in self.placed_features.iter() {
829 self.validate_placed_feature_data(&placed_feature.data);
830 }
831
832 for (_, configured_feature) in self.configured_features.iter() {
833 self.validate_configured_feature_kind(&configured_feature.kind);
834 }
835
836 if !self.placed_features.is_empty() {
837 for pool in vanilla_template_pools::vanilla_template_pools() {
838 for (element, _) in &pool.elements {
839 self.validate_template_pool_feature_refs(element);
840 }
841 }
842 }
843 }
844
845 fn validate_placed_feature_ref(&self, feature: &PlacedFeatureRef) {
846 match feature {
847 PlacedFeatureRef::Reference(feature) => {
848 let key = &feature.key;
849 assert!(
850 self.placed_features.by_key(key).is_some(),
851 "unknown placed feature reference {key}"
852 );
853 }
854 PlacedFeatureRef::Inline(data) => self.validate_placed_feature_data(data),
855 }
856 }
857
858 fn validate_placed_feature_data(&self, feature: &PlacedFeatureData) {
859 self.validate_configured_feature_ref(&feature.feature);
860 }
861
862 fn validate_configured_feature_ref(&self, feature: &ConfiguredFeatureRef) {
863 match feature {
864 ConfiguredFeatureRef::Reference(feature) => {
865 let key = &feature.key;
866 assert!(
867 self.configured_features.by_key(key).is_some(),
868 "unknown configured feature reference {key}"
869 );
870 }
871 ConfiguredFeatureRef::Inline(kind) => self.validate_configured_feature_kind(kind),
872 }
873 }
874
875 fn validate_configured_feature_kind(&self, kind: &ConfiguredFeatureKind) {
876 match kind {
877 ConfiguredFeatureKind::RandomBooleanSelector(config) => {
878 self.validate_placed_feature_ref(&config.feature_true);
879 self.validate_placed_feature_ref(&config.feature_false);
880 }
881 ConfiguredFeatureKind::RandomSelector(config) => {
882 for feature in &config.features {
883 self.validate_placed_feature_ref(&feature.feature);
884 }
885 self.validate_placed_feature_ref(&config.default);
886 }
887 ConfiguredFeatureKind::RootSystem(config) => {
888 self.validate_placed_feature_ref(&config.feature);
889 }
890 ConfiguredFeatureKind::Fossil(config) => {
891 assert!(
892 self.structure_processors
893 .by_key(&config.fossil_processors)
894 .is_some(),
895 "fossil configured feature references unknown processor list {}",
896 config.fossil_processors
897 );
898 assert!(
899 self.structure_processors
900 .by_key(&config.overlay_processors)
901 .is_some(),
902 "fossil configured feature references unknown processor list {}",
903 config.overlay_processors
904 );
905 }
906 ConfiguredFeatureKind::SimpleRandomSelector(config) => {
907 for feature in &config.features {
908 self.validate_placed_feature_ref(feature);
909 }
910 }
911 ConfiguredFeatureKind::VegetationPatch(config)
912 | ConfiguredFeatureKind::WaterloggedVegetationPatch(config) => {
913 self.validate_placed_feature_ref(&config.vegetation_feature);
914 }
915 _ => {}
916 }
917 }
918
919 fn validate_template_pool_feature_refs(&self, element: &template_pool::PoolElement) {
920 match element {
921 template_pool::PoolElement::Feature { feature, .. } => {
922 assert!(
923 self.placed_features.by_key(feature).is_some(),
924 "template pool references unknown placed feature {feature}"
925 );
926 }
927 template_pool::PoolElement::List { elements, .. } => {
928 for element in elements {
929 self.validate_template_pool_feature_refs(element);
930 }
931 }
932 template_pool::PoolElement::Single { .. }
933 | template_pool::PoolElement::LegacySingle { .. }
934 | template_pool::PoolElement::Empty => {}
935 }
936 }
937
938 #[must_use]
939 pub fn new_empty() -> Self {
940 Self {
941 attributes: AttributeRegistry::new(),
942 blocks: BlockRegistry::new(),
943 data_components: DataComponentRegistry::new(),
944 entity_data_serializers: EntityDataSerializerRegistry::new(),
945 items: ItemRegistry::new(),
946 biomes: BiomeRegistry::new(),
947 chat_types: ChatTypeRegistry::new(),
948 trim_patterns: TrimPatternRegistry::new(),
949 trim_materials: TrimMaterialRegistry::new(),
950 wolf_variants: WolfVariantRegistry::new(),
951 wolf_sound_variants: WolfSoundVariantRegistry::new(),
952 pig_variants: PigVariantRegistry::new(),
953 pig_sound_variants: PigSoundVariantRegistry::new(),
954 chicken_sound_variants: ChickenSoundVariantRegistry::new(),
955 cat_sound_variants: CatSoundVariantRegistry::new(),
956 cow_sound_variants: CowSoundVariantRegistry::new(),
957 frog_variants: FrogVariantRegistry::new(),
958 cat_variants: CatVariantRegistry::new(),
959 cow_variants: CowVariantRegistry::new(),
960 chicken_variants: ChickenVariantRegistry::new(),
961 painting_variants: PaintingVariantRegistry::new(),
962 particle_types: ParticleTypeRegistry::new(),
963 villager_types: VillagerTypeRegistry::new(),
964 villager_professions: VillagerProfessionRegistry::new(),
965 dimension_types: DimensionTypeRegistry::new(),
966 damage_types: DamageTypeRegistry::new(),
967 banner_patterns: BannerPatternRegistry::new(),
968 jukebox_songs: JukeboxSongRegistry::new(),
969 instruments: InstrumentRegistry::new(),
970 dialogs: DialogRegistry::new(),
971 menu_types: MenuTypeRegistry::new(),
972 mob_effects: MobEffectRegistry::new(),
973 zombie_nautilus_variants: ZombieNautilusVariantRegistry::new(),
974 timelines: TimelineRegistry::new(),
975 recipes: RecipeRegistry::new(),
976 entity_types: EntityTypeRegistry::new(),
977 loot_tables: LootTableRegistry::new(),
978 block_entity_types: BlockEntityTypeRegistry::new(),
979 game_rules: GameRuleRegistry::new(),
980 game_events: GameEventRegistry::new(),
981 sound_events: SoundEventRegistry::new(),
982 fluids: FluidRegistry::new(),
983 world_clocks: WorldClockRegistry::new(),
984 poi_types: PoiTypeRegistry::new(),
985 enchantments: EnchantmentRegistry::new(),
986 configured_carvers: ConfiguredCarverRegistry::new(),
987 configured_features: ConfiguredFeatureRegistry::new(),
988 placed_features: PlacedFeatureRegistry::new(),
989 structures: StructureRegistry::new(),
990 structure_processors: StructureProcessorListRegistry::new(),
991 }
992 }
993}
994
995#[cfg(test)]
996mod tests {
997 use std::sync::OnceLock;
998
999 use rustc_hash::FxHashMap;
1000 use steel_utils::Identifier;
1001
1002 use crate::biome::{Biome, BiomeEffects, GrassColorModifier, TemperatureModifier};
1003
1004 use super::{Registry, RegistryExt};
1005
1006 fn biome_with_refs(carvers: Vec<Identifier>, features: Vec<Vec<Identifier>>) -> &'static Biome {
1007 Box::leak(Box::new(Biome {
1008 key: Identifier::new_static("test", "missing_carver_biome"),
1009 has_precipitation: false,
1010 temperature: 0.5,
1011 downfall: 0.0,
1012 temperature_modifier: TemperatureModifier::None,
1013 effects: BiomeEffects {
1014 fog_color: 0,
1015 sky_color: 0,
1016 water_color: 0,
1017 water_fog_color: 0,
1018 foliage_color: None,
1019 grass_color: None,
1020 dry_foliage_color: None,
1021 grass_color_modifier: GrassColorModifier::None,
1022 music: None,
1023 ambient_sound: None,
1024 additions_sound: None,
1025 mood_sound: None,
1026 particle: None,
1027 },
1028 creature_spawn_probability: 0.0,
1029 spawners: FxHashMap::default(),
1030 spawn_costs: FxHashMap::default(),
1031 carvers,
1032 features,
1033 id: OnceLock::new(),
1034 }))
1035 }
1036
1037 #[test]
1038 #[should_panic(expected = "references unknown configured carver")]
1039 fn freeze_rejects_missing_biome_carver_reference() {
1040 let mut registry = Registry::new_empty();
1041 registry.biomes.register(biome_with_refs(
1042 vec![Identifier::vanilla_static("missing_carver")],
1043 Vec::new(),
1044 ));
1045
1046 registry.freeze();
1047 }
1048
1049 #[test]
1050 #[should_panic(expected = "references unknown placed feature")]
1051 fn freeze_rejects_missing_biome_placed_feature_reference() {
1052 let mut registry = Registry::new_empty();
1053 registry.biomes.register(biome_with_refs(
1054 Vec::new(),
1055 vec![vec![Identifier::vanilla_static("missing_feature")]],
1056 ));
1057
1058 registry.freeze();
1059 }
1060
1061 #[test]
1062 fn vanilla_feature_registries_initialize_and_validate() {
1063 let mut registry = Registry::new_vanilla();
1064 registry.freeze();
1065
1066 assert!(
1067 registry
1068 .configured_features
1069 .by_key(&Identifier::vanilla_static("ore_diamond_small"))
1070 .is_some()
1071 );
1072 assert!(
1073 registry
1074 .placed_features
1075 .by_key(&Identifier::vanilla_static("ore_diamond"))
1076 .is_some()
1077 );
1078 }
1079
1080 #[test]
1081 fn vanilla_static_entity_data_registries_initialize_in_vanilla_order() {
1082 let registry = Registry::new_vanilla();
1083 let entity_effect = Identifier::vanilla_static("entity_effect");
1084 let plains = Identifier::vanilla_static("plains");
1085 let none = Identifier::vanilla_static("none");
1086 let tabby = Identifier::vanilla_static("tabby");
1087 let angry = Identifier::vanilla_static("angry");
1088 let big = Identifier::vanilla_static("big");
1089 let earth = Identifier::vanilla_static("earth");
1090
1091 assert_eq!(
1092 registry.particle_types.by_id(21).map(|entry| &entry.key),
1093 Some(&entity_effect)
1094 );
1095 assert_eq!(
1096 registry.villager_types.by_id(2).map(|entry| &entry.key),
1097 Some(&plains)
1098 );
1099 assert_eq!(
1100 registry
1101 .villager_professions
1102 .by_id(0)
1103 .map(|entry| &entry.key),
1104 Some(&none)
1105 );
1106 assert_eq!(
1107 registry.cat_variants.by_id(0).map(|entry| &entry.key),
1108 Some(&tabby)
1109 );
1110 assert_eq!(
1111 registry
1112 .wolf_sound_variants
1113 .by_id(3)
1114 .map(|entry| &entry.key),
1115 Some(&angry)
1116 );
1117 assert_eq!(
1118 registry.pig_sound_variants.by_id(1).map(|entry| &entry.key),
1119 Some(&big)
1120 );
1121 assert_eq!(
1122 registry.painting_variants.by_id(25).map(|entry| &entry.key),
1123 Some(&earth)
1124 );
1125 }
1126
1127 #[test]
1128 fn vanilla_game_events_initialize_in_vanilla_order() {
1129 let registry = Registry::new_vanilla();
1130 let block_activate = Identifier::vanilla_static("block_activate");
1131 let resonate_1 = Identifier::vanilla_static("resonate_1");
1132 let resonate_10 = Identifier::vanilla_static("resonate_10");
1133
1134 assert_eq!(
1135 registry.game_events.by_id(0).map(|event| &event.key),
1136 Some(&block_activate)
1137 );
1138 assert_eq!(
1139 registry.game_events.by_id(45).map(|event| &event.key),
1140 Some(&resonate_1)
1141 );
1142 assert_eq!(
1143 registry.game_events.by_id(54).map(|event| &event.key),
1144 Some(&resonate_10)
1145 );
1146 }
1147}