use std::{net::TcpStream, sync::{Arc, Mutex}}; use bevy_ecs::system::Resource; use crossbeam::channel::{unbounded, Receiver, Sender}; use starkingdoms_common::packet::{MsgFromError, Packet}; use tungstenite::{connect, stream::MaybeTlsStream, Message, WebSocket}; pub trait PacketMessageConvert { fn from_message(value: &Message) -> Result; fn into_message(&self) -> Message; } impl PacketMessageConvert for Packet { fn from_message(value: &Message) -> Result { match value { Message::Text(s) => serde_json::from_str(s).map_err(MsgFromError::JSONError), Message::Binary(b) => serde_json::from_slice(b).map_err(MsgFromError::JSONError), Message::Close(_) => Ok(Packet::_SpecialDisconnect {}), Message::Frame(_) | Message::Pong(_) | Message::Ping(_) => { Err(MsgFromError::InvalidMessageType) } } } fn into_message(&self) -> Message { Message::Text(serde_json::to_string(self).expect("failed to serialize packet to json").into()) } } #[derive(Resource, Debug)] pub struct Ws { socket: Arc>>>, pub sender: Sender, pub receiver: Receiver, packet_receiver: Receiver, } impl Ws { pub fn new() -> Self { let (socket, _) = connect("ws://localhost:3000").expect("Failed to connect to server"); let socket = Arc::new(Mutex::new(socket)); let (packet_sender, receiver) = unbounded(); let (sender, packet_receiver) = unbounded(); let socket_clone = socket.clone(); std::thread::spawn(move || { let socket = socket_clone; loop { let message = socket.lock().unwrap().read().expect("Failed to reading message"); let packet = Packet::from_message(&message).expect("Server sent invalid packet"); packet_sender.send(packet).expect("Couldn't send packet to server"); } }); Ws { socket, sender, receiver, packet_receiver, } } pub fn send_packet(&mut self, packet: &Packet) { self.socket.lock().unwrap().send(packet.into_message()).expect("Couldn't send packet to server"); } }