aboutsummaryrefslogtreecommitdiff
path: root/azalea/src/pathfinder/custom_state.rs
blob: 52af7687ec03946e002199dcf2f56b14dec82c3c (plain)
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())
    }
}