aboutsummaryrefslogtreecommitdiff
path: root/azalea-client/src/plugins.rs
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2022-11-27 16:25:07 -0600
committerGitHub <noreply@github.com>2022-11-27 16:25:07 -0600
commit631ed63dbdc7167df4de02a55b5c2ef1cea909e9 (patch)
tree104e567c332f2aeb30ea6acefef8c73f9b2f158b /azalea-client/src/plugins.rs
parent962b9fcaae917c7e5bef718469fba31f6ff7c3cb (diff)
downloadazalea-drasl-631ed63dbdc7167df4de02a55b5c2ef1cea909e9.tar.xz
Swarm (#36)
* make azalea-pathfinder dir * start writing d* lite impl * more work on d* lite * work more on implementing d* lite * full d* lite impl * updated edges * add next() function * add NoPathError * why does dstar lite not work * fix d* lite implementation * make the test actually check the coords * replace while loop with if statement * fix clippy complaints * make W only have to be PartialOrd * fix PartialOrd issues * implement mtd* lite * add a test to mtd* lite * remove normal d* lite * make heuristic only take in one arg * add `success` function * Update README.md * evil black magic to make .entity not need dimension * start adding moves * slightly improve the vec3/position situation new macro that implements all the useful functions * moves stuff * make it compile * update deps in az-pathfinder * make it compile again * more pathfinding stuff * add Bot::look_at * replace EntityMut and EntityRef with just Entity * block pos pathfinding stuff * rename movedirection to walkdirection * execute path every tick * advance path * change az-pf version * make azalea_client keep plugin state * fix Plugins::get * why does it think there is air * start debugging incorrect air * update some From methods to use rem_euclid * start adding swarm * fix deadlock i still don't understand why it was happening but the solution was to keep the Client::player lock for shorter so it didn't overlap with the Client::dimension lock * make lookat actually work probably * fix going too fast * Update main.rs * make a thing immutable * direction_looking_at * fix rotations * import swarm in an example * fix stuff from merge * remove azalea_pathfinder import * delete azalea-pathfinder crate already in azalea::pathfinder module * swarms * start working on shared dimensions * Shared worlds work * start adding Swarm::add_account * add_account works * change "client" to "bot" in some places * Fix issues from merge * Update world.rs * add SwarmEvent::Disconnect(Account) * almost add SwarmEvent::Chat and new plugin system it panics rn * make plugins have to provide the State associated type * improve comments * make fn build slightly cleaner * fix SwarmEvent::Chat * change a println in bot/main.rs * Client::shutdown -> disconnect * polish fix clippy warnings + improve some docs a bit * fix shared worlds* *there's a bug that entities and bots will have their positions exaggerated because the relative movement packet is applied for every entity once per bot * i am being trolled by rust for some reason some stuff is really slow for literally no reason and it makes no sense i am going insane * make world an RwLock again * remove debug messages * fix skipping event ticks unfortunately now sending events is `.send().await?` instead of just `.send()` * fix deadlock + warnings * turns out my floor_mod impl was wrong and i32::rem_euclid has the correct behavior LOL * still errors with lots of bots * make swarm iter & fix new chunks not loading * improve docs * start fixing tests * fix all the tests except the examples i don't know how to exclude them from the tests * improve docs some more
Diffstat (limited to 'azalea-client/src/plugins.rs')
-rw-r--r--azalea-client/src/plugins.rs106
1 files changed, 85 insertions, 21 deletions
diff --git a/azalea-client/src/plugins.rs b/azalea-client/src/plugins.rs
index 150d5960..93641906 100644
--- a/azalea-client/src/plugins.rs
+++ b/azalea-client/src/plugins.rs
@@ -10,42 +10,65 @@ use std::{
type U64Hasher = BuildHasherDefault<NoHashHasher<u64>>;
// 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.
+#[derive(Clone, Default)]
+pub struct PluginStates {
+ map: Option<HashMap<TypeId, Box<dyn PluginState>, U64Hasher>>,
+}
+
+/// A map of PluginState TypeIds to AnyPlugin objects. This can then be built
+/// into a [`PluginStates`] object to get a fresh new state based on this
+/// plugin.
///
-/// If you're using azalea, you should generate this from the `plugins!` macro.
+/// If you're using the azalea crate, you should generate this from the
+/// `plugins!` macro.
#[derive(Clone, Default)]
pub struct Plugins {
- map: Option<HashMap<TypeId, Box<dyn Plugin>, U64Hasher>>,
+ map: Option<HashMap<TypeId, Box<dyn AnyPlugin>, U64Hasher>>,
+}
+
+impl PluginStates {
+ pub fn get<T: PluginState>(&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 Plugins {
+ /// Create a new empty set of plugins.
pub fn new() -> Self {
Self::default()
}
- pub fn add<T: Plugin>(&mut self, plugin: T) {
+ /// Add a new plugin to this set.
+ pub fn add<T: Plugin + Clone>(&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));
+ .insert(TypeId::of::<T::State>(), 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>())
+ /// Build our plugin states from this set of plugins. Note that if you're
+ /// using `azalea` you'll probably never need to use this as it's called
+ /// for you.
+ pub fn build(self) -> PluginStates {
+ let mut map = HashMap::with_hasher(BuildHasherDefault::default());
+ for (id, plugin) in self.map.unwrap().into_iter() {
+ map.insert(id, plugin.build());
+ }
+ PluginStates { map: Some(map) }
}
}
-impl IntoIterator for Plugins {
- type Item = Box<dyn Plugin>;
+impl IntoIterator for PluginStates {
+ type Item = Box<dyn PluginState>;
type IntoIter = std::vec::IntoIter<Self::Item>;
+ /// Iterate over the plugin states.
fn into_iter(self) -> Self::IntoIter {
self.map
.map(|map| map.into_values().collect::<Vec<_>>())
@@ -54,26 +77,67 @@ impl IntoIterator for Plugins {
}
}
-/// Plugins can keep their own personal state, listen to events, and add new functions to Client.
+/// A `PluginState` keeps the current state of a plugin for a client. All the
+/// fields must be atomic. Unique `PluginState`s are built from [`Plugin`]s.
#[async_trait]
-pub trait Plugin: Send + Sync + PluginClone + Any + 'static {
+pub trait PluginState: Send + Sync + PluginStateClone + Any + 'static {
async fn handle(self: Box<Self>, event: Event, bot: Client);
}
-/// An internal trait that allows Plugin to be cloned.
+/// Plugins can keep their own personal state, listen to [`Event`]s, and add
+/// new functions to [`Client`].
+pub trait Plugin: Send + Sync + Any + 'static {
+ type State: PluginState;
+
+ fn build(&self) -> Self::State;
+}
+
+/// AnyPlugin is basically a Plugin but without the State associated type
+/// it has to exist so we can do a hashmap with Box<dyn AnyPlugin>
+#[doc(hidden)]
+pub trait AnyPlugin: Send + Sync + Any + AnyPluginClone + 'static {
+ fn build(&self) -> Box<dyn PluginState>;
+}
+
+impl<S: PluginState, B: Plugin<State = S> + Clone> AnyPlugin for B {
+ fn build(&self) -> Box<dyn PluginState> {
+ Box::new(self.build())
+ }
+}
+
+/// An internal trait that allows PluginState to be cloned.
+#[doc(hidden)]
+pub trait PluginStateClone {
+ fn clone_box(&self) -> Box<dyn PluginState>;
+}
+impl<T> PluginStateClone for T
+where
+ T: 'static + PluginState + Clone,
+{
+ fn clone_box(&self) -> Box<dyn PluginState> {
+ Box::new(self.clone())
+ }
+}
+impl Clone for Box<dyn PluginState> {
+ fn clone(&self) -> Self {
+ self.clone_box()
+ }
+}
+
+/// An internal trait that allows AnyPlugin to be cloned.
#[doc(hidden)]
-pub trait PluginClone {
- fn clone_box(&self) -> Box<dyn Plugin>;
+pub trait AnyPluginClone {
+ fn clone_box(&self) -> Box<dyn AnyPlugin>;
}
-impl<T> PluginClone for T
+impl<T> AnyPluginClone for T
where
T: 'static + Plugin + Clone,
{
- fn clone_box(&self) -> Box<dyn Plugin> {
+ fn clone_box(&self) -> Box<dyn AnyPlugin> {
Box::new(self.clone())
}
}
-impl Clone for Box<dyn Plugin> {
+impl Clone for Box<dyn AnyPlugin> {
fn clone(&self) -> Self {
self.clone_box()
}