diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2022-11-12 23:54:05 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-12 23:54:05 -0600 |
| commit | 6eee543a3367d38a6f0e9bffb457a2bd76a8f9cc (patch) | |
| tree | a5e493ccd7ec24293b8d866242c3836146517122 /azalea-client/src/plugins.rs | |
| parent | fa57d03627aa20b1df44caed7cb025b6db1d9b53 (diff) | |
| download | azalea-drasl-6eee543a3367d38a6f0e9bffb457a2bd76a8f9cc.tar.xz | |
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
Diffstat (limited to 'azalea-client/src/plugins.rs')
| -rw-r--r-- | azalea-client/src/plugins.rs | 78 |
1 files changed, 78 insertions, 0 deletions
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<HashMap<TypeId, Box<dyn Plugin>, BuildHasherDefault<NoHashHasher<u64>>>>, +} + +impl Plugins { + pub fn new() -> Self { + Self { map: None } + } + + pub fn add<T: Plugin>(&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::<T>(), Box::new(plugin)); + } + + pub fn get<T: Plugin>(&self) -> Option<&T> { + self.map + .as_ref() + .and_then(|map| map.get(&TypeId::of::<T>())) + .and_then(|boxed| (boxed.as_ref() as &dyn Any).downcast_ref::<T>()) + } +} + +impl IntoIterator for Plugins { + type Item = Box<dyn Plugin>; + type IntoIter = std::vec::IntoIter<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + self.map + .map(|map| map.into_iter().map(|(_, v)| v).collect::<Vec<_>>()) + .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<Self>, event: Event, bot: Client); +} + +/// 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() + } +} |
