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(()) }
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}