benthic_ui 0.3.0

Bevy UI plugin for open metaverse clients
Documentation
use crossbeam_channel::Sender;
use metaverse_messages::packet::message::UIMessage;
use std::net::UdpSocket;

use log::{info, warn};

/// This is for your UI to listen on the data coming out of the core.
/// import this and use directly, or modify to suit your own needs.
/// By default you can use this to run in the background, and subscribe to the outgoing events
/// using crossbeam.
/// Events will be sent to the crossbeam sender, and received in your UI with the crossbeam
/// receiver.
/// ```rust
/// use metaverse_session::client_subscriber::listen_for_server_events;
/// use crossbeam_channel::{unbounded, Receiver, Sender};
/// use std::thread::spawn;
/// use tokio::runtime::Runtime;
/// use portpicker::pick_unused_port;
///
/// let server_to_ui_socket = pick_unused_port().map_or_else(|| "No port found".to_string(), |port| port.to_string());
///
/// spawn(move || {
///     let rt = Runtime::new().expect("Failed to create Tokio runtime");
///     rt.block_on(async {
///         listen_for_server_events(server_to_ui_socket, sender).await;
///     });
/// });
/// ```
///
/// In your UI you can use something like this to handle events.
/// just remember to keep your crossbeam_channels as shared resources.
/// for example, create the crossbeam_channels in your main function, start your thread, save that
/// channel to a global variable, and then run handle_queue once per frame.
/// ```text
/// use crossbeam_channel::Receiver;
///
///fn handle_queue(receiver: Receiver) {
///    while let Ok(event) = receiver.try_recv() {
///         match event{
///             PacketType::LoginResponse(login_response) => {
///                 // handle the login response
///             }
///             PacketType::CoarseLocationUpdate(coarse_location_update) => {
///                 // handle the coarse location update
///             }
///             // etc for the rest of the event packets
///         }
///     }
///}
///```
pub async fn listen_for_core_events(core_to_ui_socket: String, sender: Sender<UIMessage>) {
    let socket = UdpSocket::bind(core_to_ui_socket).expect("Failed to bind UDP socket");

    info!("UI listening for core events on UDP: {:?}", socket);
    loop {
        let mut buf = [0u8; 1500];
        match socket.recv_from(&mut buf) {
            Ok((n, _)) => {
                if let Ok(packet) = UIMessage::from_bytes(&buf[..n]) {
                    // get the packet type and send that to the sender
                    if let Err(e) = sender.send(packet) {
                        warn!("Failed to send packet to UI: {:?}", e)
                    };
                }
            }
            Err(e) => {
                warn!("UI Failed to read buffer {}", e)
            }
        }
    }
}