//! Example `no_std` compatible Bevy library.12// The first step to a `no_std` library is to add this annotation:34#![no_std]56// This does 2 things to your crate:7// 1. It prevents automatically linking the `std` crate with yours.8// 2. It switches to `core::prelude` instead of `std::prelude` for what is implicitly9// imported in all modules in your crate.1011// It is common to want to use `std` when it's available, and fall-back to an alternative12// implementation which may make compromises for the sake of compatibility.13// To do this, you can conditionally re-include the standard library:1415#[cfg(feature = "std")]16extern crate std;1718// This still uses the `core` prelude, so items such as `std::println` aren't implicitly included19// in all your modules, but it does make them available to import.2021// Because Bevy requires access to an allocator anyway, you are free to include `alloc` regardless22// of what features are enabled.23// This gives you access to `Vec`, `String`, `Box`, and many other allocation primitives.2425extern crate alloc;2627// Here's our first example of using something from `core` instead of `std`.28// Since `std` re-exports `core` items, they are the same type just with a different name.29// This means any 3rd party code written for `std::time::Duration` will work identically for30// `core::time::Duration`.3132use core::time::Duration;3334// With the above boilerplate out of the way, everything below should look very familiar to those35// who have worked with Bevy before.3637use bevy::prelude::*;3839// While this example doesn't need it, a lot of fundamental types which are exclusively in `std`40// have alternatives in `bevy::platform`.41// If you find yourself needing a `HashMap`, `RwLock`, or `Instant`, check there first!4243#[expect(unused_imports, reason = "demonstrating some available items")]44use bevy::platform::{45collections::{HashMap, HashSet},46hash::DefaultHasher,47sync::{48atomic::{AtomicBool, AtomicUsize},49Arc, Barrier, LazyLock, Mutex, Once, OnceLock, RwLock, Weak,50},51time::Instant,52};5354// Note that `bevy::platform::sync::Arc` exists, despite `alloc::sync::Arc` being available.55// The reason is not every platform has full support for atomic operations, so `Arc`, `AtomicBool`,56// etc. aren't always available.57// You can test for their inclusion with `#[cfg(target_has_atomic = "ptr")]` and other related flags.58// You can get a more cross-platform alternative from `portable-atomic`, but Bevy handles this for you!59// Simply use `bevy::platform::sync` instead of `core::sync` and `alloc::sync` when possible,60// and Bevy will handle selecting the fallback from `portable-atomic` when it is required.6162/// Plugin for working with delayed components.63///64/// You can delay the insertion of a component by using [`insert_delayed`](EntityCommandsExt::insert_delayed).65pub struct DelayedComponentPlugin;6667impl Plugin for DelayedComponentPlugin {68fn build(&self, app: &mut App) {69app.add_systems(Update, tick_timers);70}71}7273/// Extension trait providing [`insert_delayed`](EntityCommandsExt::insert_delayed).74pub trait EntityCommandsExt {75/// Insert the provided [`Bundle`] `B` with a provided `delay`.76fn insert_delayed<B: Bundle>(&mut self, bundle: B, delay: Duration) -> &mut Self;77}7879impl EntityCommandsExt for EntityCommands<'_> {80fn insert_delayed<B: Bundle>(&mut self, bundle: B, delay: Duration) -> &mut Self {81self.insert((82DelayedComponentTimer(Timer::new(delay, TimerMode::Once)),83DelayedComponent(bundle),84))85.observe(unwrap::<B>)86}87}8889impl EntityCommandsExt for EntityWorldMut<'_> {90fn insert_delayed<B: Bundle>(&mut self, bundle: B, delay: Duration) -> &mut Self {91self.insert((92DelayedComponentTimer(Timer::new(delay, TimerMode::Once)),93DelayedComponent(bundle),94))95.observe(unwrap::<B>)96}97}9899#[derive(Component, Deref, DerefMut, Reflect, Debug)]100#[reflect(Component)]101struct DelayedComponentTimer(Timer);102103#[derive(Component)]104#[component(immutable)]105struct DelayedComponent<B: Bundle>(B);106107#[derive(EntityEvent)]108struct Unwrap;109110fn tick_timers(111mut commands: Commands,112mut query: Query<(Entity, &mut DelayedComponentTimer)>,113time: Res<Time>,114) {115for (entity, mut timer) in &mut query {116timer.tick(time.delta());117118if timer.just_finished() {119commands120.entity(entity)121.remove::<DelayedComponentTimer>()122.trigger(Unwrap);123}124}125}126127fn unwrap<B: Bundle>(event: On<Unwrap>, world: &mut World) {128if let Ok(mut target) = world.get_entity_mut(event.entity())129&& let Some(DelayedComponent(bundle)) = target.take::<DelayedComponent<B>>()130{131target.insert(bundle);132}133134world.despawn(event.observer());135}136137138