Skip to main content

steel_registry/
dialog.rs

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/// Represents a dialog defined in data packs.
10#[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/// The variant-specific data for a dialog.
22#[derive(Debug)]
23pub enum DialogVariant {
24    /// A dialog that displays a list of other dialogs.
25    DialogList { dialogs: &'static str },
26    /// A dialog that displays server links.
27    ServerLinks,
28}
29
30/// Represents an exit action with a label and width.
31#[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");