diff options
| author | TheDudeFromCI <thedudefromci@gmail.com> | 2023-08-15 22:12:37 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-16 00:12:37 -0500 |
| commit | f0ff8e7f295270795000f6a8fcd8c2230a3733f5 (patch) | |
| tree | c71d8f4873731b1f18b5654adc8a35e5e0c01e10 /azalea/src/lib.rs | |
| parent | 8a90a8e109b88c1c70b88f7488a0a8eb5f52d724 (diff) | |
| download | azalea-drasl-f0ff8e7f295270795000f6a8fcd8c2230a3733f5.tar.xz | |
no_handler() option for ClientBuilder (#100)
* Added no_handler client builder option
Signed-off-by: TheDudeFromCI <thedudefromci@gmail.com>
* Made EmptyState public
Signed-off-by: TheDudeFromCI <thedudefromci@gmail.com>
* Packaged no_handler placeholders in own module
Signed-off-by: TheDudeFromCI <thedudefromci@gmail.com>
* imply no state and remove Fut generic from ClientBuilder and SwarmBuilder
* use destructuring in set_handler and fix a doc
---------
Signed-off-by: TheDudeFromCI <thedudefromci@gmail.com>
Co-authored-by: mat <git@matdoes.dev>
Diffstat (limited to 'azalea/src/lib.rs')
| -rw-r--r-- | azalea/src/lib.rs | 65 |
1 files changed, 40 insertions, 25 deletions
diff --git a/azalea/src/lib.rs b/azalea/src/lib.rs index f564cd9b..ce3494e2 100644 --- a/azalea/src/lib.rs +++ b/azalea/src/lib.rs @@ -2,6 +2,7 @@ #![feature(async_closure)] #![allow(incomplete_features)] #![feature(async_fn_in_trait)] +#![feature(type_changing_struct_update)] mod auto_respawn; mod bot; @@ -23,7 +24,7 @@ pub use azalea_registry::{Block, EntityKind, Item}; pub use azalea_world as world; pub use bot::DefaultBotPlugins; use ecs::component::Component; -use futures::Future; +use futures::{future::BoxFuture, Future}; use protocol::{ resolver::{self, ResolverError}, ServerAddress, @@ -34,7 +35,9 @@ use tokio::sync::mpsc; pub use bevy_app as app; pub use bevy_ecs as ecs; -pub type HandleFn<Fut, S> = fn(Client, azalea_client::Event, S) -> Fut; +pub type BoxHandleFn<S> = + Box<dyn Fn(Client, azalea_client::Event, S) -> BoxFuture<'static, Result<(), anyhow::Error>>>; +pub type HandleFn<S, Fut> = fn(Client, azalea_client::Event, S) -> Fut; #[derive(Error, Debug)] pub enum StartError { @@ -64,24 +67,19 @@ pub enum StartError { /// # Ok(()) /// # } /// ``` -pub struct ClientBuilder<S, Fut> +pub struct ClientBuilder<S> where - S: Default + Send + Sync + Clone + 'static, - Fut: Future<Output = Result<(), anyhow::Error>>, + S: Default + Send + Sync + Clone + Component + 'static, { app: App, /// The function that's called every time a bot receives an [`Event`]. - handler: Option<HandleFn<Fut, S>>, + handler: Option<BoxHandleFn<S>>, state: S, } -impl<S, Fut> ClientBuilder<S, Fut> -where - S: Default + Send + Sync + Clone + Component + 'static, - Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static, -{ +impl ClientBuilder<NoState> { /// Start building a client that can join the world. #[must_use] - pub fn new() -> Self { + pub fn new() -> ClientBuilder<NoState> { Self::new_without_plugins() .add_plugins(DefaultPlugins) .add_plugins(DefaultBotPlugins) @@ -111,21 +109,20 @@ where /// # } /// ``` #[must_use] - pub fn new_without_plugins() -> Self { + pub fn new_without_plugins() -> ClientBuilder<NoState> { Self { // we create the app here so plugins can add onto it. // the schedules won't run until [`Self::start`] is called. app: App::new(), handler: None, - state: S::default(), + state: NoState, } } /// Set the function that's called every time a bot receives an [`Event`]. /// This is the way to handle normal per-bot events. /// - /// You must have exactly one client handler, calling this again will - /// replace the old client handler function. + /// Currently you can have up to one client handler. /// /// ``` /// # use azalea::prelude::*; @@ -139,10 +136,24 @@ where /// } /// ``` #[must_use] - pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self { - self.handler = Some(handler); - self + pub fn set_handler<S, Fut>(self, handler: HandleFn<S, Fut>) -> ClientBuilder<S> + where + S: Default + Send + Sync + Clone + Component + 'static, + Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static, + { + ClientBuilder { + handler: Some(Box::new(move |bot, event, state| { + Box::pin(handler(bot, event, state)) + })), + state: S::default(), + ..self + } } +} +impl<S> ClientBuilder<S> +where + S: Default + Send + Sync + Clone + Component + 'static, +{ /// Set the client state instead of initializing defaults. #[must_use] pub fn set_state(mut self, state: S) -> Self { @@ -186,7 +197,7 @@ where .await?; while let Some(event) = rx.recv().await { - if let Some(handler) = self.handler { + if let Some(handler) = &self.handler { tokio::spawn((handler)(bot.clone(), event.clone(), self.state.clone())); } } @@ -194,12 +205,16 @@ where Ok(()) } } -impl<S, Fut> Default for ClientBuilder<S, Fut> -where - S: Default + Send + Sync + Clone + Component + 'static, - Fut: Future<Output = Result<(), anyhow::Error>> + Send + 'static, -{ +impl Default for ClientBuilder<NoState> { fn default() -> Self { Self::new() } } + +/// A marker that can be used in place of a State in [`ClientBuilder`] or +/// [`SwarmBuilder`]. You probably don't need to use this manually since the +/// compiler will infer it for you. +/// +/// [`SwarmBuilder`]: swarm::SwarmBuilder +#[derive(Component, Clone, Default)] +pub struct NoState; |
