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};
use crate::networking::websocket::{PacketMessageConvert, Websocket};
impl PacketMessageConvert for Packet {
type M = Message;
fn from_message(value: &Message) -> Result<Packet, MsgFromError> {
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 as_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<Mutex<WebSocket<MaybeTlsStream<TcpStream>>>>,
pub sender: Sender<Packet>,
pub receiver: Receiver<Packet>,
packet_receiver: Receiver<Packet>,
}
impl Websocket for Ws {
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,
}
}
fn send_packet(&mut self, packet: Packet) {
self.socket
.lock()
.unwrap()
.send(packet.as_message())
.expect("Couldn't send packet to server");
}
}