pabitell_lib/
events.rs

1use crate::{
2    conditions::Condition,
3    data::{self, EventData},
4    updates::Change,
5    AsAny, Event, GeoLocation, Tagged, World,
6};
7use std::{any::Any, fmt};
8
9pub type Text = Option<Box<dyn Fn(&dyn Event, &dyn World) -> String>>;
10
11#[derive(Default)]
12pub struct Pick {
13    name: String,
14    data: data::PickData,
15    tags: Vec<String>,
16    world_updates: Vec<Box<dyn Change>>,
17    condition: Condition,
18}
19
20impl fmt::Debug for Pick {
21    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        f.debug_struct(&format!("Pick({})", self.name()))
23            .field("character", &self.data.character)
24            .field("item", &self.data.item)
25            .finish()
26    }
27}
28
29impl Tagged for Pick {
30    fn set_tags(&mut self, tags: Vec<String>) {
31        self.tags = tags;
32    }
33
34    fn get_tags(&self) -> Vec<String> {
35        self.tags.clone()
36    }
37}
38
39impl AsAny for Pick {
40    fn as_any(&self) -> &dyn Any {
41        self
42    }
43    fn as_any_mut(&mut self) -> &mut dyn Any {
44        self
45    }
46}
47
48impl PartialEq<[u8]> for Pick {
49    fn eq(&self, other: &[u8]) -> bool {
50        if let Ok(other_data) = serde_json::from_slice::<data::PickData>(other) {
51            self.data == other_data
52        } else {
53            false
54        }
55    }
56}
57
58impl Event for Pick {
59    fn name(&self) -> &str {
60        &self.name
61    }
62
63    fn initiator(&self) -> String {
64        self.data.initiator()
65    }
66
67    fn set_initiator(&mut self, initiator: String) {
68        self.data.set_initiator(initiator)
69    }
70
71    fn set_world_updates(&mut self, updates: Vec<Box<dyn Change>>) {
72        self.world_updates = updates;
73    }
74
75    fn set_condition(&mut self, condition: Condition) {
76        self.condition = condition;
77    }
78
79    fn get_world_updates(&self) -> &[Box<dyn Change>] {
80        &self.world_updates
81    }
82
83    fn get_condition(&self) -> &Condition {
84        &self.condition
85    }
86
87    fn dump(&self) -> serde_json::Value {
88        let mut res = serde_json::to_value(self.data.clone()).unwrap();
89        res["name"] = serde_json::Value::String(self.name().to_string());
90        res
91    }
92
93    fn matches(&self, value: &serde_json::Value) -> bool {
94        &self.dump() == value
95    }
96
97    fn items(&self) -> Vec<String> {
98        vec![self.data.item.to_string()]
99    }
100
101    fn characters(&self) -> Vec<String> {
102        vec![self.character().to_string()]
103    }
104
105    fn msg_base(&self, world: &dyn World) -> String {
106        format!("{}-{}_{}", world.name(), self.character(), self.name(),)
107    }
108}
109
110impl Pick {
111    pub fn new<S>(name: S, data: data::PickData) -> Self
112    where
113        S: ToString,
114    {
115        Self {
116            name: name.to_string(),
117            data,
118            ..Default::default()
119        }
120    }
121
122    pub fn character(&self) -> &str {
123        &self.data.character
124    }
125
126    pub fn item(&self) -> &str {
127        &self.data.item
128    }
129}
130
131#[derive(Default)]
132pub struct Give {
133    name: String,
134    data: data::GiveData,
135    tags: Vec<String>,
136    world_updates: Vec<Box<dyn Change>>,
137    condition: Condition,
138}
139
140impl fmt::Debug for Give {
141    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142        f.debug_struct(&format!("Give({})", self.name()))
143            .field("from_character", &self.data.from_character)
144            .field("to_character", &self.data.to_character)
145            .field("item", &self.data.item)
146            .finish()
147    }
148}
149
150impl Tagged for Give {
151    fn set_tags(&mut self, tags: Vec<String>) {
152        self.tags = tags;
153    }
154
155    fn get_tags(&self) -> Vec<String> {
156        self.tags.clone()
157    }
158}
159
160impl AsAny for Give {
161    fn as_any(&self) -> &dyn Any {
162        self
163    }
164    fn as_any_mut(&mut self) -> &mut dyn Any {
165        self
166    }
167}
168
169impl PartialEq<[u8]> for Give {
170    fn eq(&self, other: &[u8]) -> bool {
171        if let Ok(other_data) = serde_json::from_slice::<data::GiveData>(other) {
172            self.data == other_data
173        } else {
174            false
175        }
176    }
177}
178
179impl Event for Give {
180    fn name(&self) -> &str {
181        &self.name
182    }
183
184    fn initiator(&self) -> String {
185        self.data.initiator()
186    }
187
188    fn set_initiator(&mut self, initiator: String) {
189        self.data.set_initiator(initiator);
190    }
191
192    fn set_world_updates(&mut self, updates: Vec<Box<dyn Change>>) {
193        self.world_updates = updates;
194    }
195
196    fn set_condition(&mut self, condition: Condition) {
197        self.condition = condition;
198    }
199
200    fn get_world_updates(&self) -> &[Box<dyn Change>] {
201        &self.world_updates
202    }
203
204    fn get_condition(&self) -> &Condition {
205        &self.condition
206    }
207
208    fn dump(&self) -> serde_json::Value {
209        let mut res = serde_json::to_value(self.data.clone()).unwrap();
210        res["name"] = serde_json::Value::String(self.name().to_string());
211        res
212    }
213
214    fn matches(&self, value: &serde_json::Value) -> bool {
215        &self.dump() == value
216    }
217
218    fn items(&self) -> Vec<String> {
219        vec![self.data.item.to_string()]
220    }
221
222    fn characters(&self) -> Vec<String> {
223        vec![
224            self.from_character().to_string(),
225            self.to_character().to_string(),
226        ]
227    }
228
229    fn msg_base(&self, world: &dyn World) -> String {
230        format!(
231            "{}-{}_give_{}_to_{}",
232            world.name(),
233            self.from_character(),
234            self.item(),
235            self.to_character(),
236        )
237    }
238}
239
240impl Give {
241    pub fn new<S>(name: S, data: data::GiveData) -> Self
242    where
243        S: ToString,
244    {
245        Self {
246            name: name.to_string(),
247            data,
248            ..Default::default()
249        }
250    }
251
252    pub fn from_character(&self) -> &str {
253        &self.data.from_character
254    }
255
256    pub fn to_character(&self) -> &str {
257        &self.data.to_character
258    }
259
260    pub fn item(&self) -> &str {
261        &self.data.item
262    }
263}
264
265#[derive(Default)]
266pub struct UseItem {
267    name: String,
268    data: data::UseItemData,
269    tags: Vec<String>,
270    world_updates: Vec<Box<dyn Change>>,
271    condition: Condition,
272}
273
274impl fmt::Debug for UseItem {
275    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276        f.debug_struct(&format!("UseItem({})", self.name()))
277            .field("character", &self.data.character)
278            .field("item", &self.data.item)
279            .finish()
280    }
281}
282
283impl Tagged for UseItem {
284    fn set_tags(&mut self, tags: Vec<String>) {
285        self.tags = tags;
286    }
287
288    fn get_tags(&self) -> Vec<String> {
289        self.tags.clone()
290    }
291}
292
293impl AsAny for UseItem {
294    fn as_any(&self) -> &dyn Any {
295        self
296    }
297    fn as_any_mut(&mut self) -> &mut dyn Any {
298        self
299    }
300}
301
302impl PartialEq<[u8]> for UseItem {
303    fn eq(&self, other: &[u8]) -> bool {
304        if let Ok(other_data) = serde_json::from_slice::<data::UseItemData>(other) {
305            self.data == other_data
306        } else {
307            false
308        }
309    }
310}
311
312impl Event for UseItem {
313    fn name(&self) -> &str {
314        &self.name
315    }
316
317    fn initiator(&self) -> String {
318        self.data.initiator()
319    }
320
321    fn set_initiator(&mut self, initiator: String) {
322        self.data.set_initiator(initiator)
323    }
324
325    fn set_world_updates(&mut self, updates: Vec<Box<dyn Change>>) {
326        self.world_updates = updates;
327    }
328
329    fn set_condition(&mut self, condition: Condition) {
330        self.condition = condition;
331    }
332
333    fn get_world_updates(&self) -> &[Box<dyn Change>] {
334        &self.world_updates
335    }
336
337    fn get_condition(&self) -> &Condition {
338        &self.condition
339    }
340
341    fn dump(&self) -> serde_json::Value {
342        let mut res = serde_json::to_value(self.data.clone()).unwrap();
343        res["name"] = serde_json::Value::String(self.name().to_string());
344        res
345    }
346
347    fn matches(&self, value: &serde_json::Value) -> bool {
348        &self.dump() == value
349    }
350
351    fn items(&self) -> Vec<String> {
352        vec![self.data.item.to_string()]
353    }
354
355    fn characters(&self) -> Vec<String> {
356        vec![self.character().to_string()]
357    }
358
359    fn msg_base(&self, world: &dyn World) -> String {
360        format!("{}-{}_{}", world.name(), self.character(), self.name(),)
361    }
362}
363
364impl UseItem {
365    pub fn new<S>(name: S, data: data::UseItemData) -> Self
366    where
367        S: ToString,
368    {
369        Self {
370            name: name.to_string(),
371            data,
372            ..Default::default()
373        }
374    }
375
376    pub fn character(&self) -> &str {
377        &self.data.character
378    }
379
380    pub fn item(&self) -> &str {
381        &self.data.item
382    }
383}
384
385#[derive(Default)]
386pub struct Move {
387    name: String,
388    data: data::MoveData,
389    tags: Vec<String>,
390    world_updates: Vec<Box<dyn Change>>,
391    condition: Condition,
392}
393
394impl fmt::Debug for Move {
395    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
396        f.debug_struct(&format!("Move({})", self.name()))
397            .field("character", &self.data.character)
398            .field("to_scene", &self.data.scene)
399            .finish()
400    }
401}
402
403impl Tagged for Move {
404    fn set_tags(&mut self, tags: Vec<String>) {
405        self.tags = tags;
406    }
407
408    fn get_tags(&self) -> Vec<String> {
409        self.tags.clone()
410    }
411}
412
413impl AsAny for Move {
414    fn as_any(&self) -> &dyn Any {
415        self
416    }
417    fn as_any_mut(&mut self) -> &mut dyn Any {
418        self
419    }
420}
421
422impl PartialEq<[u8]> for Move {
423    fn eq(&self, other: &[u8]) -> bool {
424        if let Ok(other_data) = serde_json::from_slice::<data::MoveData>(other) {
425            self.data == other_data
426        } else {
427            false
428        }
429    }
430}
431
432impl Event for Move {
433    fn name(&self) -> &str {
434        &self.name
435    }
436
437    fn initiator(&self) -> String {
438        self.data.initiator()
439    }
440
441    fn set_initiator(&mut self, initiator: String) {
442        self.data.set_initiator(initiator)
443    }
444
445    fn set_world_updates(&mut self, updates: Vec<Box<dyn Change>>) {
446        self.world_updates = updates;
447    }
448
449    fn set_condition(&mut self, condition: Condition) {
450        self.condition = condition;
451    }
452
453    fn get_world_updates(&self) -> &[Box<dyn Change>] {
454        &self.world_updates
455    }
456
457    fn get_condition(&self) -> &Condition {
458        &self.condition
459    }
460
461    fn dump(&self) -> serde_json::Value {
462        let mut res = serde_json::to_value(self.data.clone()).unwrap();
463        res["name"] = serde_json::Value::String(self.name().to_string());
464        res
465    }
466
467    fn matches(&self, value: &serde_json::Value) -> bool {
468        &self.dump() == value
469    }
470
471    fn items(&self) -> Vec<String> {
472        vec![]
473    }
474
475    fn characters(&self) -> Vec<String> {
476        vec![self.character().to_string()]
477    }
478
479    fn msg_base(&self, world: &dyn World) -> String {
480        format!("{}-{}_{}", world.name(), self.character(), self.name(),)
481    }
482
483    fn geo_location(&self, world: &dyn World) -> Option<(String, Option<String>, GeoLocation)> {
484        let scene = world.scenes().get(&self.data.scene).unwrap();
485        scene.geo_location().map(|loc| {
486            (
487                self.character().to_string(),
488                Some(scene.name().to_string()),
489                loc,
490            )
491        })
492    }
493}
494
495impl Move {
496    pub fn new<S>(name: S, data: data::MoveData) -> Self
497    where
498        S: ToString,
499    {
500        Self {
501            name: name.to_string(),
502            data,
503            ..Default::default()
504        }
505    }
506
507    pub fn character(&self) -> &str {
508        &self.data.character
509    }
510
511    pub fn scene(&self) -> &str {
512        &self.data.scene
513    }
514}
515
516#[derive(Default)]
517pub struct Void {
518    name: String,
519    data: data::VoidData,
520    tags: Vec<String>,
521    world_updates: Vec<Box<dyn Change>>,
522    condition: Condition,
523}
524
525impl fmt::Debug for Void {
526    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527        f.debug_struct(&format!("Void({})", self.name()))
528            .field("character", &self.data.character)
529            .field("item", &self.data.item)
530            .finish()
531    }
532}
533
534impl Tagged for Void {
535    fn set_tags(&mut self, tags: Vec<String>) {
536        self.tags = tags;
537    }
538
539    fn get_tags(&self) -> Vec<String> {
540        self.tags.clone()
541    }
542}
543
544impl AsAny for Void {
545    fn as_any(&self) -> &dyn Any {
546        self
547    }
548    fn as_any_mut(&mut self) -> &mut dyn Any {
549        self
550    }
551}
552
553impl PartialEq<[u8]> for Void {
554    fn eq(&self, other: &[u8]) -> bool {
555        if let Ok(other_data) = serde_json::from_slice::<data::VoidData>(other) {
556            self.data == other_data
557        } else {
558            false
559        }
560    }
561}
562
563impl Event for Void {
564    fn name(&self) -> &str {
565        &self.name
566    }
567
568    fn initiator(&self) -> String {
569        self.data.initiator()
570    }
571
572    fn set_initiator(&mut self, initiator: String) {
573        self.data.set_initiator(initiator)
574    }
575
576    fn set_world_updates(&mut self, updates: Vec<Box<dyn Change>>) {
577        self.world_updates = updates;
578    }
579
580    fn set_condition(&mut self, condition: Condition) {
581        self.condition = condition;
582    }
583
584    fn get_world_updates(&self) -> &[Box<dyn Change>] {
585        &self.world_updates
586    }
587
588    fn get_condition(&self) -> &Condition {
589        &self.condition
590    }
591
592    fn dump(&self) -> serde_json::Value {
593        let mut res = serde_json::to_value(self.data.clone()).unwrap();
594        res["name"] = serde_json::Value::String(self.name().to_string());
595        res
596    }
597
598    fn matches(&self, value: &serde_json::Value) -> bool {
599        &self.dump() == value
600    }
601
602    fn items(&self) -> Vec<String> {
603        if let Some(item) = self.data.item.as_ref() {
604            vec![item.to_string()]
605        } else {
606            vec![]
607        }
608    }
609
610    fn characters(&self) -> Vec<String> {
611        vec![self.character().to_string()]
612    }
613
614    fn msg_base(&self, world: &dyn World) -> String {
615        format!(
616            "{}-{}_{}_{}",
617            world.name(),
618            self.character(),
619            self.name(),
620            self.item().clone().unwrap_or_default(),
621        )
622    }
623}
624
625impl Void {
626    pub fn new<S>(name: S, data: data::VoidData) -> Self
627    where
628        S: ToString,
629    {
630        Self {
631            name: name.to_string(),
632            data,
633            ..Default::default()
634        }
635    }
636
637    pub fn character(&self) -> &str {
638        &self.data.character
639    }
640
641    pub fn item(&self) -> &Option<String> {
642        &self.data.item
643    }
644}
645
646#[derive(Default)]
647pub struct Talk {
648    name: String,
649    data: data::TalkData,
650    tags: Vec<String>,
651    world_updates: Vec<Box<dyn Change>>,
652    condition: Condition,
653}
654
655impl fmt::Debug for Talk {
656    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
657        f.debug_struct(&format!("Talk({})", self.name()))
658            .field("character", &self.data.character)
659            .field("item", &self.data.scene)
660            .field("dialog", &self.data.dialog)
661            .finish()
662    }
663}
664
665impl Tagged for Talk {
666    fn set_tags(&mut self, tags: Vec<String>) {
667        self.tags = tags;
668    }
669
670    fn get_tags(&self) -> Vec<String> {
671        self.tags.clone()
672    }
673}
674
675impl AsAny for Talk {
676    fn as_any(&self) -> &dyn Any {
677        self
678    }
679    fn as_any_mut(&mut self) -> &mut dyn Any {
680        self
681    }
682}
683
684impl PartialEq<[u8]> for Talk {
685    fn eq(&self, other: &[u8]) -> bool {
686        if let Ok(other_data) = serde_json::from_slice::<data::TalkData>(other) {
687            self.data == other_data
688        } else {
689            false
690        }
691    }
692}
693
694impl Event for Talk {
695    fn name(&self) -> &str {
696        &self.name
697    }
698
699    fn initiator(&self) -> String {
700        self.data.initiator()
701    }
702
703    fn set_initiator(&mut self, initiator: String) {
704        self.data.set_initiator(initiator)
705    }
706
707    fn set_world_updates(&mut self, updates: Vec<Box<dyn Change>>) {
708        self.world_updates = updates;
709    }
710
711    fn set_condition(&mut self, condition: Condition) {
712        self.condition = condition;
713    }
714
715    fn get_world_updates(&self) -> &[Box<dyn Change>] {
716        &self.world_updates
717    }
718
719    fn get_condition(&self) -> &Condition {
720        &self.condition
721    }
722
723    fn dump(&self) -> serde_json::Value {
724        let mut res = serde_json::to_value(self.data.clone()).unwrap();
725        res["name"] = serde_json::Value::String(self.name().to_string());
726        res
727    }
728
729    fn matches(&self, value: &serde_json::Value) -> bool {
730        &self.dump() == value
731    }
732
733    fn items(&self) -> Vec<String> {
734        vec![]
735    }
736
737    fn characters(&self) -> Vec<String> {
738        vec![self.character().to_string()]
739    }
740
741    fn msg_base(&self, world: &dyn World) -> String {
742        format!(
743            "{}-{}_{}_says-{}",
744            world.name(),
745            self.scene(),
746            self.character(),
747            self.dialog()
748        )
749    }
750}
751
752impl Talk {
753    pub fn new<S>(name: S, data: data::TalkData) -> Self
754    where
755        S: ToString,
756    {
757        Self {
758            name: name.to_string(),
759            data,
760            ..Default::default()
761        }
762    }
763
764    pub fn character(&self) -> &str {
765        &self.data.character
766    }
767
768    pub fn scene(&self) -> &str {
769        &self.data.scene
770    }
771
772    pub fn dialog(&self) -> usize {
773        self.data.dialog
774    }
775}
776
777#[cfg(test)]
778pub mod test {
779    use super::{Give, Move, Pick, Talk, UseItem, Void};
780    use crate::{data, Event};
781
782    #[test]
783    fn kinds() {
784        let pick = Pick::new("pick", data::PickData::new("character", "item"));
785        assert_eq!(pick.kind(), "Pick");
786
787        let give = Give::new(
788            "give",
789            data::GiveData::new("from_character", "to_character", "item"),
790        );
791        assert_eq!(give.kind(), "Give");
792
793        let move_event = Move::new("move", data::MoveData::new("character", "to_scene"));
794        assert_eq!(move_event.kind(), "Move");
795
796        let use_item = UseItem::new("use_item", data::UseItemData::new("character", "item"));
797        assert_eq!(use_item.kind(), "UseItem");
798
799        let void = Void::new(
800            "void",
801            data::VoidData::new("character", None as Option<String>),
802        );
803        assert_eq!(void.kind(), "Void");
804
805        let talk = Talk::new("talk", data::TalkData::new("character", "scene", 0));
806        assert_eq!(talk.kind(), "Talk");
807    }
808}