pabitell_lib/
scenes.rs

1#[macro_export]
2macro_rules! scene_base {
3    ($class_name: ident, $name: literal, [$( $tag:expr ),* ]) => {
4        #[derive(Debug, Default)]
5        pub struct $class_name {
6            id: uuid::Uuid,
7            location: Option<$crate::GeoLocation>,
8        }
9
10        impl $crate::Named for $class_name {
11            fn name(&self) -> &'static str {
12                $name
13            }
14        }
15
16        impl $crate::Tagged for $class_name {
17            fn get_tags(&self) -> Vec<String> {
18                #[allow(unused_mut)]
19                let mut res: Vec<String> = vec![];
20                $(
21                    res.push($tag.into());
22                )*
23                res
24            }
25        }
26
27        impl AsAny for $class_name {
28            fn as_any(&self) -> &dyn Any {
29                self
30            }
31            fn as_any_mut(&mut self) -> &mut dyn Any {
32                self
33            }
34        }
35
36
37        impl $crate::Dumpable for $class_name {
38            fn dump(&self) -> serde_json::Value {
39                serde_json::json!(
40                    {
41                        "name": self.name(),
42                        "location": self.location,
43                    }
44                )
45            }
46            fn load(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
47                let location: Option<$crate::GeoLocation> = serde_json::from_value(data["location"].clone())?;
48                self.location = location;
49                Ok(())  // Scenes doesn't cotain any extras here
50            }
51        }
52
53        impl $crate::Scene for $class_name {
54            fn geo_location(&self) -> Option<$crate::GeoLocation> {
55                self.location
56            }
57
58            fn set_geo_location(&mut self, location: Option<$crate::GeoLocation>) {
59                self.location = location
60            }
61        }
62
63        impl $crate::Clean for $class_name {
64            fn clean(&mut self) {}
65        }
66    };
67}
68
69#[macro_export]
70macro_rules! scene_no_music {
71    ($class_name: ident) => {
72        impl Music for $class_name {}
73    };
74}
75
76#[macro_export]
77macro_rules! scene_with_dialog {
78    ($class_name: ident, $name: literal, [$( $tag:expr ),* ]) => {
79        #[derive(Debug, Default)]
80        pub struct $class_name {
81            id: uuid::Uuid,
82            dialog: usize,
83            location: Option<$crate::GeoLocation>,
84        }
85
86        impl $crate::Named for $class_name {
87            fn name(&self) -> &'static str {
88                $name
89            }
90        }
91
92        impl $crate::Tagged for $class_name {
93            fn get_tags(&self) -> Vec<String> {
94                #[allow(unused_mut)]
95                let mut res: Vec<String> = vec![];
96                $(
97                    res.push($tag.into());
98                )*
99                res
100            }
101        }
102
103        impl AsAny for $class_name {
104            fn as_any(&self) -> &dyn Any {
105                self
106            }
107            fn as_any_mut(&mut self) -> &mut dyn Any {
108                self
109            }
110        }
111
112
113        impl $crate::Dumpable for $class_name {
114            fn dump(&self) -> serde_json::Value {
115                serde_json::json!(
116                    {
117                        "name": self.name(),
118                        "dialog": self.dialog,
119                        "location": self.location,
120                    }
121                )
122            }
123
124            fn load(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
125                if let Value::Number(number) = &data["dialog"] {
126                    if let Some(dialog) = number.as_u64() {
127                        self.dialog = dialog as usize;
128                    } else {
129                        return Err(anyhow!("Wrong dialog field '{}'", number));
130                    }
131                } else {
132                    return Err(anyhow!("Scene format '{}'", self.name()));
133                }
134
135                let location: Option<$crate::GeoLocation> = serde_json::from_value(data["location"].clone())?;
136                self.location = location;
137
138
139                Ok(())
140            }
141        }
142
143        impl $crate::Scene for $class_name {
144            fn dialog(&self) -> Option<usize> {
145                Some(self.dialog)
146            }
147
148            fn next_dialog(&mut self) {
149                self.dialog += 1
150            }
151
152            fn geo_location(&self) -> Option<$crate::GeoLocation> {
153                self.location
154            }
155
156            fn set_geo_location(&mut self, location: Option<$crate::GeoLocation>) {
157                self.location = location
158            }
159        }
160
161        impl $crate::Description for $class_name {
162            fn long(&self, world: &dyn World) -> String {
163                world.get_message(
164                    &format!("{}-{}-long-{}", world.name(), self.name(), self.dialog),
165                    None,
166                )
167            }
168
169            fn short(&self, world: &dyn World) -> String {
170                world.get_message(
171                    &format!("{}-{}-short", world.name(), self.name()),
172                    None,
173                )
174            }
175        }
176
177        impl $crate::Clean for $class_name {
178            fn clean(&mut self) {
179                self.dialog = 0;
180            }
181        }
182    };
183}