ixa/
plugin_context.rs

1use crate::context::{Context, ContextBase};
2use crate::{
3    ContextEntitiesExt, ContextGlobalPropertiesExt, ContextNetworkExt, ContextRandomExt,
4    ContextReportExt,
5};
6
7/// A supertrait that exposes useful methods from [`Context`]
8/// for plugins implementing [`Context`] extensions.
9///
10/// Usage:
11// This example uses ctor-based registration, which is not supported
12// on every rustdoc target, so we ignore it.
13/// ```ignore
14/// use ixa::prelude_for_plugins::*;
15/// define_data_plugin!(MyData, bool, false);
16/// pub trait MyPlugin: PluginContext {
17///     fn set_my_data(&mut self) {
18///         let my_data = self.get_data_container_mut(MyData);
19///         *my_data = true;
20///     }
21/// }
22pub trait PluginContext:
23    ContextBase
24    + ContextRandomExt
25    + ContextReportExt
26    + ContextNetworkExt
27    + ContextGlobalPropertiesExt
28    + ContextEntitiesExt
29{
30}
31
32impl PluginContext for Context {}
33
34// Tests for the PluginContext trait, including:
35// - Making sure all the methods work identically to Context
36// - Defining a trait extension that uses it compiles correctly
37// - External functions can use impl PluginContext if necessary
38#[cfg(test)]
39mod test_plugin_context {
40    use crate::prelude_for_plugins::*;
41    #[derive(Copy, Clone, IxaEvent)]
42    struct MyEvent {
43        pub data: usize,
44    }
45
46    define_data_plugin!(MyData, i32, 0);
47
48    fn do_stuff_with_context(context: &mut impl PluginContext) {
49        context.add_plan(1.0, |context| {
50            let data = context.get_data(MyData);
51            assert_eq!(*data, 42);
52        });
53    }
54
55    trait MyDataExt: PluginContext {
56        fn all_methods(&mut self) {
57            assert_eq!(self.get_current_time(), 0.0);
58        }
59        fn all_methods_mut(&mut self) {
60            self.setup();
61            self.subscribe_to_event(|_: &mut Context, event: MyEvent| {
62                assert_eq!(event.data, 42);
63            });
64            self.emit_event(MyEvent { data: 42 });
65            self.add_plan_with_phase(
66                1.0,
67                |context| {
68                    let data = context.get_data(MyData);
69                    assert_eq!(*data, 42);
70                    context.set_my_data(100);
71                },
72                crate::ExecutionPhase::Last,
73            );
74            self.add_plan(1.0, |context| {
75                assert_eq!(context.get_my_data(), 42);
76            });
77            self.add_periodic_plan_with_phase(
78                1.0,
79                |context| {
80                    println!(
81                        "Periodic plan at time {} with data {}",
82                        context.get_current_time(),
83                        context.get_my_data()
84                    );
85                },
86                crate::ExecutionPhase::Normal,
87            );
88            self.queue_callback(|context| {
89                let data = context.get_data(MyData);
90                assert_eq!(*data, 42);
91            });
92        }
93        fn setup(&mut self) {
94            let data = self.get_data_mut(MyData);
95            *data = 42;
96            do_stuff_with_context(self);
97        }
98        fn get_my_data(&self) -> i32 {
99            *self.get_data(MyData)
100        }
101        fn set_my_data(&mut self, value: i32) {
102            let data = self.get_data_mut(MyData);
103            *data = value;
104        }
105        fn test_external_function(&mut self) {
106            self.setup();
107            do_stuff_with_context(self);
108        }
109    }
110    impl MyDataExt for Context {}
111
112    #[test]
113    fn test_all_methods() {
114        let mut context = Context::new();
115        context.all_methods_mut();
116        context.all_methods();
117        context.execute();
118    }
119
120    #[test]
121    fn test_plugin_context() {
122        let mut context = Context::new();
123        context.setup();
124        assert_eq!(context.get_my_data(), 42);
125    }
126
127    #[test]
128    fn test_external_function() {
129        let mut context = Context::new();
130        context.test_external_function();
131        assert_eq!(context.get_my_data(), 42);
132    }
133}