diff --git a/src/main.rs b/src/main.rs index 37eb0c9..6a083e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -97,6 +97,8 @@ impl PacketHandler for ExamplePacketHandler { fn main() { + // Инициализируем логи + // Чтобы читать debug-логи, юзаем `RUST_LOG=debug cargo run` colog::init(); // Получение аргументов diff --git a/src/server/context.rs b/src/server/context.rs index 678b152..9814cd4 100644 --- a/src/server/context.rs +++ b/src/server/context.rs @@ -6,6 +6,8 @@ use uuid::Uuid; use super::{config::Config, event::{Listener, PacketHandler}, player::context::ClientContext}; +// Контекст сервера +// Должен быть обернут в Arc для передачи между потоками pub struct ServerContext { pub config: Arc, pub clients: DashMap>, diff --git a/src/server/data/mod.rs b/src/server/data/mod.rs index 62642bc..540fa53 100644 --- a/src/server/data/mod.rs +++ b/src/server/data/mod.rs @@ -1,2 +1,11 @@ +use rust_mc_proto::{DataReader, DataWriter}; + +use super::ServerError; + pub mod text_component; +// Трейт для чтения NBT-совместимых приколов +pub trait ReadWriteNBT: DataReader + DataWriter { + fn read_nbt(&mut self) -> Result; + fn write_nbt(&mut self, val: &T) -> Result<(), ServerError>; +} \ No newline at end of file diff --git a/src/server/data/text_component.rs b/src/server/data/text_component.rs index 36cac98..cd2b839 100644 --- a/src/server/data/text_component.rs +++ b/src/server/data/text_component.rs @@ -1,13 +1,13 @@ use std::io::Read; use palette::{Hsl, IntoColor, Srgb}; -use rust_mc_proto::{DataReader, Packet}; +use rust_mc_proto::Packet; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; use crate::server::ServerError; - +use super::ReadWriteNBT; #[derive(Debug, Serialize, Deserialize, Clone)] @@ -21,6 +21,7 @@ pub struct TextComponent { pub strikethrough: Option, pub obfuscated: Option, pub extra: Option>, + // TODO: добавить все остальные стандартные поля для текст-компонента типа клик ивентов и сделать отдельный структ для транслейт компонент } impl TextComponent { @@ -161,11 +162,7 @@ impl TextComponentBuilder { } } -pub trait ReadWriteNBT: DataReader { - fn read_nbt(&mut self) -> Result; - fn write_nbt(&mut self, val: &T) -> Result<(), ServerError>; -} - +// Реализуем читалку-записывалку текст-компонентов для пакета impl ReadWriteNBT for Packet { fn read_nbt(&mut self) -> Result { let mut data = Vec::new(); diff --git a/src/server/event/mod.rs b/src/server/event/mod.rs index 5b1526e..0277fcf 100644 --- a/src/server/event/mod.rs +++ b/src/server/event/mod.rs @@ -17,6 +17,20 @@ macro_rules! generate_handlers { }; } +// Пример использования: +// let packet_dst = trigger_packet!(packet_src, client, Handshake, incoming); +// │ │ │ │ +// ┌────────────────────┼───────────┼────────┼──────────┘ +// │ │ │ │ +// │ ┌─────┼───────────┘ │ +// │ │ │ │ +// │ │ │ └──────────────────┐ +// │ ▼ └───────────┐ │ +// Сделается вот такой вызов на всех packet_handler'ах: ▼ ▼ ▼ +// handler.on_incoming_packet(client.clone(), &mut packet, ConnectionState::Handshake) +// packet_src можно заменить на получение пакета, например: trigger_packet!(client.conn().read_packet()?, client, Handshake, incoming); +// В packet_dst будет лежать обратботанный пакет, прошедший через все хандлеры +// TODO: сделать чтобы можно было ваще отключить обработку #[macro_export] macro_rules! trigger_packet { ($packet:expr, $client:ident, $state:ident, $bound:ident) => { @@ -35,49 +49,25 @@ macro_rules! trigger_packet { }; } +// Честно ни разу не проверял работу этого дерьма +// Пример использования: +// trigger_event!(client, status, $mut response, state); +// Сделается вот такой вызов на всех листенерах: +// listener.on_status(client.clone(), &mut response, state); #[macro_export] macro_rules! trigger_event { - ($client:ident, $event:ident, $($arg:expr),* $(,)?) => {{ + ($client:ident, $event:ident, $(, $arg_ty:ty)* $(,)?) => {{ paste::paste! { - trigger_event!(@declare_mut_vars 0, $($arg),*); - for handler in $client.server.listeners( |o| o.[]() ).iter() { handler.[]( $client.clone(), - $(trigger_event!(@expand_arg 0, $arg)),* + $(, $arg_ty)* )?; } } }}; - - (@declare_mut_vars $i:tt, &mut $head:expr, $($tail:tt)*) => { - paste::paste! { - let mut [<__arg $i>] = $head; - } - trigger_event!(@declare_mut_vars trigger_event!(@inc $i), $($tail)*); - }; - (@declare_mut_vars $i:tt, $head:expr, $($tail:tt)*) => { - trigger_event!(@declare_mut_vars trigger_event!(@inc $i), $($tail)*); - }; - (@declare_mut_vars $_i:tt,) => {}; - - (@expand_arg $i:tt, &mut $head:expr) => { - paste::paste! { &mut [<__arg $i>] } - }; - (@expand_arg $_i:tt, $head:expr) => { - $head - }; - - (@inc 0) => { 1 }; - (@inc 1) => { 2 }; - (@inc 2) => { 3 }; - (@inc 3) => { 4 }; - (@inc 4) => { 5 }; - (@inc 5) => { 6 }; - (@inc 6) => { 7 }; - (@inc 7) => { 8 }; } pub trait Listener: Sync + Send { diff --git a/src/server/mod.rs b/src/server/mod.rs index f8c6510..2935fcd 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -17,12 +17,13 @@ pub mod protocol; // Ошибки сервера #[derive(Debug)] pub enum ServerError { - UnknownPacket(String), - Protocol(ProtocolError), - ConnectionClosed, - SerTextComponent, - DeTextComponent, - UnexpectedState + UnknownPacket(String), // Неизвестный пакет, в строке указана ситуация в которой он неизвестен + Protocol(ProtocolError), // Ошибка в протоколе при работе с rust_mc_proto + ConnectionClosed, // Соединение закрыто, единственная ошибка которая не логируется у handle_connection + SerTextComponent, // Ошибка при сериализации текст-компонента + DeTextComponent, // Ошибка при десериализации текст-компонента + UnexpectedState, // Указывает на то что этот пакет не может быть отправлен в данном режиме (в основном через ProtocolHelper) + Other(String) // Другая ошибка, либо очень специфичная, либо хз, лучше не использовать и создавать новое поле ошибки } impl Display for ServerError { @@ -76,6 +77,8 @@ pub fn start_server(server: Arc) { // Передавется во все листенеры и хандлеры чтобы определять именно этот клиент let client = Arc::new(ClientContext::new(server.clone(), conn)); + // Добавляем клиента в список клиентов сервера + // Используем адрес как ключ, врятли ipv4 будет нам врать server.clients.insert(client.addr, client.clone()); // Обработка подключения @@ -88,6 +91,7 @@ pub fn start_server(server: Arc) { }, }; + // Удаляем клиента из списка клиентов server.clients.remove(&client.addr); info!("Отключение: {}", addr); diff --git a/src/server/player/context.rs b/src/server/player/context.rs index e04385f..ce0f5a7 100644 --- a/src/server/player/context.rs +++ b/src/server/player/context.rs @@ -7,7 +7,8 @@ use crate::server::{context::ServerContext, protocol::ConnectionState, ServerErr use super::protocol::ProtocolHelper; - +// Клиент контекст +// Должен быть обернут в Arc для передачи между потоками pub struct ClientContext { pub server: Arc, pub addr: SocketAddr, @@ -18,6 +19,8 @@ pub struct ClientContext { state: RwLock } +// Реализуем сравнение через адрес +// IPv4 не должен обманывать, иначе у нас случится коллапс impl PartialEq for ClientContext { fn eq(&self, other: &Self) -> bool { self.addr == other.addr diff --git a/src/server/player/protocol.rs b/src/server/player/protocol.rs index adbd67c..3c5a784 100644 --- a/src/server/player/protocol.rs +++ b/src/server/player/protocol.rs @@ -2,11 +2,18 @@ use std::{io::Read, sync::Arc}; use rust_mc_proto::{DataReader, DataWriter, Packet}; -use crate::server::{data::text_component::{ReadWriteNBT, TextComponent}, protocol::ConnectionState, ServerError}; +use crate::server::{data::text_component::TextComponent, data::ReadWriteNBT, protocol::ConnectionState, ServerError}; use super::context::ClientContext; +// Помощник в работе с протоколом +// Может быть использован где угодно, но сделан именно для листенеров и пакет хандлеров +// Через него удобно делать всякую одинаковую херь +// Возможно надо было бы сделать прям обязательный какойто структ через который только можно было отправлять пакеты ... +// ... но мне лень +// Пусть юзают подключение и отправляют пакеты через него если хотят +// Почему бы и нет если да pub struct ProtocolHelper { client: Arc, state: ConnectionState