Skip to main content

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(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            let listener_id = self.subscribe_to_event(|_: &mut Context, event: MyEvent| {
62                assert_eq!(event.data, 42);
63            });
64            self.emit_event(MyEvent { data: 42 });
65            assert!(self.unsubscribe_from_event(&listener_id));
66            assert!(!self.unsubscribe_from_event(&listener_id));
67            self.add_plan_with_phase(
68                1.0,
69                |context| {
70                    let data = context.get_data(MyData);
71                    assert_eq!(*data, 42);
72                    context.set_my_data(100);
73                },
74                crate::ExecutionPhase::Last,
75            );
76            self.add_plan(1.0, |context| {
77                assert_eq!(context.get_my_data(), 42);
78            });
79            self.add_passive_plan(1.0, |context| {
80                assert_eq!(context.get_my_data(), 42);
81            });
82            self.add_passive_plan_with_phase(
83                1.0,
84                |context| {
85                    assert_eq!(context.get_my_data(), 100);
86                },
87                crate::ExecutionPhase::Last,
88            );
89            let shutdown_plan = self.schedule_shutdown(2.0);
90            self.cancel_plan(&shutdown_plan);
91            self.add_periodic_plan_with_phase(
92                1.0,
93                |context| {
94                    println!(
95                        "Periodic plan at time {} with data {}",
96                        context.get_current_time(),
97                        context.get_my_data()
98                    );
99                },
100                crate::ExecutionPhase::Normal,
101            );
102            self.queue_callback(|context| {
103                let data = context.get_data(MyData);
104                assert_eq!(*data, 42);
105            });
106        }
107        fn setup(&mut self) {
108            let data = self.get_data_mut(MyData);
109            *data = 42;
110            do_stuff_with_context(self);
111        }
112        fn get_my_data(&self) -> i32 {
113            *self.get_data(MyData)
114        }
115        fn set_my_data(&mut self, value: i32) {
116            let data = self.get_data_mut(MyData);
117            *data = value;
118        }
119        fn test_external_function(&mut self) {
120            self.setup();
121            do_stuff_with_context(self);
122        }
123    }
124    impl MyDataExt for Context {}
125
126    #[test]
127    fn test_all_methods() {
128        let mut context = Context::new();
129        context.all_methods_mut();
130        context.all_methods();
131        context.execute();
132    }
133
134    #[test]
135    fn test_plugin_context() {
136        let mut context = Context::new();
137        context.setup();
138        assert_eq!(context.get_my_data(), 42);
139    }
140
141    #[test]
142    fn test_external_function() {
143        let mut context = Context::new();
144        context.test_external_function();
145        assert_eq!(context.get_my_data(), 42);
146    }
147}