use std::{hash::Hash, net::{SocketAddr, TcpStream}, sync::{Arc, RwLock, RwLockWriteGuard}}; use dashmap::DashMap; use itertools::Itertools; use rust_mc_proto::{MinecraftConnection, Packet}; use uuid::Uuid; use crate::{config::Config, data::ServerError, player::{ClientInfo, Handshake, PlayerInfo}}; pub struct ServerContext { pub config: Arc, pub clients: DashMap>, listeners: Vec>, handlers: Vec> } impl ServerContext { pub fn new(config: Arc) -> ServerContext { ServerContext { config, listeners: Vec::new(), handlers: Vec::new(), clients: DashMap::new() } } pub fn get_player_by_uuid(self: &Arc, uuid: Uuid) -> Option> { self.clients.iter() .find(|o| { let info = o.player_info(); if let Some(info) = info { info.uuid == uuid } else { false } }) .map(|o| o.clone()) } pub fn get_player_by_name(self: &Arc, name: &str) -> Option> { self.clients.iter() .find(|o| { let info = o.player_info(); if let Some(info) = info { info.name == name } else { false } }) .map(|o| o.clone()) } pub fn players(self: &Arc) -> Vec> { self.clients.iter() .filter(|o| o.player_info().is_some()) .map(|o| o.clone()) .collect() } pub fn add_packet_handler(&mut self, handler: Box) { self.handlers.push(handler); } pub fn add_listener(&mut self, listener: Box) { self.listeners.push(listener); } pub fn packet_handlers( self: &Arc, sort_by: F ) -> Vec<&Box> where K: Ord, F: FnMut(&&Box) -> K { self.handlers.iter().sorted_by_key(sort_by).collect_vec() } pub fn listeners( self: &Arc, sort_by: F ) -> Vec<&Box> where K: Ord, F: FnMut(&&Box) -> K { self.listeners.iter().sorted_by_key(sort_by).collect_vec() } } pub struct ClientContext { pub server: Arc, pub conn: RwLock>, pub addr: SocketAddr, pub handshake: RwLock>, pub client_info: RwLock>, pub player_info: RwLock> } impl PartialEq for ClientContext { fn eq(&self, other: &Self) -> bool { self.addr == other.addr } } impl Hash for ClientContext { fn hash(&self, state: &mut H) { self.addr.hash(state); } } impl Eq for ClientContext {} impl ClientContext { pub fn new( server: Arc, conn: MinecraftConnection ) -> ClientContext { ClientContext { server, addr: conn.get_ref().peer_addr().unwrap(), conn: RwLock::new(conn), handshake: RwLock::new(None), client_info: RwLock::new(None), player_info: RwLock::new(None) } } pub fn set_handshake(self: &Arc, handshake: Handshake) { *self.handshake.write().unwrap() = Some(handshake); } pub fn set_client_info(self: &Arc, client_info: ClientInfo) { *self.client_info.write().unwrap() = Some(client_info); } pub fn set_player_info(self: &Arc, player_info: PlayerInfo) { *self.player_info.write().unwrap() = Some(player_info); } pub fn handshake(self: &Arc) -> Option { self.handshake.read().unwrap().clone() } pub fn client_info(self: &Arc) -> Option { self.client_info.read().unwrap().clone() } pub fn player_info(self: &Arc) -> Option { self.player_info.read().unwrap().clone() } pub fn conn(self: &Arc) -> RwLockWriteGuard<'_, MinecraftConnection> { self.conn.write().unwrap() } } pub trait Listener: Sync + Send { fn on_status_priority(&self) -> i8 { 0 } fn on_status(&self, _: Arc, _: &mut String) -> Result<(), ServerError> { Ok(()) } } pub trait PacketHandler: Sync + Send { fn on_incoming_packet_priority(&self) -> i8 { 0 } fn on_incoming_packet(&self, _: Arc, _: &mut Packet, _: ConnectionState) -> Result<(), ServerError> { Ok(()) } fn on_outcoming_packet_priority(&self) -> i8 { 0 } fn on_outcoming_packet(&self, _: Arc, _: &mut Packet, _: ConnectionState) -> Result<(), ServerError> { Ok(()) } } #[derive(Debug)] pub enum ConnectionState { Handshake, Status, Login, Configuration, Play } #[macro_export] macro_rules! call_handlers { ($packet:expr, $client:ident, $state:ident, incoming) => { { use crate::context::ConnectionState; let mut packet = $packet; for handler in $client.server.packet_handlers( |o| o.on_incoming_packet_priority() ).iter() { handler.on_incoming_packet($client.clone(), &mut packet, ConnectionState::$state)?; } packet.get_mut().set_position(0); packet } }; ($packet:expr, $client:ident, $state:ident, outcoming) => { { use crate::context::ConnectionState; let mut packet = $packet; for handler in $client.server.packet_handlers( |o| o.on_outcoming_packet_priority() ).iter() { handler.on_outcoming_packet($client.clone(), &mut packet, ConnectionState::$state)?; } packet.get_mut().set_position(0); packet } }; }