aboutsummaryrefslogtreecommitdiff
path: root/azalea-client/src/plugins.rs
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2022-11-12 23:54:05 -0600
committerGitHub <noreply@github.com>2022-11-12 23:54:05 -0600
commit6eee543a3367d38a6f0e9bffb457a2bd76a8f9cc (patch)
treea5e493ccd7ec24293b8d866242c3836146517122 /azalea-client/src/plugins.rs
parentfa57d03627aa20b1df44caed7cb025b6db1d9b53 (diff)
downloadazalea-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.rs78
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()
+ }
+}