bevy_ecs/message/mod.rs
1//! [`Message`] functionality.
2
3mod iterators;
4mod message_cursor;
5mod message_mutator;
6mod message_reader;
7mod message_registry;
8mod message_writer;
9mod messages;
10mod mut_iterators;
11mod update;
12
13pub use iterators::*;
14pub use message_cursor::*;
15pub use message_mutator::*;
16pub use message_reader::*;
17pub use message_registry::*;
18pub use message_writer::*;
19pub use messages::*;
20pub use mut_iterators::*;
21pub use update::*;
22
23pub use bevy_ecs_macros::Message;
24
25use crate::change_detection::MaybeLocation;
26#[cfg(feature = "bevy_reflect")]
27use bevy_reflect::Reflect;
28use core::{
29 cmp::Ordering,
30 fmt,
31 hash::{Hash, Hasher},
32 marker::PhantomData,
33};
34
35/// A buffered message for pull-based event handling.
36///
37/// Messages can be written with [`MessageWriter`] and read using the [`MessageReader`] system parameter.
38/// Messages are stored in the [`Messages<M>`] resource, and require periodically polling the world for new messages,
39/// typically in a system that runs as part of a schedule.
40///
41/// While the polling imposes a small overhead, messages are useful for efficiently batch processing
42/// a large number of messages at once. For cases like these, messages can be more efficient than [`Event`]s (which are handled via [`Observer`]s).
43///
44/// Unlike [`Event`]s triggered for observers, messages are evaluated at fixed points in the schedule
45/// rather than immediately when they are sent. This allows for more predictable scheduling, and deferring
46/// message processing to a later point in time.
47///
48/// Messages must be thread-safe.
49///
50/// # Usage
51///
52/// The [`Message`] trait can be derived:
53///
54/// ```
55/// # use bevy_ecs::prelude::*;
56/// #
57/// #[derive(Message)]
58/// struct Greeting(String);
59/// ```
60///
61/// The message can then be written to the message buffer using a [`MessageWriter`]:
62///
63/// ```
64/// # use bevy_ecs::prelude::*;
65/// #
66/// # #[derive(Message)]
67/// # struct Greeting(String);
68/// #
69/// fn write_hello(mut writer: MessageWriter<Greeting>) {
70/// writer.write(Greeting("Hello!".to_string()));
71/// }
72/// ```
73///
74/// Messages can be efficiently read using a [`MessageReader`]:
75///
76/// ```
77/// # use bevy_ecs::prelude::*;
78/// #
79/// # #[derive(Message)]
80/// # struct Greeting(String);
81/// #
82/// fn read_messages(mut reader: MessageReader<Greeting>) {
83/// // Process all messages of type `Greeting`.
84/// for Greeting(greeting) in reader.read() {
85/// println!("{greeting}");
86/// }
87/// }
88/// ```
89/// [`Event`]: crate::event::Event
90/// [`Observer`]: crate::observer::Observer
91#[diagnostic::on_unimplemented(
92 message = "`{Self}` is not an `Message`",
93 label = "invalid `Message`",
94 note = "consider annotating `{Self}` with `#[derive(Message)]`"
95)]
96pub trait Message: Send + Sync + 'static {}
97
98#[derive(Debug)]
99#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
100pub(crate) struct MessageInstance<M: Message> {
101 pub message_id: MessageId<M>,
102 pub message: M,
103}
104
105/// A [`MessageId`] uniquely identifies a message stored in a specific [`World`].
106///
107/// A [`MessageId`] can, among other things, be used to trace the flow of a [`Message`] from the point it was
108/// sent to the point it was processed. [`MessageId`]s increase monotonically by write order.
109///
110/// [`World`]: crate::world::World
111#[cfg_attr(
112 feature = "bevy_reflect",
113 derive(Reflect),
114 reflect(Clone, Debug, PartialEq, Hash)
115)]
116pub struct MessageId<M: Message> {
117 /// Uniquely identifies the message associated with this ID.
118 // This value corresponds to the order in which each message was written to the world.
119 pub id: usize,
120 /// The source code location that triggered this message.
121 pub caller: MaybeLocation,
122 #[cfg_attr(feature = "bevy_reflect", reflect(ignore, clone))]
123 pub(super) _marker: PhantomData<M>,
124}
125
126impl<M: Message> Copy for MessageId<M> {}
127
128impl<M: Message> Clone for MessageId<M> {
129 fn clone(&self) -> Self {
130 *self
131 }
132}
133
134impl<M: Message> fmt::Display for MessageId<M> {
135 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136 <Self as fmt::Debug>::fmt(self, f)
137 }
138}
139
140impl<M: Message> fmt::Debug for MessageId<M> {
141 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142 write!(
143 f,
144 "message<{}>#{}",
145 core::any::type_name::<M>().split("::").last().unwrap(),
146 self.id,
147 )
148 }
149}
150
151impl<M: Message> PartialEq for MessageId<M> {
152 fn eq(&self, other: &Self) -> bool {
153 self.id == other.id
154 }
155}
156
157impl<M: Message> Eq for MessageId<M> {}
158
159impl<M: Message> PartialOrd for MessageId<M> {
160 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
161 Some(self.cmp(other))
162 }
163}
164
165impl<M: Message> Ord for MessageId<M> {
166 fn cmp(&self, other: &Self) -> Ordering {
167 self.id.cmp(&other.id)
168 }
169}
170
171impl<M: Message> Hash for MessageId<M> {
172 fn hash<H: Hasher>(&self, state: &mut H) {
173 Hash::hash(&self.id, state);
174 }
175}