aboutsummaryrefslogtreecommitdiff
path: root/azalea/src/lib.rs
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2022-10-23 16:51:49 -0500
committermat <github@matdoes.dev>2022-10-23 16:51:49 -0500
commit2eade86cf7a12a6ec64496aedbfc3d3a3bd44e1a (patch)
treec010d3f02beaec29741b723a1bc6e7eaad59e193 /azalea/src/lib.rs
parenta9ff79a10553026b0fa32f0e31f1e0442467ca78 (diff)
downloadazalea-drasl-2eade86cf7a12a6ec64496aedbfc3d3a3bd44e1a.tar.xz
make `handle` cleaner
Arc<Event> -> Event, Arc<Mutex<State>> -> State Items in State now need to have interior mutability (i.e. Arc<Mutex<T>>), but it's a worthwhile tradeoff since it allows the user to customize it for each field
Diffstat (limited to 'azalea/src/lib.rs')
-rw-r--r--azalea/src/lib.rs58
1 files changed, 43 insertions, 15 deletions
diff --git a/azalea/src/lib.rs b/azalea/src/lib.rs
index 19384761..6a000e6d 100644
--- a/azalea/src/lib.rs
+++ b/azalea/src/lib.rs
@@ -30,6 +30,7 @@
//! .unwrap();
//! }
//!
+//! #[derive(Default, Clone)]
//! pub struct State {}
//!
//! async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> anyhow::Result<()> {
@@ -52,17 +53,35 @@ pub mod prelude;
use async_trait::async_trait;
pub use azalea_client::*;
use azalea_protocol::ServerAddress;
-use parking_lot::Mutex;
-use std::{future::Future, sync::Arc};
+use std::future::Future;
use thiserror::Error;
/// Plugins can keep their own personal state, listen to events, and add new functions to Client.
#[async_trait]
-pub trait Plugin: Send + Sync {
- async fn handle(self: Arc<Self>, event: Arc<Event>, bot: Client);
+pub trait Plugin: Send + Sync + PluginClone + 'static {
+ async fn handle(self: Box<Self>, event: Event, bot: Client);
}
-pub type HandleFn<Fut, S> = fn(Client, Arc<Event>, Arc<Mutex<S>>) -> Fut;
+/// An internal trait that allows Plugin to be cloned.
+#[doc(hidden)]
+pub trait PluginClone {
+ fn clone_box(&self) -> Box<dyn Plugin>;
+}
+impl<T> PluginClone for T
+where
+ T: 'static + Plugin + Clone,
+{
+ fn clone_box(&self) -> Box<dyn Plugin> {
+ Box::new(self.clone())
+ }
+}
+impl Clone for Box<dyn Plugin> {
+ fn clone(&self) -> Self {
+ self.clone_box()
+ }
+}
+
+pub type HandleFn<Fut, S> = fn(Client, Event, S) -> Fut;
/// The options that are passed to [`azalea::start`].
///
@@ -80,10 +99,22 @@ where
pub account: Account,
/// A list of plugins that are going to be used. Plugins are external
/// crates that add extra functionality to Azalea.
- pub plugins: Vec<Arc<dyn Plugin>>,
+ pub plugins: Vec<Box<dyn Plugin>>,
/// A struct that contains the data that you want your bot to remember
/// across events.
- pub state: Arc<Mutex<S>>,
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use parking_lot::Mutex;
+ /// use std::sync::Arc;
+ ///
+ /// #[derive(Default, Clone)]
+ /// struct State {
+ /// farming: Arc<Mutex<bool>>,
+ /// }
+ /// ```
+ pub state: S,
/// The function that's called whenever we get an event.
pub handle: HandleFn<Fut, S>,
}
@@ -107,7 +138,7 @@ pub enum Error {
/// }).await.unwrap();
/// ```
pub async fn start<
- S: Send + 'static,
+ S: Send + Sync + Clone + 'static,
A: Send + TryInto<ServerAddress>,
Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static,
>(
@@ -121,19 +152,16 @@ pub async fn start<
let (bot, mut rx) = Client::join(&options.account, address).await.unwrap();
let state = options.state;
- let bot_plugin = Arc::new(bot::Plugin::default());
+ let bot_plugin = bot::Plugin::default();
while let Some(event) = rx.recv().await {
- // we put it into an Arc so it's cheaper to clone
-
- let event = Arc::new(event);
-
for plugin in &options.plugins {
- tokio::spawn(plugin.clone().handle(event.clone(), bot.clone()));
+ let plugin = plugin.clone();
+ tokio::spawn(plugin.handle(event.clone(), bot.clone()));
}
tokio::spawn(bot::Plugin::handle(
- bot_plugin.clone(),
+ Box::new(bot_plugin.clone()),
event.clone(),
bot.clone(),
));