1use crate::battle::{Battle, BattleRules, BattleState, Version};
4use crate::error::{WeaselError, WeaselResult};
5use crate::player::PlayerId;
6use crate::team::TeamId;
7use crate::user::UserEventId;
8use log::error;
9#[cfg(feature = "serialization")]
10use serde::{Deserialize, Serialize};
11use std::any::Any;
12use std::fmt::{Debug, Formatter, Result};
13use std::marker::PhantomData;
14use std::ops::{Deref, Range};
15
16pub type EventId = u32;
18
19#[derive(Copy, Clone, PartialEq, Debug)]
23pub enum EventKind {
24 DummyEvent,
26 CreateTeam,
28 CreateCreature,
30 CreateObject,
32 MoveEntity,
34 StartTurn,
36 EndTurn,
38 EndRound,
40 EnvironmentTurn,
42 ActivateAbility,
44 InvokePower,
46 ApplyImpact,
48 AlterStatistics,
50 AlterStatuses,
52 AlterAbilities,
54 AlterPowers,
56 RegenerateStatistics,
58 RegenerateAbilities,
60 RegeneratePowers,
62 InflictStatus,
64 ClearStatus,
66 ConvertCreature,
68 SetRelations,
70 ConcludeObjectives,
72 RemoveCreature,
74 RemoveObject,
76 RemoveTeam,
78 AlterSpace,
80 ResetEntropy,
82 ResetObjectives,
84 ResetRounds,
86 ResetSpace,
88 EndBattle,
90 UserEvent(UserEventId),
92}
93
94pub enum EventRights<'a, R: BattleRules> {
96 None,
98 Server,
100 Team(&'a TeamId<R>),
102 Teams(Vec<&'a TeamId<R>>),
104}
105
106impl<'a, R: BattleRules> Debug for EventRights<'a, R> {
107 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
108 use EventRights::*;
109 match self {
110 None => write!(f, "EventRights::None"),
111 Server => write!(f, "EventRights::Server"),
112 Team(id) => write!(f, "EventRights::Team {{ {:?} }}", id),
113 Teams(ids) => write!(f, "EventRights::Teams {{ {:?} }}", ids),
114 }
115 }
116}
117
118impl<'a, 'b, R: BattleRules> PartialEq<EventRights<'b, R>> for EventRights<'a, R> {
119 fn eq(&self, other: &EventRights<'b, R>) -> bool {
120 use EventRights::*;
121 match (self, other) {
122 (None, None) => true,
123 (Server, Server) => true,
124 (Team(a), Team(b)) => a == b,
125 (Teams(a), Teams(b)) => a == b,
126 _ => false,
127 }
128 }
129}
130
131impl<'a, R: BattleRules> Eq for EventRights<'a, R> {}
132
133pub trait Event<R: BattleRules>: Debug {
135 fn verify(&self, battle: &Battle<R>) -> WeaselResult<(), R>;
137
138 fn apply(&self, battle: &mut Battle<R>, queue: &mut Option<EventQueue<R>>);
146
147 fn kind(&self) -> EventKind;
149
150 fn box_clone(&self) -> Box<dyn Event<R> + Send>;
152
153 fn as_any(&self) -> &dyn Any;
155
156 fn rights<'a>(&'a self, _battle: &'a Battle<R>) -> EventRights<'a, R> {
160 EventRights::Server
161 }
162}
163
164impl<R: BattleRules> Clone for Box<dyn Event<R> + Send> {
165 fn clone(&self) -> Box<dyn Event<R> + Send> {
166 self.box_clone()
167 }
168}
169
170impl<R: BattleRules> PartialEq<Box<dyn Event<R> + Send>> for Box<dyn Event<R> + Send> {
171 fn eq(&self, other: &Box<dyn Event<R> + Send>) -> bool {
172 self.kind() == other.kind()
173 }
174}
175
176pub struct EventWrapper<R: BattleRules> {
178 id: EventId,
180 origin: Option<EventId>,
182 pub(crate) event: Box<dyn Event<R> + Send>,
184}
185
186impl<R: BattleRules> Clone for EventWrapper<R> {
187 fn clone(&self) -> Self {
188 Self::new(self.id, self.origin, self.event.clone())
189 }
190}
191
192impl<R: BattleRules> EventWrapper<R> {
193 pub(crate) fn new(
195 id: EventId,
196 origin: Option<EventId>,
197 event: Box<dyn Event<R> + Send>,
198 ) -> Self {
199 Self { id, origin, event }
200 }
201
202 pub fn id(&self) -> EventId {
204 self.id
205 }
206
207 pub fn origin(&self) -> Option<EventId> {
209 self.origin
210 }
211
212 #[allow(clippy::borrowed_box)]
214 pub fn event(&self) -> &Box<dyn Event<R> + Send> {
215 &self.event
216 }
217
218 pub fn version(self, version: Version<R>) -> VersionedEventWrapper<R> {
220 VersionedEventWrapper::new(self, version)
221 }
222}
223
224impl<R: BattleRules> Deref for EventWrapper<R> {
225 type Target = Box<dyn Event<R> + Send>;
226
227 fn deref(&self) -> &Self::Target {
228 &self.event
229 }
230}
231
232pub struct VersionedEventWrapper<R: BattleRules> {
234 pub(crate) wrapper: EventWrapper<R>,
235 pub(crate) version: Version<R>,
236}
237
238impl<R: BattleRules> Clone for VersionedEventWrapper<R> {
239 fn clone(&self) -> Self {
240 Self::new(self.wrapper.clone(), self.version.clone())
241 }
242}
243
244impl<R: BattleRules> VersionedEventWrapper<R> {
245 pub(crate) fn new(wrapper: EventWrapper<R>, version: Version<R>) -> Self {
247 Self { wrapper, version }
248 }
249
250 pub fn wrapper(&self) -> &EventWrapper<R> {
252 &self.wrapper
253 }
254
255 pub fn version(&self) -> &Version<R> {
257 &self.version
258 }
259}
260
261impl<R: BattleRules> Deref for VersionedEventWrapper<R> {
262 type Target = EventWrapper<R>;
263
264 fn deref(&self) -> &Self::Target {
265 &self.wrapper
266 }
267}
268
269pub type Condition<R> = std::rc::Rc<dyn Fn(&BattleState<R>) -> bool>;
272
273pub struct EventPrototype<R: BattleRules> {
275 origin: Option<EventId>,
277 event: Box<dyn Event<R> + Send>,
279 condition: Option<Condition<R>>,
281}
282
283impl<R: BattleRules> EventPrototype<R> {
284 pub(crate) fn new(event: Box<dyn Event<R> + Send>) -> Self {
286 Self {
287 origin: None,
288 event,
289 condition: None,
290 }
291 }
292
293 pub(crate) fn promote(self, id: EventId) -> EventWrapper<R> {
294 EventWrapper::new(id, self.origin, self.event)
295 }
296
297 pub fn origin(&self) -> Option<EventId> {
299 self.origin
300 }
301
302 pub fn set_origin(&mut self, origin: Option<EventId>) {
304 self.origin = origin;
305 }
306
307 #[allow(clippy::borrowed_box)]
309 pub fn event(&self) -> &Box<dyn Event<R> + Send> {
310 &self.event
311 }
312
313 pub fn condition(&self) -> &Option<Condition<R>> {
315 &self.condition
316 }
317
318 pub fn set_condition(&mut self, condition: Option<Condition<R>>) {
320 self.condition = condition;
321 }
322
323 pub fn client_prototype(
325 self,
326 version: Version<R>,
327 player: Option<PlayerId>,
328 ) -> ClientEventPrototype<R> {
329 ClientEventPrototype::new(self.origin, self.event, version, player)
330 }
331}
332
333impl<R: BattleRules> Deref for EventPrototype<R> {
334 type Target = Box<dyn Event<R> + Send>;
335
336 fn deref(&self) -> &Self::Target {
337 &self.event
338 }
339}
340
341impl<R: BattleRules> Clone for EventPrototype<R> {
342 fn clone(&self) -> Self {
343 Self {
344 origin: self.origin,
345 event: self.event.clone(),
346 condition: self.condition.clone(),
347 }
348 }
349}
350
351pub struct ClientEventPrototype<R: BattleRules> {
354 origin: Option<EventId>,
356 pub(crate) event: Box<dyn Event<R> + Send>,
358 pub(crate) version: Version<R>,
360 player: Option<PlayerId>,
362}
363
364impl<R: BattleRules> ClientEventPrototype<R> {
365 pub(crate) fn new(
367 origin: Option<EventId>,
368 event: Box<dyn Event<R> + Send>,
369 version: Version<R>,
370 player: Option<PlayerId>,
371 ) -> Self {
372 Self {
373 origin,
374 event,
375 version,
376 player,
377 }
378 }
379
380 pub fn version(&self) -> &Version<R> {
382 &self.version
383 }
384
385 pub fn origin(&self) -> Option<EventId> {
387 self.origin
388 }
389
390 #[allow(clippy::borrowed_box)]
392 pub fn event(&self) -> &Box<dyn Event<R> + Send> {
393 &self.event
394 }
395
396 pub(crate) fn prototype(self) -> EventPrototype<R> {
398 EventPrototype {
399 origin: self.origin,
400 event: self.event,
401 condition: None,
402 }
403 }
404
405 pub fn authenticate(&mut self, player: PlayerId) {
410 self.player = Some(player);
411 }
412
413 pub fn player(&self) -> Option<PlayerId> {
415 self.player
416 }
417}
418
419impl<R: BattleRules> Deref for ClientEventPrototype<R> {
420 type Target = Box<dyn Event<R> + Send>;
421
422 fn deref(&self) -> &Self::Target {
423 &self.event
424 }
425}
426
427impl<R: BattleRules> Clone for ClientEventPrototype<R> {
428 fn clone(&self) -> Self {
429 Self {
430 origin: self.origin,
431 event: self.event.clone(),
432 version: self.version.clone(),
433 player: self.player,
434 }
435 }
436}
437
438pub trait DefaultOutput<R: BattleRules> {
441 type Error: Sized + PartialEq + Debug;
443 fn ok() -> Self;
445 fn err(self) -> Option<Self::Error>;
447 fn result(self) -> WeaselResult<(), R>;
449}
450
451pub trait EventProcessor<R: BattleRules> {
453 type ProcessOutput: DefaultOutput<R>;
455
456 fn process(&mut self, event: EventPrototype<R>) -> Self::ProcessOutput;
458}
459
460pub trait EventServer<R: BattleRules> {
462 fn process_client(&mut self, event: ClientEventPrototype<R>) -> WeaselResult<(), R>;
464}
465
466pub trait EventReceiver<R: BattleRules> {
468 fn receive(&mut self, event: VersionedEventWrapper<R>) -> WeaselResult<(), R>;
470}
471
472pub trait EventTrigger<'a, R: BattleRules, P: 'a + EventProcessor<R>> {
474 fn processor(&'a mut self) -> &'a mut P;
476
477 fn event(&self) -> Box<dyn Event<R> + Send>;
479
480 fn fire(&'a mut self) -> P::ProcessOutput {
482 let prototype = self.prototype();
483 self.processor().process(prototype)
484 }
485
486 fn prototype(&self) -> EventPrototype<R> {
488 EventPrototype::new(self.event())
489 }
490}
491
492pub type EventQueue<R> = Vec<EventPrototype<R>>;
494
495impl<R: BattleRules> EventProcessor<R> for EventQueue<R> {
498 type ProcessOutput = ();
499
500 fn process(&mut self, event: EventPrototype<R>) -> Self::ProcessOutput {
501 self.push(event);
502 }
503}
504
505#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
526pub struct DummyEvent<R> {
527 #[cfg_attr(feature = "serialization", serde(skip))]
528 _phantom: PhantomData<R>,
529}
530
531impl<R: BattleRules> DummyEvent<R> {
532 pub fn trigger<P: EventProcessor<R>>(processor: &mut P) -> DummyEventTrigger<R, P> {
534 DummyEventTrigger {
535 processor,
536 _phantom: PhantomData,
537 }
538 }
539}
540
541impl<R> Debug for DummyEvent<R> {
542 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
543 write!(f, "DummyEvent {{ }}")
544 }
545}
546
547impl<R> Clone for DummyEvent<R> {
548 fn clone(&self) -> Self {
549 Self {
550 _phantom: PhantomData,
551 }
552 }
553}
554
555impl<R: BattleRules + 'static> Event<R> for DummyEvent<R> {
556 fn verify(&self, _: &Battle<R>) -> WeaselResult<(), R> {
557 Ok(())
558 }
559
560 fn apply(&self, _: &mut Battle<R>, _: &mut Option<EventQueue<R>>) {}
561
562 fn kind(&self) -> EventKind {
563 EventKind::DummyEvent
564 }
565
566 fn box_clone(&self) -> Box<dyn Event<R> + Send> {
567 Box::new(self.clone())
568 }
569
570 fn as_any(&self) -> &dyn Any {
571 self
572 }
573
574 fn rights<'a>(&'a self, _battle: &'a Battle<R>) -> EventRights<'a, R> {
575 EventRights::None
576 }
577}
578
579pub struct DummyEventTrigger<'a, R, P>
581where
582 R: BattleRules,
583 P: EventProcessor<R>,
584{
585 processor: &'a mut P,
586 _phantom: PhantomData<R>,
587}
588
589impl<'a, R, P> EventTrigger<'a, R, P> for DummyEventTrigger<'a, R, P>
590where
591 R: BattleRules + 'static,
592 P: EventProcessor<R>,
593{
594 fn processor(&'a mut self) -> &'a mut P {
595 self.processor
596 }
597
598 fn event(&self) -> Box<dyn Event<R> + Send> {
600 Box::new(DummyEvent {
601 _phantom: PhantomData,
602 })
603 }
604}
605
606impl<R, T> EventProcessor<R> for &mut Option<T>
609where
610 R: BattleRules,
611 T: EventProcessor<R>,
612{
613 type ProcessOutput = T::ProcessOutput;
614
615 fn process(&mut self, event: EventPrototype<R>) -> Self::ProcessOutput {
616 if let Some(processor) = self {
617 processor.process(event)
618 } else {
619 Self::ProcessOutput::ok()
620 }
621 }
622}
623
624impl<R, T> EventProcessor<R> for Option<T>
625where
626 R: BattleRules,
627 T: EventProcessor<R>,
628{
629 type ProcessOutput = T::ProcessOutput;
630
631 fn process(&mut self, event: EventPrototype<R>) -> Self::ProcessOutput {
632 if let Some(processor) = self {
633 processor.process(event)
634 } else {
635 Self::ProcessOutput::ok()
636 }
637 }
638}
639
640impl<R> EventProcessor<R> for ()
642where
643 R: BattleRules,
644{
645 type ProcessOutput = WeaselResult<(), R>;
646
647 fn process(&mut self, _: EventPrototype<R>) -> Self::ProcessOutput {
648 Err(WeaselError::EmptyEventProcessor)
649 }
650}
651
652impl<R: BattleRules> DefaultOutput<R> for () {
653 type Error = ();
654
655 fn ok() -> Self {}
656
657 fn err(self) -> Option<Self::Error> {
658 None
659 }
660
661 fn result(self) -> WeaselResult<(), R> {
662 Ok(())
663 }
664}
665
666pub struct Prioritized<'a, R: BattleRules> {
685 event_queue: &'a mut EventQueue<R>,
686}
687
688impl<'a, R: BattleRules> Prioritized<'a, R> {
689 pub fn new(event_queue: &'a mut EventQueue<R>) -> Self {
691 Self { event_queue }
692 }
693}
694
695impl<R> EventProcessor<R> for Prioritized<'_, R>
696where
697 R: BattleRules,
698{
699 type ProcessOutput = ();
700
701 fn process(&mut self, event: EventPrototype<R>) -> Self::ProcessOutput {
702 self.event_queue.insert(0, event);
703 }
704}
705
706pub struct LinkedQueue<'a, R: BattleRules> {
724 event_queue: &'a mut EventQueue<R>,
725 origin: Option<EventId>,
726}
727
728impl<'a, R: BattleRules> LinkedQueue<'a, R> {
729 pub fn new(event_queue: &'a mut EventQueue<R>, origin: Option<EventId>) -> Self {
731 Self {
732 event_queue,
733 origin,
734 }
735 }
736}
737
738impl<R> EventProcessor<R> for LinkedQueue<'_, R>
739where
740 R: BattleRules,
741{
742 type ProcessOutput = ();
743
744 fn process(&mut self, mut event: EventPrototype<R>) -> Self::ProcessOutput {
745 if event.origin().is_none() {
746 event.set_origin(self.origin);
747 }
748 self.event_queue.push(event);
749 }
750}
751
752pub struct Conditional<'a, R, T, P>
782where
783 R: BattleRules,
784 T: EventTrigger<'a, R, P>,
785 P: 'a + EventProcessor<R>,
786{
787 trigger: T,
788 condition: Condition<R>,
789 _phantom: PhantomData<&'a P>,
790}
791
792impl<'a, R, T, P> Conditional<'a, R, T, P>
793where
794 R: BattleRules,
795 T: EventTrigger<'a, R, P>,
796 P: 'a + EventProcessor<R>,
797 Condition<R>: Clone,
798{
799 pub fn new(trigger: T, condition: Condition<R>) -> Self {
801 Self {
802 trigger,
803 condition,
804 _phantom: PhantomData,
805 }
806 }
807}
808
809impl<'a, R, T, P> EventTrigger<'a, R, P> for Conditional<'a, R, T, P>
810where
811 R: BattleRules,
812 T: EventTrigger<'a, R, P>,
813 P: 'a + EventProcessor<R>,
814 Condition<R>: Clone,
815{
816 fn processor(&'a mut self) -> &'a mut P {
817 self.trigger.processor()
818 }
819
820 fn event(&self) -> Box<dyn Event<R> + Send> {
821 self.trigger.event()
822 }
823
824 fn prototype(&self) -> EventPrototype<R> {
825 let mut prototype = self.trigger.prototype();
826 prototype.set_condition(Some(self.condition.clone()));
827 prototype
828 }
829}
830
831pub type EventSinkId = u16;
833
834pub trait EventSink {
836 fn id(&self) -> EventSinkId;
838
839 fn on_disconnect(&mut self) {}
843}
844
845pub trait ClientSink<R: BattleRules>: EventSink {
847 fn send(&mut self, event: &VersionedEventWrapper<R>) -> WeaselResult<(), R>;
849}
850
851pub trait ServerSink<R: BattleRules>: EventSink {
853 fn send(&mut self, event: &ClientEventPrototype<R>) -> WeaselResult<(), R>;
855}
856
857pub(crate) struct MultiClientSink<R: BattleRules> {
859 sinks: Vec<Box<dyn ClientSink<R> + Send>>,
860}
861
862impl<R: BattleRules> MultiClientSink<R> {
863 pub(crate) fn new() -> Self {
864 Self { sinks: Vec::new() }
865 }
866
867 fn add(&mut self, sink: Box<dyn ClientSink<R> + Send>) -> WeaselResult<(), R> {
870 if self.sinks.iter().any(|e| e.id() == sink.id()) {
871 Err(WeaselError::DuplicatedEventSink(sink.id()))
872 } else {
873 self.sinks.push(sink);
874 Ok(())
875 }
876 }
877
878 fn send<I>(&mut self, id: EventSinkId, events: I) -> WeaselResult<(), R>
881 where
882 I: Iterator<Item = VersionedEventWrapper<R>>,
883 {
884 let index = self.sinks.iter().position(|e| e.id() == id);
885 if let Some(index) = index {
886 for event in events {
888 let sink = &mut self.sinks[index];
889 let result = sink.send(&event);
890 if result.is_err() {
891 sink.on_disconnect();
892 self.sinks.remove(index);
893 }
894 result?;
895 }
896 Ok(())
897 } else {
898 Err(WeaselError::EventSinkNotFound(id))
899 }
900 }
901
902 fn remove(&mut self, id: EventSinkId) {
904 let index = self.sinks.iter().position(|e| e.id() == id);
905 if let Some(index) = index {
906 self.sinks.remove(index);
907 }
908 }
909
910 pub(crate) fn send_all(&mut self, event: &VersionedEventWrapper<R>) {
914 let mut failed_sinks_index = Vec::new();
915 for (i, sink) in self.sinks.iter_mut().enumerate() {
916 sink.send(event).unwrap_or_else(|err| {
917 error!("{:?}", err);
918 failed_sinks_index.push(i)
919 });
920 }
921 for i in failed_sinks_index {
922 self.sinks[i].on_disconnect();
923 self.sinks.remove(i);
924 }
925 }
926
927 fn sinks(&self) -> impl Iterator<Item = &Box<dyn ClientSink<R> + Send>> {
928 self.sinks.iter()
929 }
930}
931
932pub struct MultiClientSinkHandle<'a, R>
934where
935 R: BattleRules,
936{
937 sinks: &'a MultiClientSink<R>,
938}
939
940impl<'a, R> MultiClientSinkHandle<'a, R>
941where
942 R: BattleRules + 'static,
943{
944 pub(crate) fn new(sinks: &'a MultiClientSink<R>) -> Self {
945 Self { sinks }
946 }
947
948 pub fn sinks(&self) -> impl Iterator<Item = &Box<dyn ClientSink<R> + Send>> {
950 self.sinks.sinks()
951 }
952}
953
954pub struct MultiClientSinkHandleMut<'a, R>
956where
957 R: BattleRules + 'static,
958{
959 sinks: &'a mut MultiClientSink<R>,
960 battle: &'a Battle<R>,
961}
962
963impl<'a, R> MultiClientSinkHandleMut<'a, R>
964where
965 R: BattleRules + 'static,
966{
967 pub(crate) fn new(sinks: &'a mut MultiClientSink<R>, battle: &'a Battle<R>) -> Self {
968 Self { sinks, battle }
969 }
970
971 pub fn add_sink(&mut self, sink: Box<dyn ClientSink<R> + Send>) -> WeaselResult<(), R> {
975 self.sinks.add(sink)
976 }
977
978 pub fn add_sink_from(
983 &mut self,
984 sink: Box<dyn ClientSink<R> + Send>,
985 event_id: EventId,
986 ) -> WeaselResult<(), R> {
987 self.add_sink_range(
988 sink,
989 Range {
990 start: event_id,
991 end: self.battle.history().len(),
992 },
993 )
994 }
995
996 pub fn add_sink_range(
1001 &mut self,
1002 sink: Box<dyn ClientSink<R> + Send>,
1003 range: Range<EventId>,
1004 ) -> WeaselResult<(), R> {
1005 let range = normalize_range(range, self.battle.history().len())?;
1006 let sink_id = sink.id();
1008 self.sinks.add(sink)?;
1009 self.sinks
1011 .send(sink_id, self.battle.versioned_events(range))
1012 }
1013
1014 pub fn send_range(&mut self, id: EventSinkId, range: Range<EventId>) -> WeaselResult<(), R> {
1016 let range = normalize_range(range, self.battle.history().len())?;
1017 self.sinks.send(id, self.battle.versioned_events(range))
1019 }
1020
1021 pub fn remove_sink(&mut self, id: EventSinkId) {
1023 self.sinks.remove(id);
1024 }
1025
1026 pub fn sinks(&self) -> impl Iterator<Item = &Box<dyn ClientSink<R> + Send>> {
1028 self.sinks.sinks()
1029 }
1030}
1031
1032fn normalize_range<R: BattleRules>(
1034 range: Range<EventId>,
1035 history_len: EventId,
1036) -> WeaselResult<Range<usize>, R> {
1037 if range.start > range.end || range.end > history_len {
1038 return Err(WeaselError::InvalidEventRange(range, history_len));
1039 }
1040 let range: Range<usize> = Range {
1041 start: range.start as usize,
1042 end: range.end as usize,
1043 };
1044 Ok(range)
1045}
1046
1047pub struct Originated<'a, R, T, P>
1067where
1068 R: BattleRules,
1069 T: EventTrigger<'a, R, P>,
1070 P: 'a + EventProcessor<R>,
1071{
1072 trigger: T,
1073 origin: EventId,
1074 _phantom: PhantomData<&'a P>,
1075 _phantom_: PhantomData<R>,
1076}
1077
1078impl<'a, R, T, P> Originated<'a, R, T, P>
1079where
1080 R: BattleRules,
1081 T: EventTrigger<'a, R, P>,
1082 P: 'a + EventProcessor<R>,
1083{
1084 pub fn new(trigger: T, origin: EventId) -> Self {
1086 Self {
1087 trigger,
1088 origin,
1089 _phantom: PhantomData,
1090 _phantom_: PhantomData,
1091 }
1092 }
1093}
1094
1095impl<'a, R, T, P> EventTrigger<'a, R, P> for Originated<'a, R, T, P>
1096where
1097 R: BattleRules,
1098 T: EventTrigger<'a, R, P>,
1099 P: 'a + EventProcessor<R>,
1100{
1101 fn processor(&'a mut self) -> &'a mut P {
1102 self.trigger.processor()
1103 }
1104
1105 fn event(&self) -> Box<dyn Event<R> + Send> {
1106 self.trigger.event()
1107 }
1108
1109 fn prototype(&self) -> EventPrototype<R> {
1110 let mut prototype = self.trigger.prototype();
1111 prototype.set_origin(Some(self.origin));
1112 prototype
1113 }
1114}
1115
1116#[cfg(test)]
1117mod tests {
1118 use super::*;
1119 use crate::entropy::ResetEntropy;
1120 use crate::{battle_rules, rules::empty::*};
1121 use std::iter::once;
1122
1123 battle_rules! {}
1124
1125 #[test]
1126 fn event_equality() {
1127 let dummy = DummyEvent::<CustomRules>::trigger(&mut ()).event();
1128 let dummy_copy = dummy.clone();
1129 let reset_entropy = ResetEntropy::<CustomRules>::trigger(&mut ()).event();
1130 assert_eq!(&dummy, &dummy_copy);
1131 assert_ne!(&dummy, &reset_entropy);
1132 }
1133
1134 #[test]
1135 fn multi_client_sink() {
1136 struct Sink {
1137 id: EventSinkId,
1138 ok: bool,
1139 }
1140
1141 impl EventSink for Sink {
1142 fn id(&self) -> EventSinkId {
1143 self.id
1144 }
1145 }
1146
1147 impl ClientSink<CustomRules> for Sink {
1148 fn send(
1149 &mut self,
1150 _: &VersionedEventWrapper<CustomRules>,
1151 ) -> WeaselResult<(), CustomRules> {
1152 if self.ok {
1153 Ok(())
1154 } else {
1155 Err(WeaselError::EventSinkError("broken".to_string()))
1156 }
1157 }
1158 }
1159
1160 let mut multi = MultiClientSink::new();
1162 assert_eq!(multi.add(Box::new(Sink { id: 0, ok: true })).err(), None);
1163 assert_eq!(multi.sinks.len(), 1);
1164 assert_eq!(
1165 multi.add(Box::new(Sink { id: 0, ok: true })).err(),
1166 Some(WeaselError::DuplicatedEventSink(0))
1167 );
1168 assert_eq!(multi.sinks.len(), 1);
1169 multi.remove(2);
1171 assert_eq!(multi.sinks.len(), 1);
1172 multi.remove(0);
1173 assert_eq!(multi.sinks.len(), 0);
1174 assert_eq!(multi.add(Box::new(Sink { id: 0, ok: true })).err(), None);
1176 assert_eq!(multi.add(Box::new(Sink { id: 1, ok: false })).err(), None);
1177 assert_eq!(multi.sinks.len(), 2);
1178 let event = DummyEvent::<CustomRules>::trigger(&mut ())
1179 .prototype()
1180 .promote(0)
1181 .version(0);
1182 multi.send_all(&event);
1183 assert_eq!(multi.sinks.len(), 1);
1184 assert_eq!(multi.send(0, once(event.clone())).err(), None);
1186 assert_eq!(
1187 multi.send(2, once(event.clone())).err(),
1188 Some(WeaselError::EventSinkNotFound(2))
1189 );
1190 assert_eq!(multi.add(Box::new(Sink { id: 1, ok: false })).err(), None);
1191 assert_eq!(multi.sinks.len(), 2);
1192 assert_eq!(
1193 multi.send(1, once(event)).err(),
1194 Some(WeaselError::EventSinkError("broken".to_string()))
1195 );
1196 assert_eq!(multi.sinks.len(), 1);
1197 }
1198
1199 #[test]
1200 #[allow(clippy::let_unit_value)]
1201 fn decorators_stack() {
1202 let mut processor = ();
1203 let event = Conditional::new(
1204 DummyEvent::trigger(&mut processor),
1205 std::rc::Rc::new(|_: &BattleState<CustomRules>| true),
1206 );
1207 let event = Originated::new(event, 0);
1208 let prototype = event.prototype();
1209 assert!(prototype.condition.is_some());
1210 assert!(prototype.origin.is_some());
1211 }
1212
1213 #[test]
1214 fn linked_queue_respects_origin() {
1215 let mut queue = EventQueue::<CustomRules>::new();
1216 let origin = 42;
1217 let mut linked_queue = LinkedQueue::new(&mut queue, Some(origin + 1));
1218 Originated::new(DummyEvent::trigger(&mut linked_queue), origin).fire();
1219 assert_eq!(queue[0].origin(), Some(origin));
1220 }
1221
1222 #[test]
1223 fn basic_event_rights_equality() {
1224 type R = CustomRules;
1225 use EventRights::*;
1226 assert_eq!(EventRights::<R>::None, None);
1227 assert_ne!(EventRights::<R>::None, Team(&1));
1228 assert_ne!(EventRights::<R>::None, Teams(vec![&1]));
1229 assert_eq!(EventRights::<R>::Server, Server);
1230 assert_ne!(EventRights::<R>::Server, Team(&1));
1231 assert_ne!(EventRights::<R>::Server, Teams(vec![&1]));
1232 assert_eq!(EventRights::<R>::Team(&1), Team(&1));
1233 assert_ne!(EventRights::<R>::Team(&1), Team(&2));
1234 assert_eq!(EventRights::<R>::Teams(vec![&1, &2]), Teams(vec![&1, &2]));
1235 assert_ne!(EventRights::<R>::Teams(vec![&1, &2]), Teams(vec![&1, &3]));
1236 assert_ne!(EventRights::<R>::Team(&1), Teams(vec![&1]));
1237 }
1238}