From 6eee543a3367d38a6f0e9bffb457a2bd76a8f9cc Mon Sep 17 00:00:00 2001 From: mat <27899617+mat-1@users.noreply.github.com> Date: Sat, 12 Nov 2022 23:54:05 -0600 Subject: Pathfinder (#25) Pathfinding is very much not done, but it works enough and I want to get this merged. TODO: fast replanning, goals that aren't a single node, falling moves (it should be able to play the dropper), parkour moves --- azalea-client/src/plugins.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 azalea-client/src/plugins.rs (limited to 'azalea-client/src/plugins.rs') diff --git a/azalea-client/src/plugins.rs b/azalea-client/src/plugins.rs new file mode 100644 index 00000000..1a3aa049 --- /dev/null +++ b/azalea-client/src/plugins.rs @@ -0,0 +1,78 @@ +use crate::{Client, Event}; +use async_trait::async_trait; +use nohash_hasher::NoHashHasher; +use std::{ + any::{Any, TypeId}, + collections::HashMap, + hash::BuildHasherDefault, +}; + +// kind of based on https://docs.rs/http/latest/src/http/extensions.rs.html +/// A map of plugin ids to Plugin trait objects. The client stores this so we +/// can keep the state for our plugins. +/// +/// If you're using azalea, you should generate this from the `plugins!` macro. +#[derive(Clone)] +pub struct Plugins { + map: Option, BuildHasherDefault>>>, +} + +impl Plugins { + pub fn new() -> Self { + Self { map: None } + } + + pub fn add(&mut self, plugin: T) { + if self.map.is_none() { + self.map = Some(HashMap::with_hasher(BuildHasherDefault::default())); + } + self.map + .as_mut() + .unwrap() + .insert(TypeId::of::(), Box::new(plugin)); + } + + pub fn get(&self) -> Option<&T> { + self.map + .as_ref() + .and_then(|map| map.get(&TypeId::of::())) + .and_then(|boxed| (boxed.as_ref() as &dyn Any).downcast_ref::()) + } +} + +impl IntoIterator for Plugins { + type Item = Box; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.map + .map(|map| map.into_iter().map(|(_, v)| v).collect::>()) + .unwrap_or_default() + .into_iter() + } +} + +/// Plugins can keep their own personal state, listen to events, and add new functions to Client. +#[async_trait] +pub trait Plugin: Send + Sync + PluginClone + Any + 'static { + async fn handle(self: Box, event: Event, bot: Client); +} + +/// An internal trait that allows Plugin to be cloned. +#[doc(hidden)] +pub trait PluginClone { + fn clone_box(&self) -> Box; +} +impl PluginClone for T +where + T: 'static + Plugin + Clone, +{ + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } +} +impl Clone for Box { + fn clone(&self) -> Self { + self.clone_box() + } +} -- cgit v1.2.3