aboutsummaryrefslogtreecommitdiff
path: root/azalea/src/lib.rs
diff options
context:
space:
mode:
authorTheDudeFromCI <thedudefromci@gmail.com>2023-08-15 22:12:37 -0700
committerGitHub <noreply@github.com>2023-08-16 00:12:37 -0500
commitf0ff8e7f295270795000f6a8fcd8c2230a3733f5 (patch)
treec71d8f4873731b1f18b5654adc8a35e5e0c01e10 /azalea/src/lib.rs
parent8a90a8e109b88c1c70b88f7488a0a8eb5f52d724 (diff)
downloadazalea-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.rs65
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;