networkinator 0.1.2

Crate for network on bevy
use std::io::Error;
use bevy::app::App;
use bevy::prelude::{error, First, IntoScheduleConfigs, Message, MessageWriter, Plugin};
use crate::{NetRes, NetResMut};
use crate::shared::plugins::messaging::MessagingPlugin;
use crate::shared::plugins::network::{ClientConnection, CurrentNetworkSides, LocalSessionUUID, NetworkConnection, NetworkType, ServerConnection};

pub struct ClientNetworkPlugin;

#[derive(Message)]
pub struct ClientPortConnected{
    pub port_id: u32,
    pub connection_id: u32,
}

#[derive(Message)]
pub struct ClientPortDisconnected{
    pub port_id: u32,
    pub connection_id: u32,
    pub error: Option<Error>,
    pub was_connected: bool
}

impl Plugin for ClientNetworkPlugin {
    fn build(&self, app: &mut App) {
        let messaging_plugin_added = app.is_plugin_added::<MessagingPlugin>();

        let current_network_sides = app.world_mut().get_resource_mut::<CurrentNetworkSides>();

        if let Some(mut current_network_sides) = current_network_sides {
            if messaging_plugin_added {
                error!("Insert MessagingPlugin for last");
                return;
            }

            current_network_sides.side().iter_mut().for_each(|network_type| {
                if network_type == &NetworkType::DedicatedServer{
                    *network_type = NetworkType::LocalServer;
                }
            });

            current_network_sides.insert_side(NetworkType::Client)
        }else{
            app.insert_resource(CurrentNetworkSides::new(Vec::from([
                NetworkType::Client
            ])));
        }

        app.add_message::<ClientPortConnected>();
        app.add_message::<ClientPortDisconnected>();
        app.add_systems(First,(start_ports,start_listening_ports,ping_ports,check_port_disconnected).chain());
    }
}

pub fn start_ports(
    mut network_connection: NetResMut<NetworkConnection<ClientConnection>>,
    mut client_port_connected: MessageWriter<ClientPortConnected>,
    server_network_connection: Option<NetRes<NetworkConnection<ServerConnection>>>,
){
    for (connection_id,client_connection) in &mut network_connection.0 {
        if client_connection.is_local_connection() {
            continue;
        } else if let Some(server_network_connection) = server_network_connection.as_ref() && server_network_connection.0.contains_key(connection_id) {
            client_connection.set_as_local_connection();
            continue;
        }

        if let (Some(main_port), network_port_shared_infos) = client_connection.get_port_split(0) {
            let (started,started_now) = main_port.started();

            if started {
                if started_now {
                    client_port_connected.write(ClientPortConnected{
                        port_id: 0,
                        connection_id: *connection_id,
                    });
                }
            }else if let Some(network_port_shared_infos) = network_port_shared_infos{
                main_port.start(network_port_shared_infos);
            }
        }

        let ports_amount = client_connection.get_ports_amount();

        for port_id in 1..=ports_amount {
            if let (Some(port),network_port_shared_infos) = client_connection.get_port_split(port_id) {
                let (started,started_now) = port.started();

                if started {
                    if started_now {
                        client_port_connected.write(ClientPortConnected{
                            port_id,
                            connection_id: *connection_id,
                        });
                    }
                    continue
                }

                if let Some(network_port_shared_infos) = network_port_shared_infos{
                    port.start(network_port_shared_infos);
                }
            }
        }
    }
}

pub fn start_listening_ports(
    mut network_connection: NetResMut<NetworkConnection<ClientConnection>>,
){
    for (_,client_connection) in &mut network_connection.0.iter_mut() {
        if let (Some(main_port), network_port_shared_infos) = client_connection.get_port_split(0) && let Some(network_port_shared_infos) = network_port_shared_infos {
            main_port.listen_to_server(network_port_shared_infos);
        }

        let ports_amount = client_connection.get_ports_amount();

        for port_id in 1..=ports_amount {
            if let (Some(port), network_port_shared_infos) = client_connection.get_port_split(port_id) && let Some(network_port_shared_infos) = network_port_shared_infos {
                port.listen_to_server(network_port_shared_infos);
            }
        }
    }
}

pub fn ping_ports(
    mut network_connection: NetResMut<NetworkConnection<ClientConnection>>,
    local_session_uuid: NetRes<LocalSessionUUID>,
){
    if let Some(local_session_uuid) = local_session_uuid.get_session_uuid() {
        for (_,client_connection) in &mut network_connection.0.iter_mut() {
            if let (Some(main_port), network_port_shared_infos) = client_connection.get_port_split(0) && let Some(network_port_shared_infos) = network_port_shared_infos {
                main_port.ping(local_session_uuid, network_port_shared_infos);
            }

            let ports_amount = client_connection.get_ports_amount();

            for port_id in 1..=ports_amount {
                if let (Some(port), network_port_shared_infos) = client_connection.get_port_split(port_id) && let Some(network_port_shared_infos) = network_port_shared_infos {
                    port.ping(local_session_uuid, network_port_shared_infos);
                }
            }
        }
    }
}

pub fn check_port_disconnected(
    mut network_connection: NetResMut<NetworkConnection<ClientConnection>>,
    mut client_port_disconnected: MessageWriter<ClientPortDisconnected>
){
    for (connection_id,client_connection) in &mut network_connection.0 {
        if let Some(main_port) = client_connection.get_port(0) {
            let (disconnected,error,was_connected) = main_port.disconnected();

            if disconnected {
                client_port_disconnected.write(ClientPortDisconnected{
                    port_id: 0,
                    connection_id: *connection_id,
                    error,
                    was_connected
                });
            }
        }

        let ports_amount = client_connection.get_ports_amount();

        for port_id in 1..=ports_amount {
            if let Some(port) = client_connection.get_port(port_id) {
                let (disconnected,error,was_connected) = port.disconnected();

                if disconnected {
                    client_port_disconnected.write(ClientPortDisconnected{
                        port_id,
                        connection_id: *connection_id,
                        error,
                        was_connected
                    });
                }
            }
        }
    }
}