1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
use std::{
any::{Any, TypeId},
sync::Arc,
};
use bevy_ecs::component::Component;
use parking_lot::RwLock;
use rustc_hash::FxHashMap;
/// The component that holds the custom pathfinder state for one of our bots.
///
/// See [`CustomPathfinderStateRef`] for more information about the inner type.
///
/// Azalea won't automatically insert this component, so if you're trying to use
/// it then you should also have logic to insert the component if it's not
/// present.
///
/// Be aware that a read lock is held on the `RwLock` while a path is being
/// calculated, which may take up to several seconds. For this reason, it may be
/// favorable to use [`RwLock::try_write`] instead of [`RwLock::write`] when
/// updating it to avoid blocking the current thread.
#[derive(Clone, Component, Default)]
pub struct CustomPathfinderState(pub Arc<RwLock<CustomPathfinderStateRef>>);
/// Arbitrary state that's passed to the pathfinder, intended to be used for
/// custom moves that need to access things that are usually inaccessible.
///
/// This is included in [`MovesCtx`].
///
/// [`MovesCtx`]: crate::pathfinder::MovesCtx
#[derive(Debug, Default)]
pub struct CustomPathfinderStateRef {
map: FxHashMap<TypeId, Box<dyn Any + Send + Sync>>,
}
impl CustomPathfinderStateRef {
pub fn insert<T: 'static + Send + Sync>(&mut self, t: T) {
self.map.insert(TypeId::of::<T>(), Box::new(t));
}
pub fn get<T: 'static + Send + Sync>(&self) -> Option<&T> {
self.map
.get(&TypeId::of::<T>())
.map(|value| value.downcast_ref().unwrap())
}
}
|