#shell #bevy-plugin #command #local #game-engine

bevy_local_commands

Simple local shell commands for the Bevy game engine

18 unstable releases (7 breaking)

new 0.8.0 Dec 6, 2024
0.7.0 Aug 23, 2024
0.6.0 Jul 9, 2024
0.5.0 Feb 18, 2024
0.2.2 Dec 29, 2023

#552 in Game dev

Download history 53/week @ 2024-08-17 144/week @ 2024-08-24 4/week @ 2024-08-31 6/week @ 2024-09-21 4/week @ 2024-09-28 1/week @ 2024-10-05 2/week @ 2024-10-12 10/week @ 2024-11-02 105/week @ 2024-11-30

112 downloads per month

MIT/Apache

47KB
521 lines

Bevy Local Commands

Bevy Local Commands Latest version Documentation MIT Apache

Bevy plugin to manage local shell commands.

Usage

Add the plugin:

// ...
.add_plugins(BevyLocalCommandsPlugin)
// ...

Run shell commands:

fn run_command(mut commands: Commands) {
    commands.spawn(LocalCommand::new("bash").args(["-c", "sleep 1 && echo slept"]));
}

See commands started and kill running commands:

fn kill_started_command(mut active_processes: Query<&mut Process>) {
    for mut process in active_processes.iter_mut() {
        warn!("Killing process {}", process.id());
        process.kill().unwrap();
    }
}

Receive command output:

fn get_command_output(mut process_output_event: EventReader<ProcessOutput>) {
    for output in process_output_event.read() {
        info!("Command output for entity {:?}", output.entity);

        for line in output.lines() {
            info!("Line Output: {}", line);
        }
    }
}

Send command input:

fn send_command_input(
    mut process_output_event: EventReader<ProcessOutput>,
    mut active_processes: Query<&mut Process>,
) {
    for output in process_output_event.read() {
        for line in output.lines() {
            if line.ends_with("Prompt String: ") {
                let mut process = active_processes.get_mut(output.entity).unwrap();
                process.println("Text to send").expect("Failed to write to process");
            }
        }
    }
}

See commands completed:

fn get_completed(mut process_completed_event: EventReader<ProcessCompleted>) {
    for completed in process_completed_event.read() {
        info!(
            "Command completed (Entity - {}, Success - {})",
            completed.entity,
            completed.exit_status.success()
        );
    }
}

Retries:

fn retries(mut commands: Commands) {
    commands.spawn((
        LocalCommand::new("bash").args(["-c", "sleep 1 && invalid-command --that=fails"]),
        Retry::Attempts(3) // Attempt the command 3 times before giving up
    ));
}

Cleanup:

fn cleanup_on_completion(mut commands: Commands) {
    commands.spawn((
        LocalCommand::new("bash").args(["-c", "sleep 1"]),
        Cleanup::DespawnEntity // Will despawn the entity upon process completion
        // Cleanup::RemoveComponents // Will remove only this crate's components upon process completion
    ));
}

Delay:

fn delay_process_start(mut commands: Commands) {
    commands.spawn((
        LocalCommand::new("bash").args(["-c", "sleep 1"]),
        Delay::Fixed(Duration::from_secs(2)), // Start the process after a 2s delay (applies to each retry)
    ));
}

Chaining:

fn chain_multiple_commands(mut commands: Commands) {
    commands.spawn((
        Chain::new(vec![
            LocalCommand::new("sh").args(["-c", "echo 'First command'"]),
            LocalCommand::new("sh").args(["-c", "echo 'Second command'"]),
            LocalCommand::new("sh").args(["-c", "echo 'Third command'"]),
        ]),
        Retry::Attempts(2), // Retry applies to any link in the chain
        Delay::Fixed(Duration::from_secs(3)), // Wait 3s between retries and chain commands
        Cleanup::RemoveComponents // Remove Chain, Retry, Delay, and Cleanup components upon completion
    ));
}

Todo

  • Mac testing (not sure if it works yet)

Bevy Compatilibity

bevy bevy_local_commands
0.15 0.8
0.14 0.7
0.13 0.5
0.12 0.4
0.11 0.1

Dependencies

~38–71MB
~1M SLoC