Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/message/message_writer.rs
6849 views
1
use crate::{
2
message::{Message, MessageId, Messages, WriteBatchIds},
3
system::{ResMut, SystemParam},
4
};
5
6
/// Writes [`Message`]s of type `T`.
7
///
8
/// # Usage
9
///
10
/// `MessageWriter`s are usually declared as a [`SystemParam`].
11
/// ```
12
/// # use bevy_ecs::prelude::*;
13
///
14
/// #[derive(Message)]
15
/// pub struct MyMessage; // Custom message type.
16
/// fn my_system(mut writer: MessageWriter<MyMessage>) {
17
/// writer.write(MyMessage);
18
/// }
19
///
20
/// # bevy_ecs::system::assert_is_system(my_system);
21
/// ```
22
///
23
/// # Concurrency
24
///
25
/// `MessageWriter` param has [`ResMut<Messages<T>>`](Messages) inside. So two systems declaring `MessageWriter<T>` params
26
/// for the same message type won't be executed concurrently.
27
///
28
/// # Untyped messages
29
///
30
/// `MessageWriter` can only write messages of one specific type, which must be known at compile-time.
31
/// This is not a problem most of the time, but you may find a situation where you cannot know
32
/// ahead of time every kind of message you'll need to write. In this case, you can use the "type-erased message" pattern.
33
///
34
/// ```
35
/// # use bevy_ecs::{prelude::*, message::Messages};
36
/// # #[derive(Message)]
37
/// # pub struct MyMessage;
38
/// fn write_untyped(mut commands: Commands) {
39
/// // Write a message of a specific type without having to declare that
40
/// // type as a SystemParam.
41
/// //
42
/// // Effectively, we're just moving the type parameter from the /type/ to the /method/,
43
/// // which allows one to do all kinds of clever things with type erasure, such as sending
44
/// // custom messages to unknown 3rd party plugins (modding API).
45
/// //
46
/// // NOTE: the message won't actually be sent until commands get applied during
47
/// // apply_deferred.
48
/// commands.queue(|w: &mut World| {
49
/// w.write_message(MyMessage);
50
/// });
51
/// }
52
/// ```
53
/// Note that this is considered *non-idiomatic*, and should only be used when `MessageWriter` will not work.
54
///
55
/// [`Observer`]: crate::observer::Observer
56
#[derive(SystemParam)]
57
pub struct MessageWriter<'w, E: Message> {
58
#[system_param(validation_message = "Message not initialized")]
59
messages: ResMut<'w, Messages<E>>,
60
}
61
62
impl<'w, E: Message> MessageWriter<'w, E> {
63
/// Writes an `message`, which can later be read by [`MessageReader`](super::MessageReader)s.
64
/// This method returns the [ID](`MessageId`) of the written `message`.
65
///
66
/// See [`Messages`] for details.
67
#[doc(alias = "send")]
68
#[track_caller]
69
pub fn write(&mut self, message: E) -> MessageId<E> {
70
self.messages.write(message)
71
}
72
73
/// Writes a list of `messages` all at once, which can later be read by [`MessageReader`](super::MessageReader)s.
74
/// This is more efficient than writing each message individually.
75
/// This method returns the [IDs](`MessageId`) of the written `messages`.
76
///
77
/// See [`Messages`] for details.
78
#[doc(alias = "send_batch")]
79
#[track_caller]
80
pub fn write_batch(&mut self, messages: impl IntoIterator<Item = E>) -> WriteBatchIds<E> {
81
self.messages.write_batch(messages)
82
}
83
84
/// Writes the default value of the message. Useful when the message is an empty struct.
85
/// This method returns the [ID](`MessageId`) of the written `message`.
86
///
87
/// See [`Messages`] for details.
88
#[doc(alias = "send_default")]
89
#[track_caller]
90
pub fn write_default(&mut self) -> MessageId<E>
91
where
92
E: Default,
93
{
94
self.messages.write_default()
95
}
96
}
97
98