Skip to content

Commit

Permalink
Use CommandContext and update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanSWard committed Jun 24, 2021
1 parent 1e753f8 commit 1857ccd
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 18 deletions.
34 changes: 20 additions & 14 deletions crates/bevy_ecs/src/system/commands/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,23 @@ impl CommandErrorHandler {
///
/// ## Note
/// This is the default behavior if no error handler is specified.
pub fn log<E: Debug>(error: E, _world: &mut World) {
pub fn log<E: Debug>(error: E, _ctx: CommandContext) {
error!("Commands failed with error: {:?}", error)
}

/// If the command failed, [`panic!`] with the error.
pub fn panic<E: Debug>(error: E, _world: &mut World) {
pub fn panic<E: Debug>(error: E, _ctx: CommandContext) {
panic!("Commands failed with error: {:?}", error)
}

/// If the command failed, ignore the error and silently succeed.
pub fn ignore<E: Debug>(_error: E, _world: &mut World) {}
pub fn ignore<E>(_error: E, _ctx: CommandContext) {}
}

pub(crate) struct HandledErrorCommand<C, F>
where
C: FallibleCommand,
F: FnOnce(C::Error, &mut World) + Send + Sync + 'static,
F: FnOnce(C::Error, CommandContext) + Send + Sync + 'static,
{
pub(crate) command: C,
pub(crate) error_handler: F,
Expand All @@ -85,7 +85,7 @@ where
impl<C, F> Command for HandledErrorCommand<C, F>
where
C: FallibleCommand,
F: FnOnce(C::Error, &mut World) + Send + Sync + 'static,
F: FnOnce(C::Error, CommandContext) + Send + Sync + 'static,
{
fn write(self: Box<Self>, world: &mut World) {
let HandledErrorCommand {
Expand All @@ -94,11 +94,16 @@ where
} = *self;

if let Err(error) = command.try_write(world) {
error_handler(error, world);
error_handler(error, CommandContext { world });
}
}
}

#[non_exhaustive]
pub struct CommandContext<'a> {
pub world: &'a mut World,
}

/// Similar to [`FallibleCommandConfig`] however does not
/// implement [`DerefMut`] nor return `&mut T` of the underlying
/// Commands type.
Expand Down Expand Up @@ -147,10 +152,8 @@ macro_rules! impl_fallible_commands {
/// If the command failed, run the provided `error_handler`.
///
/// ## Note
/// This is normally used in conjunction with [`Handlers`].
/// However, this can also be used with custom error handler (e.g. closure)
/// if the parameter type is specific. You can use `on_err_do` if you don't
/// want to specify the type.
/// This is normally used in conjunction with [`CommandErrorHandler`].
/// However, this can also be used with custom error handlers (e.g. closures).
///
/// # Examples
/// ```
Expand All @@ -161,17 +164,20 @@ macro_rules! impl_fallible_commands {
/// commands.spawn().insert(42).on_err(CommandErrorHandler::ignore);
///
/// // custom error handler
/// commands.spawn().insert(42).on_err(|error, world| {});
/// commands.spawn().insert(42).on_err(|error, ctx| {});
/// }
/// ```
pub fn on_err(
&mut self,
handler: impl FnOnce(C::Error, &mut World) + Send + Sync + 'static,
error_handler: impl FnOnce(C::Error, CommandContext) + Send + Sync + 'static,
) -> $returnty {
let command = self.command.take().unwrap();
let command = self
.command
.take()
.expect("Cannot call `on_err` multiple times for a command error handler.");
self.inner.add_command(HandledErrorCommand {
command,
error_handler: handler,
error_handler,
});
self.$returnfunc()
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/system/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ impl<T> Debug for RemoveBundleError<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RemoveBundleError")
.field("entity", &self.entity)
.field("component_type", &std::any::type_name::<T>())
.field("bundle_type", &std::any::type_name::<T>())
.finish()
}
}
Expand Down
7 changes: 4 additions & 3 deletions examples/ecs/command_error_handling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,17 @@ fn log_failed_despawn_attempts(attempts: Res<FailedDespawnAttempts>) {

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

warn!("Sadly our entity '{:?}' didn't despawn :(", entity);

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

0 comments on commit 1857ccd

Please sign in to comment.