Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/message/message_cursor.rs
6849 views
1
use crate::message::{
2
Message, MessageIterator, MessageIteratorWithId, MessageMutIterator, MessageMutIteratorWithId,
3
Messages,
4
};
5
#[cfg(feature = "multi_threaded")]
6
use crate::message::{MessageMutParIter, MessageParIter};
7
use core::marker::PhantomData;
8
9
/// Stores the state for a [`MessageReader`] or [`MessageMutator`].
10
///
11
/// Access to the [`Messages<E>`] resource is required to read any incoming messages.
12
///
13
/// In almost all cases, you should just use a [`MessageReader`] or [`MessageMutator`],
14
/// which will automatically manage the state for you.
15
///
16
/// However, this type can be useful if you need to manually track messages,
17
/// such as when you're attempting to send and receive messages of the same type in the same system.
18
///
19
/// # Example
20
///
21
/// ```
22
/// use bevy_ecs::prelude::*;
23
/// use bevy_ecs::message::{Message, MessageCursor};
24
///
25
/// #[derive(Message, Clone, Debug)]
26
/// struct MyMessage;
27
///
28
/// /// A system that both sends and receives messages using a [`Local`] [`MessageCursor`].
29
/// fn send_and_receive_messages(
30
/// // The `Local` `SystemParam` stores state inside the system itself, rather than in the world.
31
/// // `MessageCursor<T>` is the internal state of `MessageMutator<T>`, which tracks which messages have been seen.
32
/// mut local_message_reader: Local<MessageCursor<MyMessage>>,
33
/// // We can access the `Messages` resource mutably, allowing us to both read and write its contents.
34
/// mut messages: ResMut<Messages<MyMessage>>,
35
/// ) {
36
/// // We must collect the messages to resend, because we can't mutate messages while we're iterating over the messages.
37
/// let mut messages_to_resend = Vec::new();
38
///
39
/// for message in local_message_reader.read(&mut messages) {
40
/// messages_to_resend.push(message.clone());
41
/// }
42
///
43
/// for message in messages_to_resend {
44
/// messages.write(MyMessage);
45
/// }
46
/// }
47
///
48
/// # bevy_ecs::system::assert_is_system(send_and_receive_messages);
49
/// ```
50
///
51
/// [`MessageReader`]: super::MessageReader
52
/// [`MessageMutator`]: super::MessageMutator
53
#[derive(Debug)]
54
pub struct MessageCursor<E: Message> {
55
pub(super) last_message_count: usize,
56
pub(super) _marker: PhantomData<E>,
57
}
58
59
impl<E: Message> Default for MessageCursor<E> {
60
fn default() -> Self {
61
MessageCursor {
62
last_message_count: 0,
63
_marker: Default::default(),
64
}
65
}
66
}
67
68
impl<E: Message> Clone for MessageCursor<E> {
69
fn clone(&self) -> Self {
70
MessageCursor {
71
last_message_count: self.last_message_count,
72
_marker: PhantomData,
73
}
74
}
75
}
76
77
impl<E: Message> MessageCursor<E> {
78
/// See [`MessageReader::read`](super::MessageReader::read)
79
pub fn read<'a>(&'a mut self, messages: &'a Messages<E>) -> MessageIterator<'a, E> {
80
self.read_with_id(messages).without_id()
81
}
82
83
/// See [`MessageMutator::read`](super::MessageMutator::read)
84
pub fn read_mut<'a>(&'a mut self, messages: &'a mut Messages<E>) -> MessageMutIterator<'a, E> {
85
self.read_mut_with_id(messages).without_id()
86
}
87
88
/// See [`MessageReader::read_with_id`](super::MessageReader::read_with_id)
89
pub fn read_with_id<'a>(
90
&'a mut self,
91
messages: &'a Messages<E>,
92
) -> MessageIteratorWithId<'a, E> {
93
MessageIteratorWithId::new(self, messages)
94
}
95
96
/// See [`MessageMutator::read_with_id`](super::MessageMutator::read_with_id)
97
pub fn read_mut_with_id<'a>(
98
&'a mut self,
99
messages: &'a mut Messages<E>,
100
) -> MessageMutIteratorWithId<'a, E> {
101
MessageMutIteratorWithId::new(self, messages)
102
}
103
104
/// See [`MessageReader::par_read`](super::MessageReader::par_read)
105
#[cfg(feature = "multi_threaded")]
106
pub fn par_read<'a>(&'a mut self, messages: &'a Messages<E>) -> MessageParIter<'a, E> {
107
MessageParIter::new(self, messages)
108
}
109
110
/// See [`MessageMutator::par_read`](super::MessageMutator::par_read)
111
#[cfg(feature = "multi_threaded")]
112
pub fn par_read_mut<'a>(
113
&'a mut self,
114
messages: &'a mut Messages<E>,
115
) -> MessageMutParIter<'a, E> {
116
MessageMutParIter::new(self, messages)
117
}
118
119
/// See [`MessageReader::len`](super::MessageReader::len)
120
pub fn len(&self, messages: &Messages<E>) -> usize {
121
// The number of messages in this reader is the difference between the most recent message
122
// and the last message seen by it. This will be at most the number of messages contained
123
// with the messages (any others have already been dropped)
124
// TODO: Warn when there are dropped messages, or return e.g. a `Result<usize, (usize, usize)>`
125
messages
126
.message_count
127
.saturating_sub(self.last_message_count)
128
.min(messages.len())
129
}
130
131
/// Amount of messages we missed.
132
pub fn missed_messages(&self, messages: &Messages<E>) -> usize {
133
messages
134
.oldest_message_count()
135
.saturating_sub(self.last_message_count)
136
}
137
138
/// See [`MessageReader::is_empty()`](super::MessageReader::is_empty)
139
pub fn is_empty(&self, messages: &Messages<E>) -> bool {
140
self.len(messages) == 0
141
}
142
143
/// See [`MessageReader::clear()`](super::MessageReader::clear)
144
pub fn clear(&mut self, messages: &Messages<E>) {
145
self.last_message_count = messages.message_count;
146
}
147
}
148
149