amico_core/traits/
handlers.rs1use anyhow::Result;
2use evenio::event::EventMut;
3
4use crate::ecs;
5
6use super::System;
7
8pub trait Observer {
13 type Event: ecs::GlobalEvent + 'static;
15
16 fn observe(&self, event: &<Self::Event as ecs::Event>::This<'_>) -> Result<()>;
20
21 fn to_system(self) -> SystemHandler<Self, PhantomMediator>
23 where
24 Self: Sized,
25 {
26 SystemHandler::Observer(self)
27 }
28}
29
30pub trait Mediator {
37 type Event: ecs::GlobalEvent + ecs::Event<Mutability = ecs::Mutable>;
39
40 type EventsToSend: ecs::EventSet;
42
43 fn mediate(
48 &self,
49 event: &mut EventMut<'_, Self::Event>,
50 sender: ecs::Sender<Self::EventsToSend>,
51 ) -> Result<()>;
52
53 fn to_system(self) -> SystemHandler<PhantomObserver, Self>
55 where
56 Self: Sized,
57 {
58 SystemHandler::Mediator(self)
59 }
60}
61
62#[derive(ecs::GlobalEvent)]
64pub struct PhantomEvent;
65
66pub struct PhantomObserver;
68
69pub struct PhantomMediator;
71
72impl Observer for PhantomObserver {
73 type Event = PhantomEvent;
74
75 fn observe(&self, _event: &<Self::Event as ecs::Event>::This<'_>) -> Result<()> {
76 Ok(())
77 }
78}
79
80impl Mediator for PhantomMediator {
81 type Event = PhantomEvent;
82 type EventsToSend = ();
83
84 fn mediate(
85 &self,
86 _event: &mut EventMut<'_, Self::Event>,
87 _sender: ecs::Sender<Self::EventsToSend>,
88 ) -> Result<()> {
89 Ok(())
90 }
91}
92
93pub enum SystemHandler<
95 O: Observer + 'static = PhantomObserver,
96 M: Mediator + 'static = PhantomMediator,
97> {
98 Observer(O),
100
101 Mediator(M),
103}
104
105impl<O, M> System for SystemHandler<O, M>
106where
107 O: Observer + 'static,
108 M: Mediator + 'static,
109{
110 fn register_to(self, mut registry: crate::world::HandlerRegistry) {
111 match self {
112 SystemHandler::Observer(observer) => {
113 registry.register(move |r: ecs::Receiver<O::Event>| {
114 if let Err(err) = observer.observe(r.event) {
115 tracing::error!("Error in observer: {}", err);
116 }
117 })
118 }
119 SystemHandler::Mediator(mediator) => {
120 registry.register(
121 move |mut r: ecs::ReceiverMut<M::Event>,
122 sender: ecs::Sender<M::EventsToSend>| {
123 if let Err(err) = mediator.mediate(&mut r.event, sender) {
124 tracing::error!("Error in mediator: {}", err);
125 }
126
127 EventMut::take(r.event);
129 },
130 )
131 }
132 }
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use evenio::prelude::*;
139
140 use crate::world::HandlerRegistry;
141
142 use super::*;
143
144 #[derive(ecs::GlobalEvent)]
145 struct TestEvent(i32);
146
147 #[derive(ecs::GlobalEvent)]
148 struct TestEvent2(i32);
149
150 struct TestObserver;
151
152 impl Observer for TestObserver {
153 type Event = TestEvent;
154
155 fn observe(&self, event: &<Self::Event as ecs::Event>::This<'_>) -> Result<()> {
156 let TestEvent(_) = event;
157 Ok(())
158 }
159 }
160
161 struct TestMediator;
162
163 impl Mediator for TestMediator {
164 type Event = TestEvent;
165 type EventsToSend = TestEvent2;
166
167 fn mediate(
168 &self,
169 event: &mut EventMut<'_, Self::Event>,
170 mut sender: ecs::Sender<Self::EventsToSend>,
171 ) -> Result<()> {
172 let num = event.0;
173
174 sender.send(TestEvent2(num * 2));
175
176 Ok(())
177 }
178 }
179
180 #[test]
181 fn test_mediator() {
182 let mut world = World::new();
184 let mediator = TestMediator;
185 let observer = TestObserver;
186
187 world.add_handler(|r: ecs::Receiver<TestEvent>| {
189 assert_eq!(r.event.0, 1);
190 });
191 world.add_handler(|r: ecs::Receiver<TestEvent2>| {
192 assert_eq!(r.event.0, 2);
193 });
194
195 mediator
196 .to_system()
197 .register_to(HandlerRegistry { world: &mut world });
198
199 observer
200 .to_system()
201 .register_to(HandlerRegistry { world: &mut world });
202
203 world.send(TestEvent(1));
205 }
206}