event system

This commit is contained in:
MeexReay 2024-11-17 00:26:52 +03:00
parent 5a4c1d6d2b
commit 9236636025
8 changed files with 148 additions and 60 deletions

9
Cargo.lock generated
View File

@ -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",

View File

@ -13,3 +13,9 @@ ignore-result = "0.2.0"
random-string = "1.1.0"
ring = "0.17.8"
bytebuffer = "2.3.0"
make_event = { path = "make_event" }
[workspace]
members = [
"make_event"
]

View File

@ -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

11
make_event/Cargo.toml Normal file
View File

@ -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

70
make_event/src/lib.rs Normal file
View File

@ -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::<syn::LitStr>().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)
}

View File

@ -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>;
fn on_server_send_packet(
&self,
packet: &mut Packet,
cancel: &mut bool,
player: &Player,
) -> Result<(), ProxyError>;
fn on_client_send_packet(
&self,
packet: &mut Packet,
cancel: &mut bool,
player: &Player,
) -> Result<(), ProxyError>;
fn on_client_recv_packet(
&self,
packet: &mut Packet,
player: &Player,
) -> Result<(), ProxyError>;
fn on_player_connected(
&self,
player: &Player,
) -> Result<(), ProxyError>;
fn on_player_disconnected(
&self,
player: &Player,
) -> 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>;
pub trait Event {
fn name(&self) -> String;
fn is_cancelled(&self) -> bool;
fn cancel(&mut self);
}
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<Self>) -> Box<dyn Any>;
}
impl<T> AsAny for T
where
T: Any,
{
fn as_any_ref(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn as_any_box(self: Box<Self>) -> Box<dyn Any> {
self
}
}
pub trait EventListener<T: Event>: AsAny {
fn on_event(&self, event: &mut T) -> 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
}

View File

@ -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<Vec<Player>>,
event_listeners: Vec<Box<dyn EventListener + Send + Sync>>
event_listeners: Vec<Box<dyn EventListener<dyn Event> + Send + Sync>>
}
impl MeexProx {
@ -29,17 +29,17 @@ impl MeexProx {
pub fn add_event_listener(
&mut self,
event_listener: Box<dyn EventListener + Send + Sync>,
event_listener: Box<dyn EventListener<dyn Event> + 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<T: Event + 'static>(&self, event: &mut T) -> Result<(), ProxyError> {
for listener in &self.event_listeners {
if let Some(listener) =
listener.as_any_ref().downcast_ref::<Box<dyn EventListener<T> + Send + Sync + 'static>>() {
listener.on_event(event)?;
}
}
Ok(())
}