1use crate::command::{BoxedCommand, CommandQueueBuilder, CommandQueueReceiver, CommandQueueSender};
2use crate::entity::{AsyncEntity, SpawnAndSendId};
3use crate::system::{AsyncIOSystem, AsyncSystem};
4use crate::util::{insert_resource, remove_resource, trigger_targets};
5use crate::wait_for::StartWaitingFor;
6use crate::{die, recv, CowStr};
7use async_channel::Receiver;
8use bevy_ecs::observer::TriggerTargets;
9use bevy_ecs::prelude::*;
10use bevy_ecs::system::RunSystemOnce;
11use std::fmt;
12
13#[derive(Clone, Debug)]
31pub struct AsyncWorld(CommandQueueSender);
32
33impl AsyncWorld {
34 pub fn sender(&self) -> CommandQueueSender {
36 self.0.clone()
37 }
38
39 pub async fn apply<C: Command>(&self, command: C) {
41 self.0.send_single(BoxedCommand::new(command)).await
42 }
43
44 pub fn start_queue(&self) -> CommandQueueBuilder {
46 CommandQueueBuilder::new(self.sender())
47 }
48
49 pub async fn run_system<M>(self, system: impl IntoSystem<(), (), M> + Send + 'static) {
51 self.apply(|world: &mut World| {
52 _ = world.run_system_once(system);
53 })
54 .await
55 }
56
57 pub async fn register_system<M>(
59 &self,
60 system: impl IntoSystem<(), (), M> + Send,
61 ) -> AsyncSystem {
62 let system = Box::new(IntoSystem::into_system(system));
63 AsyncSystem::new(system, self.clone()).await
64 }
65
66 pub async fn register_io_system<I: Send + 'static, O: Send + 'static, M>(
69 &self,
70 system: impl IntoSystem<In<I>, O, M> + Send,
71 ) -> AsyncIOSystem<I, O> {
72 AsyncIOSystem::new(system, self.clone()).await
73 }
74
75 pub fn entity(&self, id: Entity) -> AsyncEntity {
78 AsyncEntity::new(id, self.clone())
79 }
80
81 pub async fn spawn_empty(&self) -> AsyncEntity {
84 let (command, receiver) = SpawnAndSendId::new_empty();
85 self.apply(command).await;
86 let id = recv(receiver).await;
87 AsyncEntity::new(id, self.clone())
88 }
89
90 pub async fn spawn<B: Bundle>(&self, bundle: B) -> AsyncEntity {
93 let (command, receiver) = SpawnAndSendId::new(bundle);
94 self.apply(command).await;
95 let id = recv(receiver).await;
96 AsyncEntity::new(id, self.clone())
97 }
98
99 pub async fn spawn_named(&self, name: impl Into<CowStr> + Send) -> AsyncEntity {
103 self.spawn(Name::new(name)).await
104 }
105
106 pub async fn insert_resource<R: Resource>(&self, resource: R) {
108 self.apply(insert_resource(resource)).await;
109 }
110
111 pub async fn remove_resource<R: Resource>(&self) {
113 self.apply(remove_resource::<R>()).await;
114 }
115
116 pub async fn start_waiting_for_resource<R: Resource + Clone>(&self) -> AsyncResource<R> {
122 let (start_waiting_for, rx) = StartWaitingFor::resource();
123 self.apply(start_waiting_for).await;
124 AsyncResource(rx)
125 }
126
127 pub async fn wait_for_resource<R: Resource + Clone>(&self) -> R {
132 self.start_waiting_for_resource().await.wait().await
133 }
134
135 pub async fn send_event<E: Event>(&self, event: E) {
137 self.apply(SendEvent(event)).await;
138 }
139
140 pub async fn start_waiting_for_events<E: Event + Clone>(&self) -> AsyncEvents<E> {
146 let (start_waiting_for, rx) = StartWaitingFor::events();
147 self.apply(start_waiting_for).await;
148 AsyncEvents(rx)
149 }
150
151 pub async fn wait_for_event<E: Event + Clone>(&self) -> E {
156 self.start_waiting_for_events().await.wait().await
157 }
158
159 pub async fn trigger<E: Event>(&self, event: E) {
161 self.trigger_targets(event, ()).await;
162 }
163
164 pub async fn trigger_targets<E: Event, T: TriggerTargets + Send + Sync + 'static>(
166 &self,
167 event: E,
168 targets: T,
169 ) {
170 self.apply(trigger_targets(event, targets)).await;
171 }
172}
173
174impl From<CommandQueueSender> for AsyncWorld {
175 fn from(sender: CommandQueueSender) -> Self {
176 Self(sender)
177 }
178}
179
180impl FromWorld for AsyncWorld {
181 fn from_world(world: &mut World) -> Self {
182 let (sender, receiver) = async_channel::unbounded();
183 world.spawn((
184 CommandQueueReceiver::new(receiver),
185 Name::new("CommandQueueReceiver"),
186 ));
187 CommandQueueSender::new(sender).into()
188 }
189}
190
191pub struct AsyncResource<R: Resource>(Receiver<R>);
195
196impl<R: Resource> fmt::Debug for AsyncResource<R> {
197 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 write!(f, "AsyncResource(..)")
199 }
200}
201
202impl<R: Resource> AsyncResource<R> {
203 pub async fn wait(self) -> R {
205 recv(self.0).await
206 }
207}
208
209struct SendEvent<E: Event>(E);
210
211impl<E: Event> Command for SendEvent<E> {
212 fn apply(self, world: &mut World) {
213 world
214 .send_event(self.0)
215 .ok_or("failed to send event")
216 .unwrap_or_else(die);
217 }
218}
219
220pub struct AsyncEvents<E: Event>(Receiver<E>);
224
225impl<E: Event> fmt::Debug for AsyncEvents<E> {
226 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227 write!(f, "AsyncEvents(..)")
228 }
229}
230
231impl<E: Event> AsyncEvents<E> {
232 pub async fn wait(&self) -> E {
235 recv(self.0.clone()).await
236 }
237}