bevy-networker-multiplayer 0.1.2

Tiny Bevy networking plugin with automatic entity replication and resource sync.
Documentation
use bevy::prelude::*;
use bevy_networker_multiplayer::{sync, NetResource, Replicated, ReplicatedPlugin};

const ADDRESS: &str = "127.0.0.1:5001";

#[sync]
#[derive(Component)]
struct Position(Vec2);

#[sync]
#[derive(Component)]
struct Health(u32);

#[derive(Clone, Copy, PartialEq, Eq)]
enum Mode {
    Server,
    Client,
}

#[derive(Resource, Clone, Copy)]
struct DemoMode(Mode);

fn main() {
    let mode = parse_mode();

    let mut app = App::new();
    app.add_plugins(MinimalPlugins);
    app.add_plugins(ReplicatedPlugin);
    app.insert_resource(DemoMode(mode));
    app.add_systems(Startup, setup);

    match mode {
        Mode::Server => {
            app.add_systems(Update, server_motion);
        }
        Mode::Client => {
            app.add_systems(Update, client_report);
        }
    }

    app.run();
}

fn parse_mode() -> Mode {
    match std::env::args().nth(1).as_deref() {
        Some("server") => Mode::Server,
        Some("client") => Mode::Client,
        _ => {
            eprintln!("usage: cargo run --example replication_demo -- [server|client]");
            std::process::exit(1);
        }
    }
}

fn setup(mut commands: Commands, mut net: ResMut<NetResource>, mode: Res<DemoMode>) {
    match mode.0 {
        Mode::Server => {
            net.start_server(5001);
            println!("server listening on {ADDRESS}");
            commands.spawn((
                Replicated,
                Position(Vec2::ZERO),
                Health(100),
            ));
        }
        Mode::Client => {
            net.join_server(ADDRESS.to_string());
            println!("client connected to {ADDRESS}");
        }
    }
}

fn server_motion(
    time: Res<Time>,
    mut tick: Local<f32>,
    mut query: Query<&mut Position, With<Replicated>>,
) {
    *tick += time.delta_secs();
    if *tick < 1.0 {
        return;
    }
    *tick = 0.0;

    if let Ok(mut position) = query.single_mut() {
        position.0.x += 1.0;
        position.0.y += 0.5;
        println!("server position -> {:?}", position.0);
    }
}

fn client_report(
    time: Res<Time>,
    mut tick: Local<f32>,
    query: Query<(Entity, &Position, &Health), With<Replicated>>,
) {
    *tick += time.delta_secs();
    if *tick < 1.0 {
        return;
    }
    *tick = 0.0;

    for (entity, position, health) in &query {
        println!(
            "client entity {:?} => position {:?}, health {}",
            entity, position.0, health.0
        );
    }
}