From 49c697b431b4cb409b87bdeb7a5720c61c5d90f2 Mon Sep 17 00:00:00 2001 From: suprohub <125716028+suprohub@users.noreply.github.com> Date: Tue, 28 Jan 2025 23:30:34 +0400 Subject: [PATCH] Plugin api events rewrite (#510) * simplify all * fmt --- pumpkin-macros/src/lib.rs | 64 +++++++++++++ pumpkin/src/plugin/api/events/block.rs | 81 +++++++++++++++++ pumpkin/src/plugin/api/events/block/break.rs | 89 ------------------- pumpkin/src/plugin/api/events/block/burn.rs | 51 ----------- .../src/plugin/api/events/block/can_build.rs | 69 -------------- pumpkin/src/plugin/api/events/block/mod.rs | 46 ---------- pumpkin/src/plugin/api/events/block/place.rs | 73 --------------- pumpkin/src/plugin/api/events/mod.rs | 8 +- pumpkin/src/plugin/api/events/player.rs | 56 ++++++++++++ pumpkin/src/plugin/api/events/player/join.rs | 70 --------------- pumpkin/src/plugin/api/events/player/leave.rs | 70 --------------- pumpkin/src/plugin/api/events/player/mod.rs | 23 ----- pumpkin/src/world/mod.rs | 34 ++++--- 13 files changed, 220 insertions(+), 514 deletions(-) create mode 100644 pumpkin/src/plugin/api/events/block.rs delete mode 100644 pumpkin/src/plugin/api/events/block/break.rs delete mode 100644 pumpkin/src/plugin/api/events/block/burn.rs delete mode 100644 pumpkin/src/plugin/api/events/block/can_build.rs delete mode 100644 pumpkin/src/plugin/api/events/block/mod.rs delete mode 100644 pumpkin/src/plugin/api/events/block/place.rs create mode 100644 pumpkin/src/plugin/api/events/player.rs delete mode 100644 pumpkin/src/plugin/api/events/player/join.rs delete mode 100644 pumpkin/src/plugin/api/events/player/leave.rs delete mode 100644 pumpkin/src/plugin/api/events/player/mod.rs diff --git a/pumpkin-macros/src/lib.rs b/pumpkin-macros/src/lib.rs index 1e20fac91..89c85ac6d 100644 --- a/pumpkin-macros/src/lib.rs +++ b/pumpkin-macros/src/lib.rs @@ -1,8 +1,72 @@ use proc_macro::TokenStream; use quote::quote; +use syn::{ + parse::{Nothing, Parser}, + parse_macro_input, Field, Fields, ItemStruct, +}; extern crate proc_macro; +#[proc_macro_attribute] +pub fn event(args: TokenStream, item: TokenStream) -> TokenStream { + let input = parse_macro_input!(item as ItemStruct); + let name = &input.ident; + let _ = parse_macro_input!(args as Nothing); + + quote! { + #input + + impl crate::plugin::Event for #name { + fn get_name_static() -> &'static str { + stringify!(#name) + } + + fn get_name(&self) -> &'static str { + stringify!(#name) + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + } + } + .into() +} + +#[proc_macro_attribute] +pub fn cancellable(args: TokenStream, input: TokenStream) -> TokenStream { + let mut item_struct = parse_macro_input!(input as ItemStruct); + let name = item_struct.ident.clone(); + let _ = parse_macro_input!(args as Nothing); + + if let Fields::Named(ref mut fields) = item_struct.fields { + fields.named.push( + Field::parse_named + .parse2(quote! { pub cancelled: bool }) + .unwrap(), + ); + } + + quote! { + #item_struct + + impl crate::plugin::Cancellable for #name { + fn cancelled(&self) -> bool { + self.cancelled + } + + fn set_cancelled(&mut self, cancelled: bool) { + self.cancelled = cancelled; + } + } + } + .into() +} + #[proc_macro_attribute] pub fn client_packet(input: TokenStream, item: TokenStream) -> TokenStream { let ast: syn::DeriveInput = syn::parse(item.clone()).unwrap(); diff --git a/pumpkin/src/plugin/api/events/block.rs b/pumpkin/src/plugin/api/events/block.rs new file mode 100644 index 000000000..b98a4d195 --- /dev/null +++ b/pumpkin/src/plugin/api/events/block.rs @@ -0,0 +1,81 @@ +use std::sync::Arc; + +use pumpkin_macros::{cancellable, event}; +use pumpkin_world::block::block_registry::Block; + +use crate::entity::player::Player; + +pub trait BlockEvent: Send + Sync { + fn get_block(&self) -> &Block; +} + +#[event] +#[cancellable] +pub struct BlockBreakEvent { + pub player: Option>, + pub block: Block, + pub exp: u32, + pub drop: bool, +} + +impl BlockBreakEvent { + #[must_use] + pub fn new(player: Option>, block: Block, exp: u32, drop: bool) -> Self { + Self { + player, + block, + exp, + drop, + cancelled: false, + } + } +} + +impl BlockEvent for BlockBreakEvent { + fn get_block(&self) -> &Block { + &self.block + } +} + +#[event] +#[cancellable] +pub struct BlockBurnEvent { + pub igniting_block: Block, + pub block: Block, +} + +impl BlockEvent for BlockBurnEvent { + fn get_block(&self) -> &Block { + &self.block + } +} + +#[event] +#[cancellable] +pub struct BlockCanBuildEvent { + pub block_to_build: Block, + pub buildable: bool, + pub player: Arc, + pub block: Block, +} + +impl BlockEvent for BlockCanBuildEvent { + fn get_block(&self) -> &Block { + &self.block + } +} + +#[event] +#[cancellable] +pub struct BlockPlaceEvent { + pub player: Arc, + pub block_placed: Block, + pub block_placed_against: Block, + pub can_build: bool, +} + +impl BlockEvent for BlockPlaceEvent { + fn get_block(&self) -> &Block { + &self.block_placed + } +} diff --git a/pumpkin/src/plugin/api/events/block/break.rs b/pumpkin/src/plugin/api/events/block/break.rs deleted file mode 100644 index 4069e316b..000000000 --- a/pumpkin/src/plugin/api/events/block/break.rs +++ /dev/null @@ -1,89 +0,0 @@ -use std::sync::Arc; - -use pumpkin_world::block::block_registry::Block; - -use crate::{ - entity::player::Player, - plugin::{CancellableEvent, Event}, -}; - -use super::{BlockBreakEvent, BlockEvent, BlockExpEvent}; - -pub struct BlockBreakEventImpl { - player: Option>, - block: Block, - exp: u32, - drop: bool, - is_cancelled: bool, -} - -impl BlockBreakEventImpl { - #[must_use] - pub fn new(player: Option>, block: Block, exp: u32, drop: bool) -> Self { - Self { - player, - block, - exp, - drop, - is_cancelled: false, - } - } -} - -impl BlockBreakEvent for BlockBreakEventImpl { - fn get_player(&self) -> Option> { - self.player.clone() - } - - fn will_drop(&self) -> bool { - self.drop - } - - fn set_drop(&mut self, drop: bool) { - self.drop = drop; - } -} - -impl BlockExpEvent for BlockBreakEventImpl { - fn get_exp_to_drop(&self) -> u32 { - self.exp - } - - fn set_exp_to_drop(&mut self, exp: u32) { - self.exp = exp; - } -} - -impl BlockEvent for BlockBreakEventImpl { - fn get_block(&self) -> &Block { - &self.block - } -} - -impl CancellableEvent for BlockBreakEventImpl { - fn is_cancelled(&self) -> bool { - self.is_cancelled - } - - fn set_cancelled(&mut self, cancelled: bool) { - self.is_cancelled = cancelled; - } -} - -impl Event for BlockBreakEventImpl { - fn get_name_static() -> &'static str { - "BlockBreakEvent" - } - - fn get_name(&self) -> &'static str { - "BlockBreakEvent" - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } -} diff --git a/pumpkin/src/plugin/api/events/block/burn.rs b/pumpkin/src/plugin/api/events/block/burn.rs deleted file mode 100644 index 96d7f4724..000000000 --- a/pumpkin/src/plugin/api/events/block/burn.rs +++ /dev/null @@ -1,51 +0,0 @@ -use pumpkin_world::block::block_registry::Block; - -use crate::plugin::{CancellableEvent, Event}; - -use super::{BlockBurnEvent, BlockEvent}; - -pub struct BlockBurnEventImpl { - igniting_block: Block, - block: Block, - is_cancelled: bool, -} - -impl BlockBurnEvent for BlockBurnEventImpl { - fn get_igniting_block(&self) -> &Block { - &self.igniting_block - } -} - -impl BlockEvent for BlockBurnEventImpl { - fn get_block(&self) -> &Block { - &self.block - } -} - -impl CancellableEvent for BlockBurnEventImpl { - fn is_cancelled(&self) -> bool { - self.is_cancelled - } - - fn set_cancelled(&mut self, cancelled: bool) { - self.is_cancelled = cancelled; - } -} - -impl Event for BlockBurnEventImpl { - fn get_name_static() -> &'static str { - "BlockBurnEvent" - } - - fn get_name(&self) -> &'static str { - "BlockBurnEvent" - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } -} diff --git a/pumpkin/src/plugin/api/events/block/can_build.rs b/pumpkin/src/plugin/api/events/block/can_build.rs deleted file mode 100644 index da9fee947..000000000 --- a/pumpkin/src/plugin/api/events/block/can_build.rs +++ /dev/null @@ -1,69 +0,0 @@ -use pumpkin_world::block::block_registry::Block; -use std::sync::Arc; - -use crate::{ - entity::player::Player, - plugin::{CancellableEvent, Event}, -}; - -use super::{BlockCanBuildEvent, BlockEvent}; - -pub struct BlockCanBuildEventImpl { - block_to_build: Block, - buildable: bool, - player: Arc, - block: Block, - is_cancelled: bool, -} - -impl BlockCanBuildEvent for BlockCanBuildEventImpl { - fn get_block_to_build(&self) -> &Block { - &self.block_to_build - } - - fn is_buildable(&self) -> bool { - self.buildable - } - - fn set_buildable(&mut self, buildable: bool) { - self.buildable = buildable; - } - - fn get_player(&self) -> Option> { - Some(self.player.clone()) - } -} - -impl BlockEvent for BlockCanBuildEventImpl { - fn get_block(&self) -> &Block { - &self.block - } -} - -impl CancellableEvent for BlockCanBuildEventImpl { - fn is_cancelled(&self) -> bool { - self.is_cancelled - } - - fn set_cancelled(&mut self, cancelled: bool) { - self.is_cancelled = cancelled; - } -} - -impl Event for BlockCanBuildEventImpl { - fn get_name_static() -> &'static str { - "BlockCanBuildEvent" - } - - fn get_name(&self) -> &'static str { - "BlockCanBuildEvent" - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } -} diff --git a/pumpkin/src/plugin/api/events/block/mod.rs b/pumpkin/src/plugin/api/events/block/mod.rs deleted file mode 100644 index 6ee2ed852..000000000 --- a/pumpkin/src/plugin/api/events/block/mod.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::sync::Arc; - -use pumpkin_world::block::block_registry::Block; - -use crate::entity::player::Player; - -use super::CancellableEvent; - -pub mod r#break; -pub mod burn; -pub mod can_build; -pub mod place; - -pub trait BlockEvent: CancellableEvent { - fn get_block(&self) -> &Block; -} - -pub trait BlockExpEvent: BlockEvent { - fn get_exp_to_drop(&self) -> u32; - fn set_exp_to_drop(&mut self, exp: u32); -} - -pub trait BlockBreakEvent: BlockExpEvent { - fn get_player(&self) -> Option>; - fn will_drop(&self) -> bool; - fn set_drop(&mut self, drop: bool); -} - -pub trait BlockBurnEvent: BlockEvent { - fn get_igniting_block(&self) -> &Block; -} - -pub trait BlockCanBuildEvent: BlockEvent { - fn get_block_to_build(&self) -> &Block; - fn is_buildable(&self) -> bool; - fn set_buildable(&mut self, buildable: bool); - fn get_player(&self) -> Option>; -} - -pub trait BlockPlaceEvent: BlockEvent { - fn get_player(&self) -> Option>; - fn can_build(&self) -> bool; - fn set_build(&mut self, build: bool); - fn get_block_placed_against(&self) -> &Block; - fn get_block_placed(&self) -> &Block; -} diff --git a/pumpkin/src/plugin/api/events/block/place.rs b/pumpkin/src/plugin/api/events/block/place.rs deleted file mode 100644 index b8566ebe8..000000000 --- a/pumpkin/src/plugin/api/events/block/place.rs +++ /dev/null @@ -1,73 +0,0 @@ -use pumpkin_world::block::block_registry::Block; -use std::sync::Arc; - -use crate::{ - entity::player::Player, - plugin::{CancellableEvent, Event}, -}; - -use super::{BlockEvent, BlockPlaceEvent}; - -pub struct BlockPlaceEventImpl { - player: Arc, - block_placed: Block, - block_placed_against: Block, - can_build: bool, - is_cancelled: bool, -} - -impl BlockPlaceEvent for BlockPlaceEventImpl { - fn get_player(&self) -> Option> { - Some(self.player.clone()) - } - - fn can_build(&self) -> bool { - self.can_build - } - - fn set_build(&mut self, build: bool) { - self.can_build = build; - } - - fn get_block_placed_against(&self) -> &Block { - &self.block_placed_against - } - - fn get_block_placed(&self) -> &Block { - &self.block_placed - } -} - -impl BlockEvent for BlockPlaceEventImpl { - fn get_block(&self) -> &Block { - &self.block_placed - } -} - -impl CancellableEvent for BlockPlaceEventImpl { - fn is_cancelled(&self) -> bool { - self.is_cancelled - } - - fn set_cancelled(&mut self, cancelled: bool) { - self.is_cancelled = cancelled; - } -} - -impl Event for BlockPlaceEventImpl { - fn get_name_static() -> &'static str { - "BlockPlaceEvent" - } - - fn get_name(&self) -> &'static str { - "BlockPlaceEvent" - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } -} diff --git a/pumpkin/src/plugin/api/events/mod.rs b/pumpkin/src/plugin/api/events/mod.rs index 0958d1482..d0ab0b921 100644 --- a/pumpkin/src/plugin/api/events/mod.rs +++ b/pumpkin/src/plugin/api/events/mod.rs @@ -3,7 +3,7 @@ use std::any::Any; pub mod block; pub mod player; -pub trait Event: Any + Send + Sync { +pub trait Event: Send + Sync { fn get_name_static() -> &'static str where Self: Sized; @@ -12,13 +12,13 @@ pub trait Event: Any + Send + Sync { fn as_any(&self) -> &dyn Any; } -pub trait CancellableEvent: Event { - fn is_cancelled(&self) -> bool; +pub trait Cancellable: Send + Sync { + fn cancelled(&self) -> bool; fn set_cancelled(&mut self, cancelled: bool); } -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)] // Lowest priority events are executed first, so that higher priority events can override their changes +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)] pub enum EventPriority { Highest, High, diff --git a/pumpkin/src/plugin/api/events/player.rs b/pumpkin/src/plugin/api/events/player.rs new file mode 100644 index 000000000..9e24ea3f6 --- /dev/null +++ b/pumpkin/src/plugin/api/events/player.rs @@ -0,0 +1,56 @@ +use std::sync::Arc; + +use pumpkin_macros::{cancellable, event}; +use pumpkin_util::text::TextComponent; + +use crate::entity::player::Player; + +pub trait PlayerEvent: Send + Sync { + fn get_player(&self) -> &Arc; +} + +#[event] +#[cancellable] +pub struct PlayerJoinEvent { + pub player: Arc, + pub join_message: TextComponent, +} + +impl PlayerJoinEvent { + pub fn new(player: Arc, join_message: TextComponent) -> Self { + Self { + player, + join_message, + cancelled: false, + } + } +} + +impl PlayerEvent for PlayerJoinEvent { + fn get_player(&self) -> &Arc { + &self.player + } +} + +#[event] +#[cancellable] +pub struct PlayerLeaveEvent { + pub player: Arc, + pub leave_message: TextComponent, +} + +impl PlayerLeaveEvent { + pub fn new(player: Arc, leave_message: TextComponent) -> Self { + Self { + player, + leave_message, + cancelled: false, + } + } +} + +impl PlayerEvent for PlayerLeaveEvent { + fn get_player(&self) -> &Arc { + &self.player + } +} diff --git a/pumpkin/src/plugin/api/events/player/join.rs b/pumpkin/src/plugin/api/events/player/join.rs deleted file mode 100644 index ff9de9424..000000000 --- a/pumpkin/src/plugin/api/events/player/join.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::sync::Arc; - -use pumpkin_util::text::TextComponent; - -use crate::{ - entity::player::Player, - plugin::{CancellableEvent, Event}, -}; - -use super::{PlayerEvent, PlayerJoinEvent}; - -pub struct PlayerJoinEventImpl { - player: Arc, - join_message: TextComponent, - is_cancelled: bool, -} - -impl PlayerJoinEventImpl { - pub fn new(player: Arc, join_message: TextComponent) -> Self { - Self { - player, - join_message, - is_cancelled: false, - } - } -} - -impl PlayerJoinEvent for PlayerJoinEventImpl { - fn get_join_message(&self) -> &TextComponent { - &self.join_message - } - - fn set_join_message(&mut self, message: TextComponent) { - self.join_message = message; - } -} - -impl PlayerEvent for PlayerJoinEventImpl { - fn get_player(&self) -> Arc { - self.player.clone() - } -} - -impl CancellableEvent for PlayerJoinEventImpl { - fn is_cancelled(&self) -> bool { - self.is_cancelled - } - - fn set_cancelled(&mut self, cancelled: bool) { - self.is_cancelled = cancelled; - } -} - -impl Event for PlayerJoinEventImpl { - fn get_name_static() -> &'static str { - "PlayerJoinEvent" - } - - fn get_name(&self) -> &'static str { - "PlayerJoinEvent" - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } -} diff --git a/pumpkin/src/plugin/api/events/player/leave.rs b/pumpkin/src/plugin/api/events/player/leave.rs deleted file mode 100644 index 90a687e7f..000000000 --- a/pumpkin/src/plugin/api/events/player/leave.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::sync::Arc; - -use pumpkin_util::text::TextComponent; - -use crate::{ - entity::player::Player, - plugin::{CancellableEvent, Event}, -}; - -use super::{PlayerEvent, PlayerLeaveEvent}; - -pub struct PlayerLeaveEventImpl { - player: Arc, - leave_message: TextComponent, - is_cancelled: bool, -} - -impl PlayerLeaveEventImpl { - pub fn new(player: Arc, leave_message: TextComponent) -> Self { - Self { - player, - leave_message, - is_cancelled: false, - } - } -} - -impl PlayerLeaveEvent for PlayerLeaveEventImpl { - fn get_leave_message(&self) -> &TextComponent { - &self.leave_message - } - - fn set_leave_message(&mut self, message: TextComponent) { - self.leave_message = message; - } -} - -impl PlayerEvent for PlayerLeaveEventImpl { - fn get_player(&self) -> Arc { - self.player.clone() - } -} - -impl CancellableEvent for PlayerLeaveEventImpl { - fn is_cancelled(&self) -> bool { - self.is_cancelled - } - - fn set_cancelled(&mut self, cancelled: bool) { - self.is_cancelled = cancelled; - } -} - -impl Event for PlayerLeaveEventImpl { - fn get_name_static() -> &'static str { - "PlayerLeaveEvent" - } - - fn get_name(&self) -> &'static str { - "PlayerLeaveEvent" - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } -} diff --git a/pumpkin/src/plugin/api/events/player/mod.rs b/pumpkin/src/plugin/api/events/player/mod.rs deleted file mode 100644 index 0101da718..000000000 --- a/pumpkin/src/plugin/api/events/player/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -use pumpkin_util::text::TextComponent; -use std::sync::Arc; - -use crate::entity::player::Player; - -use super::CancellableEvent; - -pub mod join; -pub mod leave; - -pub trait PlayerEvent: CancellableEvent { - fn get_player(&self) -> Arc; -} - -pub trait PlayerJoinEvent: PlayerEvent { - fn get_join_message(&self) -> &TextComponent; - fn set_join_message(&mut self, message: TextComponent); -} - -pub trait PlayerLeaveEvent: PlayerEvent { - fn get_leave_message(&self) -> &TextComponent; - fn set_leave_message(&mut self, message: TextComponent); -} diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 6db6750e7..46293507c 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -8,12 +8,8 @@ use crate::{ entity::{living::LivingEntity, mob::MobEntity, player::Player, Entity, EntityId}, error::PumpkinError, plugin::{ - block::r#break::BlockBreakEventImpl, - player::{ - join::PlayerJoinEventImpl, leave::PlayerLeaveEventImpl, PlayerJoinEvent, - PlayerLeaveEvent, - }, - CancellableEvent, + block::BlockBreakEvent, + player::{PlayerJoinEvent, PlayerLeaveEvent}, }, server::Server, PLUGIN_MANAGER, @@ -779,21 +775,21 @@ impl World { [TextComponent::text(player.gameprofile.name.clone())].into(), ) .color_named(NamedColor::Yellow); - let event = PlayerJoinEventImpl::new(player.clone(), msg_comp); + let event = PlayerJoinEvent::new(player.clone(), msg_comp); let event = PLUGIN_MANAGER .lock() .await - .fire::(event) + .fire::(event) .await; - if !event.is_cancelled() { + if !event.cancelled { let current_players = current_players.clone(); let players = current_players.lock().await; for player in players.values() { - player.send_system_message(event.get_join_message()).await; + player.send_system_message(&event.join_message).await; } - log::info!("{}", event.get_join_message().clone().to_pretty_console()); + log::info!("{}", event.join_message.clone().to_pretty_console()); } }); } @@ -835,20 +831,20 @@ impl World { [TextComponent::text(player.gameprofile.name.clone())].into(), ) .color_named(NamedColor::Yellow); - let event = PlayerLeaveEventImpl::new(player.clone(), msg_comp); + let event = PlayerLeaveEvent::new(player.clone(), msg_comp); let event = PLUGIN_MANAGER .lock() .await - .fire::(event) + .fire::(event) .await; - if !event.is_cancelled() { + if !event.cancelled { let players = self.current_players.lock().await; for player in players.values() { - player.send_system_message(event.get_leave_message()).await; + player.send_system_message(&event.leave_message).await; } - log::info!("{}", event.get_leave_message().clone().to_pretty_console()); + log::info!("{}", event.leave_message.clone().to_pretty_console()); } } @@ -945,15 +941,15 @@ impl World { pub async fn break_block(&self, position: &BlockPos, cause: Option>) { let block = self.get_block(position).await.unwrap(); - let event = BlockBreakEventImpl::new(cause.clone(), block.clone(), 0, false); + let event = BlockBreakEvent::new(cause.clone(), block.clone(), 0, false); let event = PLUGIN_MANAGER .lock() .await - .fire::(event) + .fire::(event) .await; - if !event.is_cancelled() { + if !event.cancelled { let broken_block_state_id = self.set_block_state(position, 0).await; let particles_packet = CWorldEvent::new(