Skip to main content

weasel/
event.rs

1//! Event module.
2
3use 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
16/// Type for the id of events.
17pub type EventId = u32;
18
19/// Enum to represent all different kinds of events.
20// Internal note: remember to update the event debug and serialization tests in tests/event.rs
21// each time a new event is added to weasel.
22#[derive(Copy, Clone, PartialEq, Debug)]
23pub enum EventKind {
24    /// Dummy event doing nothing.
25    DummyEvent,
26    /// Create a new team.
27    CreateTeam,
28    /// Create a new creature.
29    CreateCreature,
30    /// Create a new object.
31    CreateObject,
32    /// Move an entity from one position to another.
33    MoveEntity,
34    /// Start a new turn.
35    StartTurn,
36    /// End the current turn.
37    EndTurn,
38    /// End the current round.
39    EndRound,
40    /// Perform a turn for the environment.
41    EnvironmentTurn,
42    /// Activate an actor's ability.
43    ActivateAbility,
44    /// Invoke a team's power.
45    InvokePower,
46    /// Apply the consequences of an impact on the world.
47    ApplyImpact,
48    /// Modify the statistics of a character.
49    AlterStatistics,
50    /// Modify the statuses of a character.
51    AlterStatuses,
52    /// Modify the abilities of an actor.
53    AlterAbilities,
54    /// Modify the powers of a team.
55    AlterPowers,
56    /// Regenerate the statistics of a character.
57    RegenerateStatistics,
58    /// Regenerate the abilities of an actor.
59    RegenerateAbilities,
60    /// Regenerate the powers of a team.
61    RegeneratePowers,
62    /// Inflict a status effect on a character.
63    InflictStatus,
64    /// Frees a character from a status effect.
65    ClearStatus,
66    /// Convert a creature from one team to another.
67    ConvertCreature,
68    /// Set new relations between teams.
69    SetRelations,
70    /// An event to set a team's objectives outcome.
71    ConcludeObjectives,
72    /// Remove a creature from the battle.
73    RemoveCreature,
74    /// Remove an object from the battle.
75    RemoveObject,
76    /// Remove a team from the battle.
77    RemoveTeam,
78    /// Modify the spatial model.
79    AlterSpace,
80    /// Reset the entropy model.
81    ResetEntropy,
82    /// Reset the objectives of a team.
83    ResetObjectives,
84    /// Reset the rounds model.
85    ResetRounds,
86    /// Reset the space model.
87    ResetSpace,
88    /// End the battle.
89    EndBattle,
90    /// A user defined event with an unique id.
91    UserEvent(UserEventId),
92}
93
94/// Types of access rights that might be required in order to fire an event.
95pub enum EventRights<'a, R: BattleRules> {
96    /// Everyone can fire the event.
97    None,
98    /// Only the server can fire the event.
99    Server,
100    /// Only the server or a player with rights to this team can fire the event.
101    Team(&'a TeamId<R>),
102    /// Only the server or a player with rights to all of these teams can fire the event.
103    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
133/// An event is the only mean to apply a change to the world.
134pub trait Event<R: BattleRules>: Debug {
135    /// Verifies if this event can be applied to the world.
136    fn verify(&self, battle: &Battle<R>) -> WeaselResult<(), R>;
137
138    /// Applies this event to the world. This method is called only if `verify` succeeded.
139    ///
140    /// If there's a failure inside this method, it immediately panic because we can't guarantee
141    /// any consistency in the state of the world.
142    ///
143    /// Events generated by this event are stored into `queue`, if there's one.
144    /// Noe that they will keep a link with the original event.
145    fn apply(&self, battle: &mut Battle<R>, queue: &mut Option<EventQueue<R>>);
146
147    /// Returns the kind of this event.
148    fn kind(&self) -> EventKind;
149
150    /// Clones this event as a trait object.
151    fn box_clone(&self) -> Box<dyn Event<R> + Send>;
152
153    /// Returns an `Any` reference this event.
154    fn as_any(&self) -> &dyn Any;
155
156    /// Returns the access rights required by this event.
157    ///
158    /// The provided implementation returns `EventRights::Server`.
159    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
176/// A wrapper to decorate verified events with additional data.
177pub struct EventWrapper<R: BattleRules> {
178    /// Event Id is assigned only after events has been verified for consistency.
179    id: EventId,
180    /// Id of the event that generated this one.
181    origin: Option<EventId>,
182    /// The actual event wrapped inside this struct.
183    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    /// Creates a new EventWrapper.
194    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    /// Returns this event's id.
203    pub fn id(&self) -> EventId {
204        self.id
205    }
206
207    /// Returns the id of the event that caused this one.
208    pub fn origin(&self) -> Option<EventId> {
209        self.origin
210    }
211
212    /// Returns the event.
213    #[allow(clippy::borrowed_box)]
214    pub fn event(&self) -> &Box<dyn Event<R> + Send> {
215        &self.event
216    }
217
218    /// Consume this event wrapper and returns a versioned instance of it.
219    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
232/// Decorates an `EventWrapper` with the battle rules version.
233pub 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    /// Creates a new VersionedEventWrapper.
246    pub(crate) fn new(wrapper: EventWrapper<R>, version: Version<R>) -> Self {
247        Self { wrapper, version }
248    }
249
250    /// Returns the `EventWrapper` contained in this object.
251    pub fn wrapper(&self) -> &EventWrapper<R> {
252        &self.wrapper
253    }
254
255    /// Returns the `BattleRules`' version of the event.
256    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
269/// Function that tells if an event prototype met its additional conditions
270/// in order to be applied.
271pub type Condition<R> = std::rc::Rc<dyn Fn(&BattleState<R>) -> bool>;
272
273/// A prototype for tentative events that are not yet verified.
274pub struct EventPrototype<R: BattleRules> {
275    /// Id of the event that generated this one.
276    origin: Option<EventId>,
277    /// The actual event wrapped inside this struct.
278    event: Box<dyn Event<R> + Send>,
279    /// Condition that must be satisfied for this prototype to be valid.
280    condition: Option<Condition<R>>,
281}
282
283impl<R: BattleRules> EventPrototype<R> {
284    /// Creates a new EventPrototype.
285    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    /// Returns the id of the event that caused this one.
298    pub fn origin(&self) -> Option<EventId> {
299        self.origin
300    }
301
302    /// Sets the origin of this prototype.
303    pub fn set_origin(&mut self, origin: Option<EventId>) {
304        self.origin = origin;
305    }
306
307    /// Returns the event.
308    #[allow(clippy::borrowed_box)]
309    pub fn event(&self) -> &Box<dyn Event<R> + Send> {
310        &self.event
311    }
312
313    /// Returns the prototype's acceptance condition.
314    pub fn condition(&self) -> &Option<Condition<R>> {
315        &self.condition
316    }
317
318    /// Sets the acceptance condition of this prototype.
319    pub fn set_condition(&mut self, condition: Option<Condition<R>>) {
320        self.condition = condition;
321    }
322
323    /// Consume this event prototype and returns a `ClientEventPrototype` instance of it.
324    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
351/// An event prototype sent by a client to a server that must be first verified
352/// before being processed.
353pub struct ClientEventPrototype<R: BattleRules> {
354    /// Id of the event that generated this one.
355    origin: Option<EventId>,
356    /// The actual event wrapped inside this struct.
357    pub(crate) event: Box<dyn Event<R> + Send>,
358    /// Version of `BattleRules` that generated this event.
359    pub(crate) version: Version<R>,
360    /// Id of the player who fired this event.
361    player: Option<PlayerId>,
362}
363
364impl<R: BattleRules> ClientEventPrototype<R> {
365    /// Creates a new ClientEventPrototype.
366    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    /// Returns the `BattleRules`'s version of the event.
381    pub fn version(&self) -> &Version<R> {
382        &self.version
383    }
384
385    /// Returns the id of the event that caused this one.
386    pub fn origin(&self) -> Option<EventId> {
387        self.origin
388    }
389
390    /// Returns the event.
391    #[allow(clippy::borrowed_box)]
392    pub fn event(&self) -> &Box<dyn Event<R> + Send> {
393        &self.event
394    }
395
396    /// Transforms this client event into an event prototype.
397    pub(crate) fn prototype(self) -> EventPrototype<R> {
398        EventPrototype {
399            origin: self.origin,
400            event: self.event,
401            condition: None,
402        }
403    }
404
405    /// Authenticate this event with the identity of `player`.
406    ///
407    /// **Note:** you can use this method to perform server-side authentication of events coming
408    /// from a remote client.
409    pub fn authenticate(&mut self, player: PlayerId) {
410        self.player = Some(player);
411    }
412
413    /// Returns the player who fired this prototype.
414    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
438/// A trait to describe an output type from an event processor.
439/// The requirement of this type is to be able to return an object for an ok state.
440pub trait DefaultOutput<R: BattleRules> {
441    /// Error type for this `DefaultOutput`.
442    type Error: Sized + PartialEq + Debug;
443    /// Returns the `ok` result for this type.
444    fn ok() -> Self;
445    /// Convert this output into an `Option`.
446    fn err(self) -> Option<Self::Error>;
447    /// Convert this output into a `WeaselResult`.
448    fn result(self) -> WeaselResult<(), R>;
449}
450
451/// A trait for objects that can process new local events.
452pub trait EventProcessor<R: BattleRules> {
453    /// Return type for this processor's `process()`.
454    type ProcessOutput: DefaultOutput<R>;
455
456    /// Processes a local event prototype.
457    fn process(&mut self, event: EventPrototype<R>) -> Self::ProcessOutput;
458}
459
460/// A trait for objects that can verify and process new client events.
461pub trait EventServer<R: BattleRules> {
462    /// Processes a client event prototype.
463    fn process_client(&mut self, event: ClientEventPrototype<R>) -> WeaselResult<(), R>;
464}
465
466/// A trait for objects that can receive verified events.
467pub trait EventReceiver<R: BattleRules> {
468    /// Processes a verified event.
469    fn receive(&mut self, event: VersionedEventWrapper<R>) -> WeaselResult<(), R>;
470}
471
472/// Trait to unify the interface of all event builders.
473pub trait EventTrigger<'a, R: BattleRules, P: 'a + EventProcessor<R>> {
474    /// Returns the processor bound to this trigger.
475    fn processor(&'a mut self) -> &'a mut P;
476
477    /// Returns the event constructed by this builder.
478    fn event(&self) -> Box<dyn Event<R> + Send>;
479
480    /// Fires the event constructed by this builder.
481    fn fire(&'a mut self) -> P::ProcessOutput {
482        let prototype = self.prototype();
483        self.processor().process(prototype)
484    }
485
486    /// Returns the event constructed by this builder, wrapped in a prototype.
487    fn prototype(&self) -> EventPrototype<R> {
488        EventPrototype::new(self.event())
489    }
490}
491
492/// Collection to queue events prototypes, in order of insertion.
493pub type EventQueue<R> = Vec<EventPrototype<R>>;
494
495// Implement `EventProcessor` for event queues, so that it can be possible to
496// use the latter with event triggers.
497impl<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/// An event that does nothing.
506///
507/// # Examples
508/// ```
509/// use weasel::{
510///     battle_rules, event::DummyEvent, rules::empty::*, Battle, BattleController, BattleRules,
511///     EventKind, EventTrigger, Server,
512/// };
513///
514/// battle_rules! {}
515///
516/// let battle = Battle::builder(CustomRules::new()).build();
517/// let mut server = Server::builder(battle).build();
518///
519/// DummyEvent::trigger(&mut server).fire().unwrap();
520/// assert_eq!(
521///     server.battle().history().events()[0].kind(),
522///     EventKind::DummyEvent
523/// );
524/// ```
525#[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    /// Returns a trigger for this event.
533    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
579/// Trigger to build and fire a `DummyEvent` event.
580pub 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    /// Returns a `DummyEvent` event.
599    fn event(&self) -> Box<dyn Event<R> + Send> {
600        Box::new(DummyEvent {
601            _phantom: PhantomData,
602        })
603    }
604}
605
606// Implement `EventProcessor` for option, so that it would be possible to pass
607// None or a real processor to event triggers.
608impl<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
640// Implement `EventProcessor` for (), doing nothing.
641impl<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
666/// Decorator for `EventQueue` processor. It appends new events at the front of the queue, instead
667/// of pushing them at the back.
668///
669/// # Examples
670/// ```
671/// use weasel::{
672///     battle_rules, event::DummyEvent, event::Prioritized, rules::empty::*, BattleRules,
673///     EndBattle, EventKind, EventQueue, EventTrigger,
674/// };
675///
676/// battle_rules! {}
677///
678/// let mut queue = EventQueue::<CustomRules>::new();
679/// EndBattle::trigger(&mut queue).fire();
680/// DummyEvent::trigger(&mut Prioritized::new(&mut queue)).fire();
681/// assert_eq!(queue[0].kind(), EventKind::DummyEvent);
682/// assert_eq!(queue[1].kind(), EventKind::EndBattle);
683/// ```
684pub struct Prioritized<'a, R: BattleRules> {
685    event_queue: &'a mut EventQueue<R>,
686}
687
688impl<'a, R: BattleRules> Prioritized<'a, R> {
689    /// Creates a new Prioritized decorator for the given `event_queue`.
690    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
706/// Decorator for `EventQueue` processor. It sets the origin of all events inserted into the queue
707/// to the `EventId` specified during instantiation, unless origin has been manually specified.
708///
709/// # Examples
710/// ```
711/// use weasel::{
712///     battle_rules, event::DummyEvent, rules::empty::*, BattleRules, EndBattle, EventKind,
713///     EventQueue, EventTrigger, LinkedQueue,
714/// };
715///
716/// battle_rules! {}
717///
718/// let mut queue = EventQueue::<CustomRules>::new();
719/// let origin = 42;
720/// DummyEvent::trigger(&mut LinkedQueue::new(&mut queue, Some(origin))).fire();
721/// assert_eq!(queue[0].origin(), Some(origin));
722/// ```
723pub 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    /// Creates a new LinkedQueue decorator for the given `event_queue`.
730    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
752/// Decorator for event triggers to add a condition on the generated event prototype.
753///
754/// # Examples
755/// ```
756/// use weasel::{
757///     battle_rules, event::Conditional, event::DummyEvent, rules::empty::*, Battle, BattleRules,
758///     BattleState, EventTrigger, Server, WeaselError,
759/// };
760///
761/// battle_rules! {}
762///
763/// let battle = Battle::builder(CustomRules::new()).build();
764/// let mut server = Server::builder(battle).build();
765///
766/// let result = Conditional::new(
767///     DummyEvent::trigger(&mut server),
768///     std::rc::Rc::new(|state: &BattleState<CustomRules>| {
769///         state
770///             .entities()
771///             .teams()
772///             .count() == 42
773///     }),
774/// )
775/// .fire();
776/// assert_eq!(
777///     result.err().map(|e| e.unfold()),
778///     Some(WeaselError::ConditionUnsatisfied)
779/// );
780/// ```
781pub 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    /// Creates a new `Conditional` decorator for an `EventTrigger`.
800    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
831/// Id of an event sink.
832pub type EventSinkId = u16;
833
834/// Basic trait for event sinks.
835pub trait EventSink {
836    /// Returns the Id associated to this sink.
837    fn id(&self) -> EventSinkId;
838
839    /// Invoked when this sink is forcedly disconnected.
840    ///
841    /// The provided implementation does nothing.
842    fn on_disconnect(&mut self) {}
843}
844
845/// An output sink to dump versioned and verified events to a client.
846pub trait ClientSink<R: BattleRules>: EventSink {
847    /// Sends an already accepted event to a remote or local client.
848    fn send(&mut self, event: &VersionedEventWrapper<R>) -> WeaselResult<(), R>;
849}
850
851/// An output sink to dump tentative events to a server.
852pub trait ServerSink<R: BattleRules>: EventSink {
853    /// Sends a client event prototype to a remote or local server.
854    fn send(&mut self, event: &ClientEventPrototype<R>) -> WeaselResult<(), R>;
855}
856
857/// A data structure to contain multiple client sinks.
858pub(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    /// Adds a new sink.
868    /// Returns an error if another sink with the same id already exists.
869    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    /// Sends all `events` to an existing sink.
879    /// Returns an error if sending the events failed or the sink doesn't exist.
880    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            // Send events.
887            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    /// Removes the sink with the given `id`, if it exists.
903    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    /// Sends an event to all sinks.
911    /// If a sink returns an error, its on_disconnect() fn will be invoked
912    /// and the sink is disconnected from the server.
913    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
932/// A structure to access client sinks.
933pub 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    /// Returns an iterator over all sinks.
949    pub fn sinks(&self) -> impl Iterator<Item = &Box<dyn ClientSink<R> + Send>> {
950        self.sinks.sinks()
951    }
952}
953
954/// A structure to access and manipulate client sinks.
955pub 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    /// Adds a new sink.
972    ///
973    /// Sinks must have unique ids.
974    pub fn add_sink(&mut self, sink: Box<dyn ClientSink<R> + Send>) -> WeaselResult<(), R> {
975        self.sinks.add(sink)
976    }
977
978    /// Adds a new sink and shares the battle history with it,
979    /// starting from the event having `event_id` up to the most recent event.
980    ///
981    /// Sinks must have unique ids.
982    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    /// Adds a new sink and shares a portion of the battle history with it.
997    /// More precisely, only the events inside `range` will be sent to the sink.
998    ///
999    /// Sinks must have unique ids.
1000    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        // Add the new sink.
1007        let sink_id = sink.id();
1008        self.sinks.add(sink)?;
1009        // Get all versioned events from history and send them.
1010        self.sinks
1011            .send(sink_id, self.battle.versioned_events(range))
1012    }
1013
1014    /// Sends a range of events from the battle history to the sink with the given id.
1015    pub fn send_range(&mut self, id: EventSinkId, range: Range<EventId>) -> WeaselResult<(), R> {
1016        let range = normalize_range(range, self.battle.history().len())?;
1017        // Get all versioned events from history and send them.
1018        self.sinks.send(id, self.battle.versioned_events(range))
1019    }
1020
1021    /// Removes the sink with the given id.
1022    pub fn remove_sink(&mut self, id: EventSinkId) {
1023        self.sinks.remove(id);
1024    }
1025
1026    /// Returns an iterator over all sinks.
1027    pub fn sinks(&self) -> impl Iterator<Item = &Box<dyn ClientSink<R> + Send>> {
1028        self.sinks.sinks()
1029    }
1030}
1031
1032/// Converts a range of `EventId` into a range of `usize`.
1033fn 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
1047/// Decorator for event triggers to manually set the origin of an event.
1048///
1049/// # Examples
1050/// ```
1051/// use weasel::{
1052///     battle_rules, event::DummyEvent, event::Originated, rules::empty::*, Battle,
1053///     BattleController, BattleRules, EventTrigger, Server,
1054/// };
1055///
1056/// battle_rules! {}
1057///
1058/// let battle = Battle::builder(CustomRules::new()).build();
1059/// let mut server = Server::builder(battle).build();
1060///
1061/// Originated::new(DummyEvent::trigger(&mut server), 42)
1062///     .fire()
1063///     .unwrap();
1064/// assert_eq!(server.battle().history().events()[0].origin(), Some(42));
1065/// ```
1066pub 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    /// Creates a new decorator to change an event's origin.
1085    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        // Check add.
1161        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        // Check remove.
1170        multi.remove(2);
1171        assert_eq!(multi.sinks.len(), 1);
1172        multi.remove(0);
1173        assert_eq!(multi.sinks.len(), 0);
1174        // Check send_all.
1175        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        // Check send.
1185        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}