use crate::{AccessResult, AsyncWorld};
use bevy::ecs::{
message::{Message, MessageReader},
resource::Resource,
system::ResMut,
};
use event_listener::Event;
use std::collections::VecDeque;
#[derive(Debug, Resource)]
pub struct EventChannel<T: Send + Sync> {
queue: VecDeque<T>,
event: Event,
}
impl<T: Send + Sync> Default for EventChannel<T> {
fn default() -> Self {
Self {
queue: Default::default(),
event: Default::default(),
}
}
}
impl<T: Send + Sync> EventChannel<T> {
pub fn take(&mut self) -> Option<T> {
self.queue.pop_front()
}
pub fn push(&mut self, value: T) {
if self.queue.is_empty() {
self.event.notify(usize::MAX);
}
self.queue.push_back(value);
}
pub fn clear(&mut self) {
self.queue.clear();
}
}
impl<T: Send + Sync> Extend<T> for EventChannel<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
if self.queue.is_empty() {
self.event.notify(usize::MAX);
}
self.queue.extend(iter);
}
}
impl AsyncWorld {
pub async fn next_event<E: Clone + Send + Sync + 'static>(&self) -> E {
loop {
let result = AsyncWorld
.resource::<EventChannel<E>>()
.get_mut(|x| x.take())
.expect("Event not registered");
if let Some(result) = result {
return result;
} else {
AsyncWorld
.resource::<EventChannel<E>>()
.get(|x| x.event.listen())
.expect("Event not registered")
.await;
}
}
}
pub async fn get_next_event<E: Clone + Send + Sync + 'static>(&self) -> AccessResult<E> {
loop {
let result = AsyncWorld
.resource::<EventChannel<E>>()
.get_mut(|x| x.take())?;
if let Some(result) = result {
return Ok(result);
} else {
AsyncWorld
.resource::<EventChannel<E>>()
.get(|x| x.event.listen())?
.await;
}
}
}
pub fn send_oneshot_event<E: Send + Sync + 'static>(&self, event: E) -> AccessResult {
AsyncWorld
.resource::<EventChannel<E>>()
.get_mut(|x| x.push(event))
}
}
pub fn react_to_message<E: Message + Clone>(
mut reader: MessageReader<E>,
mut channel: ResMut<EventChannel<E>>,
) {
channel.clear();
if !reader.is_empty() {
channel.extend(reader.read().cloned());
};
}