use std::{hash::Hash, net::{SocketAddr, TcpStream}, sync::{Arc, RwLock, RwLockWriteGuard}}; use dashmap::DashMap; use itertools::Itertools; use rust_mc_proto::MinecraftConnection; use uuid::Uuid; use crate::{config::Config, data::ServerError, event::{ConnectionState, Listener, PacketHandler}, player::{ClientInfo, Handshake, PlayerInfo, ProtocolHelper}}; 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 addr: SocketAddr, conn: RwLock>, handshake: RwLock>, client_info: RwLock>, player_info: RwLock>, state: 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), state: RwLock::new(ConnectionState::Handshake) } } 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 set_state(self: &Arc, state: ConnectionState) -> Result<(), ServerError> { *self.state.write().unwrap() = state.clone(); for handler in self.server.packet_handlers( |o| o.on_state_priority() ).iter() { handler.on_state(self.clone(), state.clone())?; } Ok(()) } 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 state(self: &Arc) -> ConnectionState { self.state.read().unwrap().clone() } pub fn conn(self: &Arc) -> RwLockWriteGuard<'_, MinecraftConnection> { self.conn.write().unwrap() } pub fn protocol_helper(self: &Arc) -> ProtocolHelper { ProtocolHelper::new(self.clone()) } }