use std::time::{Duration, SystemTime};
use bevy_app::prelude::*;
use bevy_ecs::lifecycle::HookContext;
use bevy_ecs::prelude::*;
use bevy_ecs::world::DeferredWorld;
use bevy_reflect::prelude::*;
#[derive(Component, Clone, Copy, Debug, PartialEq, Eq)]
#[component(on_insert = rearm)]
pub struct WakeAt(pub SystemTime);
impl WakeAt {
pub fn after(after: Duration) -> Self {
Self(SystemTime::now() + after)
}
pub fn left(&self, now: SystemTime) -> Duration {
self.0.duration_since(now).unwrap_or_default()
}
}
#[derive(Component, Clone, Copy, Debug, Default)]
#[component(storage = "SparseSet")]
pub struct Due;
#[derive(Component, Reflect, Clone, Copy, Debug)]
#[reflect(Component, Clone, Debug)]
pub struct KeepAwake(pub Duration);
pub struct ClockPlugin;
impl Plugin for ClockPlugin {
fn build(&self, app: &mut App) {
app.add_systems(First, mark_due);
}
}
fn rearm(mut world: DeferredWorld, context: HookContext) {
world.commands().entity(context.entity).try_remove::<Due>();
}
fn mark_due(waits: Query<(Entity, &WakeAt), Without<Due>>, mut commands: Commands) {
let now = SystemTime::now();
for (entity, wake) in &waits {
if wake.0 <= now {
commands.entity(entity).try_insert(Due);
}
}
}
#[cfg(test)]
mod tests;