more docs

This commit is contained in:
MeexReay 2025-05-02 20:11:04 +03:00
parent 8b537f8339
commit 8a1aa4b31f
8 changed files with 60 additions and 46 deletions

View File

@ -97,6 +97,8 @@ impl PacketHandler for ExamplePacketHandler {
fn main() {
// Инициализируем логи
// Чтобы читать debug-логи, юзаем `RUST_LOG=debug cargo run`
colog::init();
// Получение аргументов

View File

@ -6,6 +6,8 @@ use uuid::Uuid;
use super::{config::Config, event::{Listener, PacketHandler}, player::context::ClientContext};
// Контекст сервера
// Должен быть обернут в Arc для передачи между потоками
pub struct ServerContext {
pub config: Arc<Config>,
pub clients: DashMap<SocketAddr, Arc<ClientContext>>,

View File

@ -1,2 +1,11 @@
use rust_mc_proto::{DataReader, DataWriter};
use super::ServerError;
pub mod text_component;
// Трейт для чтения NBT-совместимых приколов
pub trait ReadWriteNBT<T>: DataReader + DataWriter {
fn read_nbt(&mut self) -> Result<T, ServerError>;
fn write_nbt(&mut self, val: &T) -> Result<(), ServerError>;
}

View File

@ -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<bool>,
pub obfuscated: Option<bool>,
pub extra: Option<Vec<TextComponent>>,
// TODO: добавить все остальные стандартные поля для текст-компонента типа клик ивентов и сделать отдельный структ для транслейт компонент
}
impl TextComponent {
@ -161,11 +162,7 @@ impl TextComponentBuilder {
}
}
pub trait ReadWriteNBT<T>: DataReader {
fn read_nbt(&mut self) -> Result<T, ServerError>;
fn write_nbt(&mut self, val: &T) -> Result<(), ServerError>;
}
// Реализуем читалку-записывалку текст-компонентов для пакета
impl ReadWriteNBT<TextComponent> for Packet {
fn read_nbt(&mut self) -> Result<TextComponent, ServerError> {
let mut data = Vec::new();

View File

@ -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.[<on_ $event _priority>]()
).iter() {
handler.[<on_ $event>](
$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 {

View File

@ -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<ServerContext>) {
// Передавется во все листенеры и хандлеры чтобы определять именно этот клиент
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<ServerContext>) {
},
};
// Удаляем клиента из списка клиентов
server.clients.remove(&client.addr);
info!("Отключение: {}", addr);

View File

@ -7,7 +7,8 @@ use crate::server::{context::ServerContext, protocol::ConnectionState, ServerErr
use super::protocol::ProtocolHelper;
// Клиент контекст
// Должен быть обернут в Arc для передачи между потоками
pub struct ClientContext {
pub server: Arc<ServerContext>,
pub addr: SocketAddr,
@ -18,6 +19,8 @@ pub struct ClientContext {
state: RwLock<ConnectionState>
}
// Реализуем сравнение через адрес
// IPv4 не должен обманывать, иначе у нас случится коллапс
impl PartialEq for ClientContext {
fn eq(&self, other: &Self) -> bool {
self.addr == other.addr

View File

@ -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<ClientContext>,
state: ConnectionState