From 92366360254d3a41ed6124a71f8309ea229a1766 Mon Sep 17 00:00:00 2001 From: MeexReay Date: Sun, 17 Nov 2024 00:26:52 +0300 Subject: [PATCH] event system --- Cargo.lock | 9 ++++ Cargo.toml | 8 +++- docs/player_forwarding.md | 2 +- make_event/Cargo.toml | 11 +++++ make_event/src/lib.rs | 70 +++++++++++++++++++++++++++++++ src/lib.rs | 2 +- src/meexprox/event.rs | 88 ++++++++++++++++++--------------------- src/meexprox/meexprox.rs | 18 ++++---- 8 files changed, 148 insertions(+), 60 deletions(-) create mode 100644 make_event/Cargo.toml create mode 100644 make_event/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 7825a02..cbd73c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -157,6 +157,14 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "make_event" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "meexprox" version = "0.1.0" @@ -164,6 +172,7 @@ dependencies = [ "bytebuffer", "ignore-result", "log", + "make_event", "random-string", "ring", "rust_mc_proto", diff --git a/Cargo.toml b/Cargo.toml index ea9d50d..72d74a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,10 @@ simplelog = "0.12.2" ignore-result = "0.2.0" random-string = "1.1.0" ring = "0.17.8" -bytebuffer = "2.3.0" \ No newline at end of file +bytebuffer = "2.3.0" +make_event = { path = "make_event" } + +[workspace] +members = [ + "make_event" +] \ No newline at end of file diff --git a/docs/player_forwarding.md b/docs/player_forwarding.md index 4e85b19..ceb3c91 100644 --- a/docs/player_forwarding.md +++ b/docs/player_forwarding.md @@ -13,7 +13,7 @@ forwarding: ### Player forwarding types -- `meexprox` - meexprox player forwarding ([about it](meexprox_forwarding.md)) +- `meexprox` - meexprox player forwarding ([about it](meexprox_forwarding.md)) ([plugin](https://github.com/MeexReay/meexprox_plugin)) - `velocity` - velocity 'modern' player forwarding, secret key is required - `bungeecord` (with secret) - bungeecord player forwarding - `bungeecord` (without secret) - bungeeguard player forwarding diff --git a/make_event/Cargo.toml b/make_event/Cargo.toml new file mode 100644 index 0000000..46696ca --- /dev/null +++ b/make_event/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "make_event" +version = "0.1.0" +edition = "2021" + +[dependencies] +quote = "1.0.37" +syn = "2.0.87" + +[lib] +proc-macro = true \ No newline at end of file diff --git a/make_event/src/lib.rs b/make_event/src/lib.rs new file mode 100644 index 0000000..187dcb1 --- /dev/null +++ b/make_event/src/lib.rs @@ -0,0 +1,70 @@ + +use proc_macro::TokenStream; +use quote::{quote, format_ident}; +use syn::{parse_macro_input, DeriveInput, Data, Fields}; + +#[proc_macro_derive(MakeEvent, attributes(MakeEvent, setter))] +pub fn make_event_derive(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let struct_name = &input.ident; + let event_name = input.attrs.iter() + .find_map(|attr| { + if attr.path().is_ident("MakeEvent") { + attr.parse_args::().ok() + } else { + None + } + }) + .expect("Expected MakeEvent attribute with a name argument") + .value(); + + let mut getters = Vec::new(); + let mut setters = Vec::new(); + + if let Data::Struct(data) = input.data { + if let Fields::Named(fields) = data.fields { + for field in fields.named.iter() { + let field_name = &field.ident; + let field_ty = &field.ty; + getters.push(quote! { + pub fn #field_name(&self) -> &#field_ty { + &self.#field_name + } + }); + if field.attrs.iter().any(|attr| attr.path().is_ident("setter")) { + let setter_name = format_ident!("set_{}", field_name.as_ref().unwrap()); + setters.push(quote! { + pub fn #setter_name(&mut self, value: #field_ty) { + self.#field_name = value; + } + }); + } + } + } + } else { + panic!("MakeEvent can only be derived for structs with named fields"); + } + + let expanded = quote! { + impl #struct_name { + #(#getters)* + #(#setters)* + } + + impl Event for #struct_name { + fn cancel(&mut self) { + self.cancelled = true; + } + + fn is_cancelled(&self) -> bool { + self.cancelled + } + + fn name(&self) -> String { + #event_name.to_string() + } + } + }; + + TokenStream::from(expanded) +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index ed9eaa5..045c86b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,3 @@ pub mod meexprox; -pub use meexprox::*; +pub use meexprox::*; \ No newline at end of file diff --git a/src/meexprox/event.rs b/src/meexprox/event.rs index 366cdfb..eb5b3fa 100644 --- a/src/meexprox/event.rs +++ b/src/meexprox/event.rs @@ -1,59 +1,51 @@ -use std::net::SocketAddr; +use std::{any::Any, net::SocketAddr}; -use rust_mc_proto::Packet; +use make_event::MakeEvent; -use super::{config::ServerInfo, connection::Player, error::ProxyError}; +use super::error::ProxyError; -pub trait EventListener { - fn on_server_recv_packet( - &self, - packet: &mut Packet, - player: &Player, - ) -> Result<(), ProxyError>; +pub trait Event { + fn name(&self) -> String; + fn is_cancelled(&self) -> bool; + fn cancel(&mut self); +} - fn on_server_send_packet( - &self, - packet: &mut Packet, - cancel: &mut bool, - player: &Player, - ) -> Result<(), ProxyError>; +pub trait AsAny { + fn as_any_ref(&self) -> &dyn Any; + fn as_any_mut(&mut self) -> &mut dyn Any; + fn as_any_box(self: Box) -> Box; +} - fn on_client_send_packet( - &self, - packet: &mut Packet, - cancel: &mut bool, - player: &Player, - ) -> Result<(), ProxyError>; +impl AsAny for T +where + T: Any, +{ + fn as_any_ref(&self) -> &dyn Any { + self + } - fn on_client_recv_packet( - &self, - packet: &mut Packet, - player: &Player, - ) -> Result<(), ProxyError>; + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } - fn on_player_connected( - &self, - player: &Player, - ) -> Result<(), ProxyError>; + fn as_any_box(self: Box) -> Box { + self + } +} - fn on_player_disconnected( - &self, - player: &Player, - ) -> Result<(), ProxyError>; +pub trait EventListener: AsAny { + fn on_event(&self, event: &mut T) -> Result<(), ProxyError>; +} - fn on_player_connecting_server( - &self, - player: &Player, - cancel: &mut bool, - server: &mut ServerInfo - ) -> Result<(), ProxyError>; - fn on_status_request( - &self, - status: String, - client_address: SocketAddr, - server_address: String, - server_port: u16, - cancel: &mut bool, - ) -> Result<(), ProxyError>; +#[derive(MakeEvent)] +#[MakeEvent("status")] +pub struct StatusEvent { + cancelled: bool, + addr: SocketAddr, + #[setter] + motd: String, + server_address: String, + server_port: u16, + protocol_version: u16 } \ No newline at end of file diff --git a/src/meexprox/meexprox.rs b/src/meexprox/meexprox.rs index f4b4270..8bdc428 100644 --- a/src/meexprox/meexprox.rs +++ b/src/meexprox/meexprox.rs @@ -9,13 +9,13 @@ use std::{ }, thread, }; -use super::{config::ProxyConfig, connection::Player, error::{AsProxyResult, ProxyError}, event::EventListener}; +use super::{config::ProxyConfig, connection::Player, error::{AsProxyResult, ProxyError}, event::{Event, EventListener}}; pub struct MeexProx { config: ProxyConfig, players: RwLock>, - event_listeners: Vec> + event_listeners: Vec + Send + Sync>> } impl MeexProx { @@ -29,17 +29,17 @@ impl MeexProx { pub fn add_event_listener( &mut self, - event_listener: Box, + event_listener: Box + Send + Sync>, ) { self.event_listeners.push(event_listener); } - pub fn trigger_event( - &self, - trigger: fn(&dyn EventListener) -> Result<(), ProxyError> - ) -> Result<(), ProxyError> { - for event_listener in &self.event_listeners { - trigger(event_listener.as_ref())? + pub fn trigger_event(&self, event: &mut T) -> Result<(), ProxyError> { + for listener in &self.event_listeners { + if let Some(listener) = + listener.as_any_ref().downcast_ref:: + Send + Sync + 'static>>() { + listener.on_event(event)?; + } } Ok(()) }