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}