Abort Commands

Introduction

This page explains the Abort Command pattern that can be used to exit a command chain. If this is the first time using IoC+, we suggest to read the introduction first.

Abort Command

Let’s say we have a player that has to jump on the jump input, but only if the player isn’t tired. We could check if the player is tired in a PlayerJumpCommand, but this behavior would then be hidden in that command. Instead, we can add a separate command that aborts the command chain when the player is tired. Let’s see how that command would look.

public class AbortIfTiredCommand : Command {

    [Inject] PlayerStatus playerStatus;

    protected override void Execute() {
        if (playerStatus.IsTired) {
            Abort();
        }
    }

}

The command uses the PlayerStatus to check whether the player is indeed tired and calls the command’s Abort() methods accordingly. Calling the Abort() method will prevent the command binder from executing any of the next commands. Let’s see how we would set this up in the context.

public class GameContext : Context {

    protected override void SetBindings() {
        base.SetBindings();

        Bind<PlayerStatus>();
        Bind<JumpInputSignal>();
        Bind<PlayerJumpSignal>();

        On<JumpInputSignal>().Do<AbortIfTiredCommand>()
                             .Do<PlayerJumpCommand>();
    }

}

Here we first bind the AbortIfTiredCommand and only then bind the PlayerJumpCommand. The PlayerJumpCommand will now only be executed when the player is not tired.

Using the Abort Command pattern will help you build up a whole range of reusable commands that allow you to change small and large parts of your game by rewriting just a few lines of code. You can also chain multiple Abort Commands. In this case, you could add an Do<AbortIfInAirCommand>() before the jump command to only jump when both not tired and on the ground.

If/Else Command Chain

Let’s say we want something different to happen when the player actually is tired, for example, sigh. In IoC+, each On<T>() method will generate a new command chain. So commands that are bound to a second On<T>() call will still be executed when the first command chain is aborted. Let’s see how we can make use of this.

public class GameContext : Context {

    protected override void SetBindings() {
        base.SetBindings();

        Bind<PlayerStatus>();
        Bind<JumpInputSignal>();
        Bind<PlayerJumpSignal>();

        On<JumpInputSignal>().Do<AbortIfTiredCommand>()
                             .Do<PlayerJumpSignal>();

        On<JumpInputSignal>().Do<AbortIfNotTiredCommand>()
                             .Do<PlayerSighSignal>();
    }

}

See how the On<JumpInputSignal>() is called twice? This generates two separate command chains that are immune to each other’s abort. The player will now either jump or sign when the jump input is dispatched as either AbortIfTiredCommand or AbortIfNotTiredCommand will abort a command chain. We call this pattern the If/Else Command Chain as it behaves just like an if/else statement.