1use rustc_hash::FxHashMap;
2use simdnbt::ToNbtTag;
3use simdnbt::owned::NbtTag;
4use steel_utils::Identifier;
5use text_components::{EmbeddedNbtCodec, TextComponent};
6
7use crate::RegistryTags;
8
9#[derive(Debug)]
11pub struct Dialog {
12 pub key: Identifier,
13 pub button_width: i32,
14 pub columns: i32,
15 pub exit_action: ExitAction,
16 pub external_title: TextComponent,
17 pub title: TextComponent,
18 pub variant: DialogVariant,
19}
20
21#[derive(Debug)]
23pub enum DialogVariant {
24 DialogList { dialogs: &'static str },
26 ServerLinks,
28}
29
30#[derive(Debug)]
32pub struct ExitAction {
33 pub label: TextComponent,
34 pub width: i32,
35}
36
37impl ToNbtTag for &Dialog {
38 fn to_nbt_tag(self) -> NbtTag {
39 use simdnbt::owned::NbtCompound;
40 let mut compound = NbtCompound::new();
41 compound.insert(
42 "type",
43 match &self.variant {
44 DialogVariant::DialogList { .. } => "minecraft:dialog_list",
45 DialogVariant::ServerLinks => "minecraft:server_links",
46 },
47 );
48 compound.insert("title", self.title.to_codec_nbt());
49 compound.insert("external_title", self.external_title.to_codec_nbt());
50 compound.insert("button_width", self.button_width);
51 compound.insert("columns", self.columns);
52 let mut exit_action = NbtCompound::new();
53 exit_action.insert("label", self.exit_action.label.to_codec_nbt());
54 exit_action.insert("width", self.exit_action.width);
55 compound.insert("exit_action", NbtTag::Compound(exit_action));
56 if let DialogVariant::DialogList { dialogs } = &self.variant {
57 compound.insert("dialogs", *dialogs);
58 }
59 NbtTag::Compound(compound)
60 }
61}
62
63impl EmbeddedNbtCodec for &Dialog {
64 type Error = std::convert::Infallible;
65
66 fn encode_embedded_nbt(self) -> Result<NbtTag, Self::Error> {
67 Ok(self.to_nbt_tag())
68 }
69}
70
71pub type DialogRef = &'static Dialog;
72
73pub struct DialogRegistry {
74 dialogs_by_id: Vec<DialogRef>,
75 dialogs_by_key: FxHashMap<Identifier, usize>,
76 tags: RegistryTags,
77 allows_registering: bool,
78}
79
80impl DialogRegistry {
81 #[must_use]
82 pub fn new() -> Self {
83 Self {
84 dialogs_by_id: Vec::new(),
85 dialogs_by_key: FxHashMap::default(),
86 tags: RegistryTags::default(),
87 allows_registering: true,
88 }
89 }
90}
91
92crate::impl_standard_methods!(
93 DialogRegistry,
94 DialogRef,
95 dialogs_by_id,
96 dialogs_by_key,
97 allows_registering
98);
99
100crate::impl_registry!(
101 DialogRegistry,
102 Dialog,
103 dialogs_by_id,
104 dialogs_by_key,
105 dialogs
106);
107crate::impl_tagged_registry!(DialogRegistry, dialogs_by_key, "dialog");