A multiplayer VR framework w/voice chat

stuff i wrote while bored at uni

+78
src/client/debug_camera.rs
··· 1 + use std::f32::consts::PI; 2 + 3 + use bevy::{ input::mouse::MouseMotion, prelude::* }; 4 + 5 + use crate::net::client::component::ClientNetworkingManager; 6 + 7 + #[derive(Component)] 8 + pub struct DebugCamera{ 9 + pitch: f32, 10 + yaw: f32 11 + } 12 + 13 + impl Default for DebugCamera{ 14 + fn default() -> Self { 15 + Self { 16 + pitch: 0.0, 17 + yaw: -PI / 2.0 18 + } 19 + } 20 + } 21 + 22 + pub fn fixed_update( 23 + mut query: Query<(&mut DebugCamera, &mut Transform)>, 24 + mut networking: Query<&mut ClientNetworkingManager> 25 + ){ 26 + let ( _, transform ) = query.single_mut().unwrap(); 27 + let net_manager = networking.single_mut().unwrap(); 28 + 29 + net_manager.update_server_position(transform.translation.clone(), transform.rotation.clone()); 30 + } 31 + 32 + pub fn update( 33 + mut query: Query<(&mut DebugCamera, &mut Transform)>, 34 + 35 + time: Res<Time>, 36 + 37 + keys: Res<ButtonInput<KeyCode>>, 38 + mouse_buttons: Res<ButtonInput<MouseButton>>, 39 + mut mouse_motion: MessageReader<MouseMotion>, 40 + ){ 41 + let mut delta_time = time.delta_secs(); 42 + if keys.pressed(KeyCode::ShiftLeft){ delta_time *= 2.0; } 43 + 44 + let ( mut debug, mut transform ) = query.single_mut().unwrap(); 45 + 46 + for ev in mouse_motion.read(){ 47 + if mouse_buttons.pressed(MouseButton::Right){ 48 + debug.pitch -= ev.delta.y * delta_time * 0.1; 49 + debug.yaw -= ev.delta.x * delta_time * 0.1; 50 + } 51 + } 52 + 53 + transform.rotation = Quat::from_euler(EulerRot::YXZ, debug.yaw, debug.pitch, 0.0); 54 + 55 + if keys.pressed(KeyCode::KeyW){ 56 + let dir = transform.forward(); 57 + transform.translation += dir * delta_time; 58 + } else if keys.pressed(KeyCode::KeyS){ 59 + let dir = -transform.forward(); 60 + transform.translation += dir * delta_time; 61 + } 62 + 63 + if keys.pressed(KeyCode::KeyA){ 64 + let dir = transform.left(); 65 + transform.translation += dir * delta_time; 66 + } else if keys.pressed(KeyCode::KeyD){ 67 + let dir = -transform.left(); 68 + transform.translation += dir * delta_time; 69 + } 70 + 71 + if keys.pressed(KeyCode::KeyE){ 72 + let dir = transform.up(); 73 + transform.translation += dir * delta_time; 74 + } else if keys.pressed(KeyCode::KeyQ){ 75 + let dir = -transform.up(); 76 + transform.translation += dir * delta_time; 77 + } 78 + }
-65
src/engine/debug_camera.rs
··· 1 - use std::f32::consts::PI; 2 - 3 - use bevy::{ input::mouse::MouseMotion, prelude::* }; 4 - 5 - #[derive(Component)] 6 - pub struct DebugCamera{ 7 - pitch: f32, 8 - yaw: f32 9 - } 10 - 11 - impl Default for DebugCamera{ 12 - fn default() -> Self { 13 - Self { 14 - pitch: 0.0, 15 - yaw: -PI / 2.0 16 - } 17 - } 18 - } 19 - 20 - pub fn setup( 21 - mut query: Query<(&mut DebugCamera, &mut Transform)>, 22 - time: Res<Time>, 23 - 24 - keys: Res<ButtonInput<KeyCode>>, 25 - mouse_buttons: Res<ButtonInput<MouseButton>>, 26 - mut mouse_motion: MessageReader<MouseMotion>, 27 - ){ 28 - let mut delta_time = time.delta_secs(); 29 - if keys.pressed(KeyCode::ShiftLeft){ delta_time *= 2.0; } 30 - 31 - for ( mut debug, mut transform ) in &mut query{ 32 - for ev in mouse_motion.read(){ 33 - if mouse_buttons.pressed(MouseButton::Right){ 34 - debug.pitch -= ev.delta.y * delta_time * 0.1; 35 - debug.yaw -= ev.delta.x * delta_time * 0.1; 36 - } 37 - } 38 - 39 - transform.rotation = Quat::from_euler(EulerRot::YXZ, debug.yaw, debug.pitch, 0.0); 40 - 41 - if keys.pressed(KeyCode::KeyW){ 42 - let dir = transform.forward(); 43 - transform.translation += dir * delta_time; 44 - } else if keys.pressed(KeyCode::KeyS){ 45 - let dir = -transform.forward(); 46 - transform.translation += dir * delta_time; 47 - } 48 - 49 - if keys.pressed(KeyCode::KeyA){ 50 - let dir = transform.left(); 51 - transform.translation += dir * delta_time; 52 - } else if keys.pressed(KeyCode::KeyD){ 53 - let dir = -transform.left(); 54 - transform.translation += dir * delta_time; 55 - } 56 - 57 - if keys.pressed(KeyCode::KeyE){ 58 - let dir = transform.up(); 59 - transform.translation += dir * delta_time; 60 - } else if keys.pressed(KeyCode::KeyQ){ 61 - let dir = -transform.up(); 62 - transform.translation += dir * delta_time; 63 - } 64 - } 65 - }
src/engine/mod.rs src/client/mod.rs
+23 -11
src/main.rs
··· 1 - use bevy::app::{ App, Startup }; 2 - 3 1 mod net; 4 2 mod util; 5 3 6 4 #[cfg(feature = "client")] 7 - mod engine; 5 + mod client; 8 6 9 7 fn main() { 10 - let mut app = App::new(); 11 - app.add_systems(Startup, move || net::handle_net().expect("Network Module Failed.")); 8 + 9 + #[cfg(not(feature = "client"))] 10 + net::handle_net().expect("Network Module Failed."); 12 11 13 12 #[cfg(feature = "client")] 14 13 { 15 - use bevy::{DefaultPlugins, app::Update}; 16 - app.add_plugins(DefaultPlugins); 14 + use std::sync::mpsc::channel; 17 15 18 - app.add_systems(Startup, engine::setup); 19 - app.add_systems(Update, engine::debug_camera::setup); 20 - } 16 + use bevy::{DefaultPlugins, app::{App, FixedUpdate, Startup, Update}, ecs::system::Commands}; 21 17 22 - app.run(); 18 + use crate::net::client::component::ClientNetworkingManager; 19 + 20 + let (sender, recv) = channel(); 21 + let net_manager = ClientNetworkingManager::from(sender); 22 + 23 + net::handle_net(recv).expect("Network Module Failed."); 24 + 25 + App::new() 26 + .add_plugins(DefaultPlugins) 27 + .add_systems(Startup, client::setup) 28 + .add_systems(Startup, move | mut commands: Commands | { 29 + commands.spawn(net_manager.clone()); 30 + }) 31 + .add_systems(Update, client::debug_camera::update) 32 + .add_systems(FixedUpdate, client::debug_camera::fixed_update) 33 + .run(); 34 + } 23 35 }
+27
src/net/client/component.rs
··· 1 + use std::sync::mpsc::Sender; 2 + 3 + use bevy::{ecs::component::Component, math::{Quat, Vec3}}; 4 + 5 + #[derive(Debug, Clone)] 6 + pub enum ClientNetworkingManagerCommand{ 7 + UpdatePlayerPosition(Vec3, Quat), 8 + } 9 + 10 + #[derive(Component, Debug, Clone)] 11 + pub struct ClientNetworkingManager{ 12 + cmd: Sender<ClientNetworkingManagerCommand> 13 + } 14 + 15 + impl From<Sender<ClientNetworkingManagerCommand>> for ClientNetworkingManager{ 16 + fn from(value: Sender<ClientNetworkingManagerCommand>) -> Self { 17 + Self { 18 + cmd: value 19 + } 20 + } 21 + } 22 + 23 + impl ClientNetworkingManager{ 24 + pub fn update_server_position(&self, pos: Vec3, rot: Quat){ 25 + self.cmd.send(ClientNetworkingManagerCommand::UpdatePlayerPosition(pos, rot)).unwrap(); 26 + } 27 + }
+51 -21
src/net/client/mod.rs
··· 1 - use std::{io::Read, net::{TcpStream, UdpSocket}, thread}; 1 + use std::{net::{TcpStream, UdpSocket}, sync::mpsc::{Receiver, channel}, thread}; 2 2 3 - use crate::net::{packet::{self, Packet, PacketTypes}, packets::link_udp::LinkUDP}; 3 + use bevy::math::{Quat, Vec3}; 4 4 5 - pub fn handle_net_client() -> anyhow::Result<()>{ 6 - let mut tcp = TcpStream::connect("127.0.0.1:2603")?; 7 - let udp = UdpSocket::bind("0.0.0.0:0")?; 5 + use crate::{net::{client::component::ClientNetworkingManagerCommand, connection::Connection, packet::PacketTypes, packets::update_server_position::UpdateServerPositions}, util::net::ipv4_address}; 8 6 9 - // TODO: Proper player networking controller 7 + pub mod component; 10 8 11 - thread::spawn(move || { 12 - let mut buf = [0; 1024]; 9 + pub enum NetClientCommand{ 10 + Connected(String), 11 + Disconnected, 12 + UpdatePlayerPosition(Vec3, Quat), 13 + RecvPacket(PacketTypes) 14 + } 13 15 14 - while let Ok(length) = tcp.read(&mut buf){ 15 - if length == 0 { break; } 16 + pub fn handle_net_client(cmd: Receiver<ClientNetworkingManagerCommand>) -> anyhow::Result<()>{ 17 + let tcp = TcpStream::connect("127.0.0.1:2603")?; 18 + let udp = UdpSocket::bind("0.0.0.0:0")?; 16 19 17 - let msg = &buf[0..length]; 18 - let packet = packet::parse(msg.into()); 20 + let ( sender_cmd, recv ) = channel(); 21 + let sender_cmd_1 = sender_cmd.clone(); 19 22 20 - match packet{ 21 - PacketTypes::NotifyConnectionInfo(info) => { 22 - dbg!(&info); 23 + thread::spawn(move || { 24 + while let Ok(cmd) = cmd.recv(){ 25 + match cmd{ 26 + ClientNetworkingManagerCommand::UpdatePlayerPosition(pos, rot) => 27 + sender_cmd_1.send(NetClientCommand::UpdatePlayerPosition(pos, rot)).unwrap(), 28 + } 29 + } 30 + }); 23 31 24 - let packet = LinkUDP { id: info.id }; 25 - let packet: Vec<_> = packet.to_buf().into(); 32 + thread::spawn(move || { 33 + let mut conn = Connection::new(tcp, udp,ipv4_address(127, 0, 0, 1, 2603), sender_cmd); 26 34 27 - udp.send_to(&packet, "127.0.0.1:2603").unwrap(); 35 + while let Ok(cmd) = recv.recv(){ 36 + match cmd{ 37 + NetClientCommand::Connected(id) => { 38 + println!("[INFO] Connected to server as {}", id); 39 + conn.id = id; 28 40 }, 29 - _ => {} 41 + NetClientCommand::Disconnected => { 42 + println!("[WARN] Disconnected from server."); 43 + }, 44 + NetClientCommand::UpdatePlayerPosition(pos, rot) => { 45 + let packet = UpdateServerPositions { position: pos, rotation: rot }; 46 + conn.try_send_unreliable(packet).unwrap(); 47 + }, 48 + NetClientCommand::RecvPacket(packet) => { 49 + match packet{ 50 + PacketTypes::PlayerJoinPacket(player) => { 51 + dbg!(player); 52 + }, 53 + PacketTypes::PlayerListPacket(players) => { 54 + dbg!(players); 55 + }, 56 + PacketTypes::PlayerLeavePacket(player) => { 57 + dbg!(player); 58 + }, 59 + _ => {} 60 + } 61 + } 30 62 } 31 63 } 32 - 33 - println!("[WARN] Client disconnected from server"); 34 64 }); 35 65 36 66 Ok(())
+166
src/net/connection.rs
··· 1 + use std::{fs, io::{Read, Write}, net::{SocketAddr, TcpStream, UdpSocket}, sync::mpsc::Sender, thread}; 2 + 3 + use nanoid::nanoid; 4 + 5 + #[cfg(feature = "client")] 6 + use crate::net::{client::NetClientCommand, packets::link_udp::LinkUDP}; 7 + #[cfg(not(feature = "client"))] 8 + use crate::net::{server::NetServerCommand, packets::notify_connection_info::NotifyConnectionInfo}; 9 + 10 + use crate::net::packet::{self, Packet, PacketTypes}; 11 + 12 + #[derive(Debug)] 13 + pub struct Connection{ 14 + tcp: TcpStream, 15 + 16 + #[cfg(not(feature = "client"))] 17 + udp: Option<SocketAddr>, 18 + #[cfg(not(feature = "client"))] 19 + main_thread_sender: Sender<NetServerCommand>, 20 + 21 + #[cfg(feature = "client")] 22 + udp: UdpSocket, 23 + #[cfg(feature = "client")] 24 + udp_server_address: SocketAddr, 25 + 26 + pub id: String 27 + } 28 + 29 + impl Connection{ 30 + #[cfg(not(feature = "client"))] 31 + pub fn new( stream: TcpStream, cmd: Sender<NetServerCommand> ) -> Self{ 32 + let mut conn = Self { 33 + tcp: stream, 34 + main_thread_sender: cmd.clone(), 35 + udp: None, 36 + 37 + id: nanoid!() 38 + }; 39 + 40 + conn.start_listener_thread(cmd).unwrap(); 41 + 42 + let packet = NotifyConnectionInfo::from(&conn); 43 + conn.send_reliable(packet).unwrap(); 44 + 45 + conn 46 + } 47 + 48 + #[cfg(not(feature = "client"))] 49 + fn start_listener_thread(&self, cmd: Sender<NetServerCommand>) -> anyhow::Result<()>{ 50 + let mut stream = self.tcp.try_clone()?; 51 + let id = self.id.clone(); 52 + 53 + thread::spawn(move || { 54 + let mut buf = [0; 1024]; 55 + while let Ok(length) = stream.read(&mut buf) { 56 + if length == 0 { break; } 57 + let msg = &buf[0..length]; 58 + 59 + let packet = packet::parse(msg.into()); 60 + } 61 + 62 + cmd.send(NetServerCommand::PlayerDisconnect(id)).unwrap(); 63 + }); 64 + 65 + Ok(()) 66 + } 67 + 68 + #[cfg(feature = "client")] 69 + pub fn new( tcp: TcpStream, udp: UdpSocket, udp_server_address: SocketAddr, cmd: Sender<NetClientCommand> ) -> Self{ 70 + let mut conn = Self { 71 + tcp: tcp, 72 + udp: udp, 73 + udp_server_address: udp_server_address, 74 + 75 + id: "".to_owned() 76 + }; 77 + 78 + conn.start_listener_thread(cmd).unwrap(); 79 + 80 + conn 81 + } 82 + 83 + #[cfg(feature = "client")] 84 + fn start_listener_thread(&self, cmd: Sender<NetClientCommand>) -> anyhow::Result<()>{ 85 + let mut tcp = self.tcp.try_clone()?; 86 + let udp = self.udp.try_clone()?; 87 + 88 + let udp_1 = self.udp.try_clone()?; 89 + let cmd_1 = cmd.clone(); 90 + 91 + let srv_addr = self.udp_server_address.clone(); 92 + 93 + thread::spawn(move || { // UDP RECV THREAD 94 + let mut buf = [0; 1024]; 95 + 96 + while let Ok((length, addr)) = udp_1.recv_from(&mut buf){ 97 + if addr != srv_addr{ continue; } 98 + 99 + let msg = &buf[0..length]; 100 + let packet = packet::parse(msg.into()); 101 + 102 + cmd_1.send(NetClientCommand::RecvPacket(packet)).unwrap(); 103 + } 104 + }); 105 + 106 + thread::spawn(move || { // TCP RECV THREAD 107 + let mut buf = [0; 1024]; 108 + 109 + while let Ok(length) = tcp.read(&mut buf){ 110 + if length == 0 { break; } 111 + 112 + let msg = &buf[0..length]; 113 + let packet = packet::parse(msg.into()); 114 + 115 + match packet{ 116 + PacketTypes::NotifyConnectionInfo(info) => { 117 + cmd.send(NetClientCommand::Connected(info.id.clone())).unwrap(); 118 + 119 + let packet = LinkUDP { id: info.id }; 120 + let packet: Vec<_> = packet.to_buf().into(); 121 + 122 + udp.send_to(&packet, "127.0.0.1:2603").unwrap(); 123 + }, 124 + _ => { 125 + cmd.send(NetClientCommand::RecvPacket(packet)).unwrap(); 126 + } 127 + } 128 + } 129 + 130 + cmd.send(NetClientCommand::Disconnected).unwrap(); 131 + }); 132 + 133 + Ok(()) 134 + } 135 + 136 + #[cfg(not(feature = "client"))] 137 + pub fn connect_udp(&mut self, address: SocketAddr){ 138 + self.udp = Some(address); 139 + } 140 + 141 + pub fn send_reliable(&mut self, packet: impl Packet) -> anyhow::Result<()>{ 142 + let buf: Vec<u8> = packet.to_buf().into(); 143 + self.tcp.write(&buf)?; 144 + 145 + Ok(()) 146 + } 147 + 148 + pub fn try_send_unreliable(&mut self, packet: impl Packet) -> anyhow::Result<()>{ 149 + let buf: Vec<u8> = packet.to_buf().into(); 150 + 151 + #[cfg(not(feature = "client"))] 152 + { 153 + if let Some(addr) = self.udp{ 154 + self.main_thread_sender.send(NetServerCommand::SendOverUDP(buf, addr))?; 155 + } else{ 156 + println!("[WARN] Cannot send unreliable packet to {}, using TCP instead.", self.id); 157 + self.tcp.write(&buf)?; 158 + } 159 + } 160 + 161 + #[cfg(feature = "client")] 162 + self.udp.send_to(&buf, self.udp_server_address)?; 163 + 164 + Ok(()) 165 + } 166 + }
+16 -4
src/net/mod.rs
··· 1 1 #[cfg(feature = "client")] 2 - mod client; 2 + use std::sync::mpsc::Receiver; 3 + 4 + #[cfg(feature = "client")] 5 + use crate::net::client::component::ClientNetworkingManagerCommand; 3 6 7 + #[cfg(feature = "client")] 8 + pub mod client; 9 + 10 + #[cfg(not(feature = "client"))] 4 11 mod server; 5 12 6 13 mod packet; 7 14 mod packets; 8 15 mod buffer; 9 16 10 - pub fn handle_net() -> anyhow::Result<()>{ 11 - #[cfg(feature = "client")] 12 - return client::handle_net_client(); 17 + mod connection; 13 18 19 + #[cfg(feature = "client")] 20 + pub fn handle_net( cmd: Receiver<ClientNetworkingManagerCommand> ) -> anyhow::Result<()>{ 21 + client::handle_net_client(cmd) 22 + } 23 + 24 + #[cfg(not(feature = "client"))] 25 + pub fn handle_net() -> anyhow::Result<()>{ 14 26 server::handle_net_server() 15 27 }
+14 -4
src/net/packet.rs
··· 1 1 use crate::net::{ 2 2 buffer::Buffer, 3 3 packets::{ 4 - link_udp::LinkUDP, 5 - notify_connection_info::NotifyConnectionInfo, 6 - null::Null, update_server_position::UpdateServerPositions 4 + link_udp::LinkUDP, notify_connection_info::NotifyConnectionInfo, null::Null, player_join_packet::PlayerJoinPacket, player_leave_packet::PlayerLeavePacket, player_list_packet::PlayerListPacket, update_server_position::UpdateServerPositions 7 5 } 8 6 }; 9 7 10 8 #[derive(Debug)] 11 9 pub enum PacketTypes{ 12 - UpdateServerPositions(UpdateServerPositions), 13 10 NotifyConnectionInfo(NotifyConnectionInfo), 14 11 LinkUDP(LinkUDP), 12 + 13 + UpdateServerPositions(UpdateServerPositions), 14 + 15 + PlayerJoinPacket(PlayerJoinPacket), 16 + PlayerListPacket(PlayerListPacket), 17 + PlayerLeavePacket(PlayerLeavePacket), 18 + 15 19 Null(Null) 16 20 } 17 21 ··· 26 30 match id{ 27 31 0 => PacketTypes::NotifyConnectionInfo(NotifyConnectionInfo::from_buf(buf)), 28 32 1 => PacketTypes::LinkUDP(LinkUDP::from_buf(buf)), 33 + 29 34 2 => PacketTypes::UpdateServerPositions(UpdateServerPositions::from_buf(buf)), 35 + 36 + 3 => PacketTypes::PlayerJoinPacket(PlayerJoinPacket::from_buf(buf)), 37 + 4 => PacketTypes::PlayerListPacket(PlayerListPacket::from_buf(buf)), 38 + 5 => PacketTypes::PlayerLeavePacket(PlayerLeavePacket::from_buf(buf)), 39 + 30 40 _ => PacketTypes::Null(Null::from_buf(buf)) 31 41 } 32 42 }
+5
src/net/packets/mod.rs
··· 1 1 pub mod notify_connection_info; 2 2 pub mod link_udp; 3 + 3 4 pub mod update_server_position; 5 + 6 + pub mod player_join_packet; 7 + pub mod player_list_packet; 8 + pub mod player_leave_packet; 4 9 5 10 pub mod null;
+1 -1
src/net/packets/notify_connection_info.rs
··· 1 - use crate::net::{buffer::Buffer, server::connection::Connection, packet::Packet}; 1 + use crate::net::{buffer::Buffer, connection::Connection, packet::Packet}; 2 2 3 3 #[derive(Debug)] 4 4 pub struct NotifyConnectionInfo{
+20
src/net/packets/player_join_packet.rs
··· 1 + use crate::net::{buffer::Buffer, packet::Packet}; 2 + 3 + #[derive(Debug, Clone)] 4 + pub struct PlayerJoinPacket{ 5 + pub id: String 6 + } 7 + 8 + impl Packet for PlayerJoinPacket{ 9 + fn to_buf(&self) -> Buffer { 10 + let mut buf = Buffer::empty(); 11 + buf.set_u16(3); 12 + buf.set_str(self.id.clone()); 13 + 14 + buf 15 + } 16 + 17 + fn from_buf(mut buf: Buffer) -> Self { 18 + Self { id: buf.get_str() } 19 + } 20 + }
+20
src/net/packets/player_leave_packet.rs
··· 1 + use crate::net::{buffer::Buffer, packet::Packet}; 2 + 3 + #[derive(Debug, Clone)] 4 + pub struct PlayerLeavePacket{ 5 + pub id: String 6 + } 7 + 8 + impl Packet for PlayerLeavePacket{ 9 + fn to_buf(&self) -> Buffer { 10 + let mut buf = Buffer::empty(); 11 + buf.set_u16(5); 12 + buf.set_str(self.id.clone()); 13 + 14 + buf 15 + } 16 + 17 + fn from_buf(mut buf: Buffer) -> Self { 18 + Self { id: buf.get_str() } 19 + } 20 + }
+25
src/net/packets/player_list_packet.rs
··· 1 + use crate::net::{buffer::Buffer, packet::Packet}; 2 + 3 + #[derive(Debug, Clone)] 4 + pub struct PlayerListPacket{ 5 + pub ids: Vec<String> 6 + } 7 + 8 + impl Packet for PlayerListPacket{ 9 + fn to_buf(&self) -> Buffer { 10 + let mut buf = Buffer::empty(); 11 + buf.set_u16(4); 12 + buf.set_u32(self.ids.len() as u32); 13 + 14 + for id in &self.ids{ buf.set_str(id.clone()); } 15 + buf 16 + } 17 + 18 + fn from_buf(mut buf: Buffer) -> Self { 19 + let mut ids = vec![]; 20 + let length = buf.get_u32(); 21 + 22 + for _ in 0..length{ ids.push(buf.get_str()); } 23 + Self { ids } 24 + } 25 + }
-72
src/net/server/connection.rs
··· 1 - use std::{fs, io::{Read, Write}, net::{SocketAddr, TcpStream, UdpSocket}, sync::mpsc::Sender, thread}; 2 - 3 - use nanoid::nanoid; 4 - 5 - use crate::net::{packet::Packet, packets::notify_connection_info::NotifyConnectionInfo, server::NetServerCommand}; 6 - 7 - #[derive(Debug)] 8 - pub struct Connection{ 9 - tcp: TcpStream, 10 - udp: Option<SocketAddr>, 11 - 12 - pub id: String 13 - } 14 - 15 - impl Connection{ 16 - pub fn new( stream: TcpStream, cmd: Sender<NetServerCommand> ) -> Self{ 17 - let mut conn = Self { 18 - tcp: stream, 19 - udp: None, 20 - 21 - id: nanoid!() 22 - }; 23 - 24 - conn.start_listener_thread(cmd).unwrap(); 25 - 26 - let packet = NotifyConnectionInfo::from(&conn); 27 - conn.send_reliable(packet).unwrap(); 28 - 29 - conn 30 - } 31 - 32 - fn start_listener_thread(&self, cmd: Sender<NetServerCommand>) -> anyhow::Result<()>{ 33 - let mut stream = self.tcp.try_clone()?; 34 - let id = self.id.clone(); 35 - 36 - thread::spawn(move || { 37 - let mut buf = [0; 1024]; 38 - while let Ok(length) = stream.read(&mut buf) { 39 - if length == 0 { break; } 40 - let msg = &buf[0..length]; 41 - } 42 - 43 - cmd.send(NetServerCommand::PlayerDisconnect(id)).unwrap(); 44 - }); 45 - 46 - Ok(()) 47 - } 48 - 49 - pub fn connect_udp(&mut self, address: SocketAddr){ 50 - self.udp = Some(address); 51 - } 52 - 53 - pub fn send_reliable(&mut self, packet: impl Packet) -> anyhow::Result<()>{ 54 - let buf: Vec<u8> = packet.to_buf().into(); 55 - self.tcp.write(&buf)?; 56 - 57 - Ok(()) 58 - } 59 - 60 - pub fn try_send_unreliable(&mut self, packet: impl Packet) -> anyhow::Result<()>{ 61 - let buf: Vec<u8> = packet.to_buf().into(); 62 - 63 - if let Some(addr) = self.udp{ 64 - UdpSocket::bind("0.0.0.0:0")?.send_to(&buf, addr)?; // TODO: Use shared UDP Socket. 65 - } else{ 66 - println!("[WARN] Cannot send unreliable packet to {}, using TCP instead.", self.id); 67 - self.tcp.write(&buf)?; 68 - } 69 - 70 - Ok(()) 71 - } 72 - }
+48 -13
src/net/server/mod.rs
··· 1 1 use std::{collections::HashMap, net::{SocketAddr, TcpListener, TcpStream, UdpSocket}, sync::mpsc::channel, thread}; 2 2 3 - use bevy::math::{Quat, Vec3, VectorSpace}; 3 + use bevy::math::{Quat, Vec3}; 4 4 5 - use crate::net::{packet::{self, PacketTypes}, server::{connection::Connection, remote_player::RemotePlayer}}; 5 + use crate::net::{connection::Connection, packet::{self, PacketTypes}, packets::{player_join_packet::PlayerJoinPacket, player_leave_packet::PlayerLeavePacket, player_list_packet::{self, PlayerListPacket}}, server::remote_player::RemotePlayer}; 6 6 7 - pub mod connection; 8 7 pub mod remote_player; 9 8 10 9 pub enum NetServerCommand{ 11 10 CreateConnection(TcpStream), 12 11 LinkUDP(String, SocketAddr), 13 - PlayerDisconnect(String) 12 + PlayerDisconnect(String), 13 + SendOverUDP(Vec<u8>, SocketAddr), 14 + RecvOverUDP(SocketAddr, PacketTypes) 14 15 } 15 16 16 17 pub fn handle_net_server() -> anyhow::Result<()>{ 17 18 let tcp_listener = TcpListener::bind("0.0.0.0:2603")?; 19 + 18 20 let udp_listener = UdpSocket::bind("0.0.0.0:2603")?; 21 + let udp_listener_1 = udp_listener.try_clone()?; 19 22 20 - let ( sender_1, recv ) = channel(); 21 - let sender_2 = sender_1.clone(); 22 - let sender_3 = sender_1.clone(); 23 + let ( sender, recv ) = channel(); 24 + let sender_1 = sender.clone(); 25 + let sender_2 = sender.clone(); 23 26 24 27 thread::spawn(move || { 25 28 loop { 26 29 let ( socket, _ ) = tcp_listener.accept().unwrap(); 27 - sender_1.send(NetServerCommand::CreateConnection(socket)).unwrap(); 30 + sender.send(NetServerCommand::CreateConnection(socket)).unwrap(); 28 31 } 29 32 }); 30 33 ··· 39 42 40 43 match packet{ 41 44 PacketTypes::LinkUDP(info) => { 42 - sender_2.send(NetServerCommand::LinkUDP(info.id, address)).unwrap(); 45 + sender_1.send(NetServerCommand::LinkUDP(info.id, address)).unwrap(); 46 + } 47 + _ => { 48 + sender_1.send(NetServerCommand::RecvOverUDP(address, packet)).unwrap(); 43 49 } 44 - _ => {} 45 50 } 46 51 } 47 52 }); 48 53 49 - let mut connections = HashMap::new(); 50 - let mut players = HashMap::new(); 54 + let mut connections: HashMap<String, Connection> = HashMap::new(); 55 + let mut connections_by_address: HashMap<SocketAddr, String> = HashMap::new(); 56 + 57 + let mut players: HashMap<String, RemotePlayer> = HashMap::new(); 51 58 52 59 while let Ok(cmd) = recv.recv(){ 53 60 match cmd{ 54 61 NetServerCommand::CreateConnection(socket) => { 55 - let conn = Connection::new(socket, sender_3.clone()); 62 + let mut conn = Connection::new(socket, sender_2.clone()); 56 63 let player = RemotePlayer { 57 64 id: conn.id.clone(), 58 65 position: Vec3::default(), ··· 61 68 62 69 println!("[INFO] Connected {}", conn.id); 63 70 71 + let player_join_packet = PlayerJoinPacket { id: conn.id.clone() }; 72 + 73 + for ( _, player ) in &mut connections{ 74 + player.send_reliable(player_join_packet.clone())?; 75 + } 76 + 77 + let player_list_packet = PlayerListPacket { 78 + ids: players.iter().map(|(id,_)| id.clone()).collect() 79 + }; 80 + 81 + conn.send_reliable(player_list_packet).unwrap(); 82 + 64 83 connections.insert(conn.id.clone(), conn); 65 84 players.insert(player.id.clone(), player); 66 85 } 67 86 NetServerCommand::LinkUDP(id, addr) => { 68 87 if let Some(conn) = connections.get_mut(&id){ 88 + connections_by_address.insert(addr.clone(), id); 69 89 conn.connect_udp(addr); 70 90 } 71 91 }, ··· 73 93 players.remove(&id); 74 94 connections.remove(&id); 75 95 96 + let player_leave_packet = PlayerLeavePacket { id: id.clone() }; 97 + 98 + for ( _, player ) in &mut connections{ 99 + player.send_reliable(player_leave_packet.clone())?; 100 + } 101 + 76 102 println!("[INFO] Disconnected {}", id); 103 + }, 104 + NetServerCommand::SendOverUDP(buf, addr) => { 105 + udp_listener_1.send_to(&buf, addr)?; 106 + }, 107 + NetServerCommand::RecvOverUDP(addr, packet) => { 108 + let conn_id = &connections_by_address[&addr]; 109 + let conn = &connections[conn_id]; 110 + 111 + 77 112 } 78 113 } 79 114 }
+2 -1
src/util/mod.rs
··· 1 - pub mod angles; 1 + pub mod angles; 2 + pub mod net;
+5
src/util/net.rs
··· 1 + use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; 2 + 3 + pub fn ipv4_address(a: u8, b: u8, c: u8, d: u8, port: u16) -> SocketAddr{ 4 + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(a, b, c, d), port)) 5 + }