Skip to content

Commit

Permalink
rework example
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanSWard committed May 26, 2021
1 parent e93fdfa commit aa166a9
Showing 1 changed file with 67 additions and 44 deletions.
111 changes: 67 additions & 44 deletions examples/ecs/command_error_handling.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,74 @@
use bevy::prelude::*;
use bevy::{core::FixedTimestep, prelude::*};

fn main() {
App::build()
.add_startup_system(handle_command_error.system())
.add_startup_system(setup.system())
.add_system_set(
SystemSet::new()
.with_run_criteria(FixedTimestep::step(0.5))
.with_system(remove_components.system()),
)
.add_system_set(
SystemSet::new()
.with_run_criteria(FixedTimestep::step(2.0))
.with_system(despawn_all_entities.system()),
)
.run();
}

#[derive(Debug)]
struct AComponent(usize);

fn handle_command_error(mut commands: Commands) {
let e = commands.spawn().id();

// Immediately despawn the entity.
commands.entity(e).despawn();

// This `despawn` command will fail because the entity was already despawned!
// If no error handler is specified, the error will be logged.
commands.entity(e).despawn();

// Optionally, `on_failure` allows you to provide a custom error handler!
commands
.entity(e)
.insert(AComponent(0))
.on_failure(|CommandError { error, world, .. }| {
// You'll notice that the `error` will also give you back the component you
// attempted to insert on the entity.

println!(
"Sadly our component '{:?}' for entity '{:?}' didn't insert... :(",
error.component, error.entity
);

// error handlers have mutable access to `World`
world.insert_resource("🐦");
});

// Some nice things:
// - You can still chain commands!
// - There are a slew of built-in error handlers
commands
.entity(e)
.insert(AComponent(1))
.ignore() // `ignore` will neither log nor panic the error
.insert(AComponent(2))
.log_on_failure(); // `log_on_failure` is the default behavior, and will log the error

// Uncomment the below line to see the command error cause a panic due to `panic_on_failure`
// commands.entity(e).despawn().panic_on_failure();
struct A(usize);

#[derive(Bundle, Default)]
struct B {
value: usize,
}

struct FailedDespawnAttempts(usize);

fn setup(mut commands: Commands) {
for i in 0..3 {
// Note that `insert` and `insert_bundle` are fallible functions.
// If no error handler is specified, the default behavior is to log the error, and continue.
// These calls to `insert` and `insert_bundle` will not fail, since the entity is valid.
commands.spawn().insert(A(i)).insert_bundle(B::default());
}

commands.insert_resource(FailedDespawnAttempts(0));
}

fn despawn_all_entities(mut commands: Commands, query: Query<Entity>) {
for e in query.iter() {
// `on_failure` allows you to provide a custom error handler!
commands
.entity(e)
.despawn()
.on_failure(|CommandError { error, world, .. }| {
// You'll notice that the `error` will also give you back the entity
// you tried to despawn.
let entity = error.entity;

println!("Sadly our entity '{:?}' didn't despawned... :(", entity);

// error handlers have mutable access to `World`
if let Some(mut failed_despawns) = world.get_resource_mut::<FailedDespawnAttempts>()
{
failed_despawns.0 += 1;
}
});
}
}

fn remove_components(mut commands: Commands, query: Query<Entity>) {
for e in query.iter() {
// Some nice things:
// - You can still chain commands!
// - There are a slew of built-in error handlers
commands
.entity(e)
.remove::<A>()
.ignore() // `ignore` will neither log nor panic the error
.remove_bundle::<B>()
.log_on_failure(); // `log_on_failure` is the default behavior, and will log the error.
// `panic_on_failure` is another alternative which will panic on the error.
}
}

0 comments on commit aa166a9

Please sign in to comment.