more docs
This commit is contained in:
parent
8b537f8339
commit
8a1aa4b31f
@ -97,6 +97,8 @@ impl PacketHandler for ExamplePacketHandler {
|
|||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// Инициализируем логи
|
||||||
|
// Чтобы читать debug-логи, юзаем `RUST_LOG=debug cargo run`
|
||||||
colog::init();
|
colog::init();
|
||||||
|
|
||||||
// Получение аргументов
|
// Получение аргументов
|
||||||
|
@ -6,6 +6,8 @@ use uuid::Uuid;
|
|||||||
|
|
||||||
use super::{config::Config, event::{Listener, PacketHandler}, player::context::ClientContext};
|
use super::{config::Config, event::{Listener, PacketHandler}, player::context::ClientContext};
|
||||||
|
|
||||||
|
// Контекст сервера
|
||||||
|
// Должен быть обернут в Arc для передачи между потоками
|
||||||
pub struct ServerContext {
|
pub struct ServerContext {
|
||||||
pub config: Arc<Config>,
|
pub config: Arc<Config>,
|
||||||
pub clients: DashMap<SocketAddr, Arc<ClientContext>>,
|
pub clients: DashMap<SocketAddr, Arc<ClientContext>>,
|
||||||
|
@ -1,2 +1,11 @@
|
|||||||
|
use rust_mc_proto::{DataReader, DataWriter};
|
||||||
|
|
||||||
|
use super::ServerError;
|
||||||
|
|
||||||
pub mod text_component;
|
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>;
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use palette::{Hsl, IntoColor, Srgb};
|
use palette::{Hsl, IntoColor, Srgb};
|
||||||
use rust_mc_proto::{DataReader, Packet};
|
use rust_mc_proto::Packet;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
|
||||||
use crate::server::ServerError;
|
use crate::server::ServerError;
|
||||||
|
|
||||||
|
use super::ReadWriteNBT;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
@ -21,6 +21,7 @@ pub struct TextComponent {
|
|||||||
pub strikethrough: Option<bool>,
|
pub strikethrough: Option<bool>,
|
||||||
pub obfuscated: Option<bool>,
|
pub obfuscated: Option<bool>,
|
||||||
pub extra: Option<Vec<TextComponent>>,
|
pub extra: Option<Vec<TextComponent>>,
|
||||||
|
// TODO: добавить все остальные стандартные поля для текст-компонента типа клик ивентов и сделать отдельный структ для транслейт компонент
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextComponent {
|
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 {
|
impl ReadWriteNBT<TextComponent> for Packet {
|
||||||
fn read_nbt(&mut self) -> Result<TextComponent, ServerError> {
|
fn read_nbt(&mut self) -> Result<TextComponent, ServerError> {
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
|
@ -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_export]
|
||||||
macro_rules! trigger_packet {
|
macro_rules! trigger_packet {
|
||||||
($packet:expr, $client:ident, $state:ident, $bound:ident) => {
|
($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_export]
|
||||||
macro_rules! trigger_event {
|
macro_rules! trigger_event {
|
||||||
($client:ident, $event:ident, $($arg:expr),* $(,)?) => {{
|
($client:ident, $event:ident, $(, $arg_ty:ty)* $(,)?) => {{
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
trigger_event!(@declare_mut_vars 0, $($arg),*);
|
|
||||||
|
|
||||||
for handler in $client.server.listeners(
|
for handler in $client.server.listeners(
|
||||||
|o| o.[<on_ $event _priority>]()
|
|o| o.[<on_ $event _priority>]()
|
||||||
).iter() {
|
).iter() {
|
||||||
handler.[<on_ $event>](
|
handler.[<on_ $event>](
|
||||||
$client.clone(),
|
$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 {
|
pub trait Listener: Sync + Send {
|
||||||
|
@ -17,12 +17,13 @@ pub mod protocol;
|
|||||||
// Ошибки сервера
|
// Ошибки сервера
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ServerError {
|
pub enum ServerError {
|
||||||
UnknownPacket(String),
|
UnknownPacket(String), // Неизвестный пакет, в строке указана ситуация в которой он неизвестен
|
||||||
Protocol(ProtocolError),
|
Protocol(ProtocolError), // Ошибка в протоколе при работе с rust_mc_proto
|
||||||
ConnectionClosed,
|
ConnectionClosed, // Соединение закрыто, единственная ошибка которая не логируется у handle_connection
|
||||||
SerTextComponent,
|
SerTextComponent, // Ошибка при сериализации текст-компонента
|
||||||
DeTextComponent,
|
DeTextComponent, // Ошибка при десериализации текст-компонента
|
||||||
UnexpectedState
|
UnexpectedState, // Указывает на то что этот пакет не может быть отправлен в данном режиме (в основном через ProtocolHelper)
|
||||||
|
Other(String) // Другая ошибка, либо очень специфичная, либо хз, лучше не использовать и создавать новое поле ошибки
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for ServerError {
|
impl Display for ServerError {
|
||||||
@ -76,6 +77,8 @@ pub fn start_server(server: Arc<ServerContext>) {
|
|||||||
// Передавется во все листенеры и хандлеры чтобы определять именно этот клиент
|
// Передавется во все листенеры и хандлеры чтобы определять именно этот клиент
|
||||||
let client = Arc::new(ClientContext::new(server.clone(), conn));
|
let client = Arc::new(ClientContext::new(server.clone(), conn));
|
||||||
|
|
||||||
|
// Добавляем клиента в список клиентов сервера
|
||||||
|
// Используем адрес как ключ, врятли ipv4 будет нам врать
|
||||||
server.clients.insert(client.addr, client.clone());
|
server.clients.insert(client.addr, client.clone());
|
||||||
|
|
||||||
// Обработка подключения
|
// Обработка подключения
|
||||||
@ -88,6 +91,7 @@ pub fn start_server(server: Arc<ServerContext>) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Удаляем клиента из списка клиентов
|
||||||
server.clients.remove(&client.addr);
|
server.clients.remove(&client.addr);
|
||||||
|
|
||||||
info!("Отключение: {}", addr);
|
info!("Отключение: {}", addr);
|
||||||
|
@ -7,7 +7,8 @@ use crate::server::{context::ServerContext, protocol::ConnectionState, ServerErr
|
|||||||
|
|
||||||
use super::protocol::ProtocolHelper;
|
use super::protocol::ProtocolHelper;
|
||||||
|
|
||||||
|
// Клиент контекст
|
||||||
|
// Должен быть обернут в Arc для передачи между потоками
|
||||||
pub struct ClientContext {
|
pub struct ClientContext {
|
||||||
pub server: Arc<ServerContext>,
|
pub server: Arc<ServerContext>,
|
||||||
pub addr: SocketAddr,
|
pub addr: SocketAddr,
|
||||||
@ -18,6 +19,8 @@ pub struct ClientContext {
|
|||||||
state: RwLock<ConnectionState>
|
state: RwLock<ConnectionState>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Реализуем сравнение через адрес
|
||||||
|
// IPv4 не должен обманывать, иначе у нас случится коллапс
|
||||||
impl PartialEq for ClientContext {
|
impl PartialEq for ClientContext {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.addr == other.addr
|
self.addr == other.addr
|
||||||
|
@ -2,11 +2,18 @@ use std::{io::Read, sync::Arc};
|
|||||||
|
|
||||||
use rust_mc_proto::{DataReader, DataWriter, Packet};
|
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;
|
use super::context::ClientContext;
|
||||||
|
|
||||||
|
|
||||||
|
// Помощник в работе с протоколом
|
||||||
|
// Может быть использован где угодно, но сделан именно для листенеров и пакет хандлеров
|
||||||
|
// Через него удобно делать всякую одинаковую херь
|
||||||
|
// Возможно надо было бы сделать прям обязательный какойто структ через который только можно было отправлять пакеты ...
|
||||||
|
// ... но мне лень
|
||||||
|
// Пусть юзают подключение и отправляют пакеты через него если хотят
|
||||||
|
// Почему бы и нет если да
|
||||||
pub struct ProtocolHelper {
|
pub struct ProtocolHelper {
|
||||||
client: Arc<ClientContext>,
|
client: Arc<ClientContext>,
|
||||||
state: ConnectionState
|
state: ConnectionState
|
||||||
|
Loading…
Reference in New Issue
Block a user