Skip to main content

naia_client/
tick_events.rs

1use std::vec::IntoIter;
2
3use naia_shared::Tick;
4
5/// Collects client and server tick events emitted during a single frame for typed iteration.
6pub struct TickEvents {
7    client_ticks: Vec<Tick>,
8    server_ticks: Vec<Tick>,
9    empty: bool,
10}
11
12impl Default for TickEvents {
13    fn default() -> Self {
14        Self::new()
15    }
16}
17
18impl TickEvents {
19    pub(crate) fn new() -> Self {
20        Self {
21            client_ticks: Vec::new(),
22            server_ticks: Vec::new(),
23            empty: true,
24        }
25    }
26
27    /// Returns `true` if no tick events have been queued this frame.
28    pub fn is_empty(&self) -> bool {
29        self.empty
30    }
31
32    /// Drains and returns an iterator over tick events of type `V`.
33    pub fn read<V: TickEvent>(&mut self) -> V::Iter {
34        V::iter(self)
35    }
36
37    /// Returns `true` if at least one tick event of type `V` is queued.
38    pub fn has<V: TickEvent>(&self) -> bool {
39        V::has(self)
40    }
41
42    pub(crate) fn push_client_tick(&mut self, tick: Tick) {
43        self.client_ticks.push(tick);
44        self.empty = false;
45    }
46
47    pub(crate) fn push_server_tick(&mut self, tick: Tick) {
48        self.server_ticks.push(tick);
49        self.empty = false;
50    }
51
52    pub(crate) fn clear(&mut self) {
53        self.client_ticks.clear();
54        self.server_ticks.clear();
55        self.empty = true;
56    }
57}
58
59/// Type-indexed tick event; implemented by [`ClientTickEvent`] and [`ServerTickEvent`].
60pub trait TickEvent {
61    /// Iterator type returned from [`TickEvents::read`].
62    type Iter;
63
64    /// Drains tick events of this variant out of `events` and returns an iterator over them.
65    fn iter(events: &mut TickEvents) -> Self::Iter;
66
67    /// Returns `true` if `events` contains at least one event of this variant.
68    fn has(events: &TickEvents) -> bool;
69}
70
71/// Fired each client-side simulation tick; iterate via `tick_events.read::<ClientTickEvent>()`.
72pub struct ClientTickEvent;
73impl TickEvent for ClientTickEvent {
74    type Iter = IntoIter<Tick>;
75
76    fn iter(events: &mut TickEvents) -> Self::Iter {
77        let list = std::mem::take(&mut events.client_ticks);
78        IntoIterator::into_iter(list)
79    }
80
81    fn has(events: &TickEvents) -> bool {
82        !events.client_ticks.is_empty()
83    }
84}
85
86/// Fired each time the server's authoritative tick advances; iterate via `tick_events.read::<ServerTickEvent>()`.
87pub struct ServerTickEvent;
88impl TickEvent for ServerTickEvent {
89    type Iter = IntoIter<Tick>;
90
91    fn iter(events: &mut TickEvents) -> Self::Iter {
92        let list = std::mem::take(&mut events.server_ticks);
93        IntoIterator::into_iter(list)
94    }
95
96    fn has(events: &TickEvents) -> bool {
97        !events.server_ticks.is_empty()
98    }
99}