From ba4cfaafaec97a3c5b9405fe542035ebe9039edd Mon Sep 17 00:00:00 2001 From: mat <27899617+mat-1@users.noreply.github.com> Date: Fri, 7 Oct 2022 19:57:42 -0500 Subject: Bot API (#27) Basically make the `azalea` crate have stuff --- azalea/src/lib.rs | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) (limited to 'azalea/src/lib.rs') diff --git a/azalea/src/lib.rs b/azalea/src/lib.rs index fe8a3740..8ef02e7c 100644 --- a/azalea/src/lib.rs +++ b/azalea/src/lib.rs @@ -1,4 +1,84 @@ mod bot; pub mod prelude; -pub use azalea_client::Client; +use async_trait::async_trait; +pub use azalea_client::*; +use azalea_protocol::ServerAddress; +use parking_lot::Mutex; +use std::{future::Future, sync::Arc}; +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, bot: Client, event: Arc); +} + +// pub type HeuristicFn = fn(start: &Vertex, current: &Vertex) -> W; +pub type HandleFn = fn(Client, Arc, Arc>) -> Fut; + +pub struct Options +where + A: TryInto, + Fut: Future>, +{ + pub address: A, + pub account: Account, + pub plugins: Vec>, + pub state: Arc>, + pub handle: HandleFn, +} + +#[derive(Error, Debug)] +pub enum Error { + #[error("Invalid address")] + InvalidAddress, +} + +/// Join a Minecraft server. +/// +/// ```no_run +/// azalea::start(azalea::Options { +/// account, +/// address: "localhost", +/// state: Arc::new(Mutex::new(State::default())), +/// plugins: vec![&autoeat::Plugin::default()], +/// handle: Box::new(handle), +/// }).await.unwrap(); +/// ``` +pub async fn start< + S: Send + 'static, + A: Send + TryInto, + Fut: Future> + Send + 'static, +>( + options: Options, +) -> Result<(), Error> { + let address = match options.address.try_into() { + Ok(address) => address, + Err(_) => return Err(Error::InvalidAddress), + }; + + let (bot, mut rx) = options.account.join(&address).await.unwrap(); + + let state = options.state; + let bot_plugin = Arc::new(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(bot.clone(), event.clone())); + } + + { + let bot_plugin = bot_plugin.clone(); + let bot = bot.clone(); + let event = event.clone(); + tokio::spawn(bot::Plugin::handle(bot_plugin, bot, event)); + }; + tokio::spawn((options.handle)(bot.clone(), event.clone(), state.clone())); + } + + Ok(()) +} -- cgit v1.2.3