oxygengine_ai/
resources.rs

1use emergent::prelude::*;
2use oxygengine_core::ecs::{
3    commands::UniverseCommands,
4    commands::{EntityAddComponent, EntityRemoveComponent},
5    Component, Entity,
6};
7use std::{collections::HashMap, marker::PhantomData};
8
9pub type AiBehavior<C> = dyn DecisionMakingTask<AiBehaviorMemory<C>>;
10
11pub type AiCondition<C> = dyn Condition<AiBehaviorMemory<C>>;
12
13pub type AiConsideration<C> = dyn Consideration<AiBehaviorMemory<C>>;
14
15#[derive(Debug, Clone)]
16pub enum AiBehaviorError {
17    TemplateDoesNotExists(String),
18}
19
20pub struct AiBehaviorMemory<C>
21where
22    C: Component,
23{
24    pub entity: Entity,
25    pub component: &'static mut C,
26    pub commands: &'static mut UniverseCommands,
27}
28
29#[derive(Debug, Default, Copy, Clone)]
30pub struct AiBehaviorTask<MC, TC>(PhantomData<fn() -> (MC, TC)>)
31where
32    MC: Component,
33    TC: Component + Default;
34
35impl<MC, TC> Task<AiBehaviorMemory<MC>> for AiBehaviorTask<MC, TC>
36where
37    MC: Component,
38    TC: Component + Default,
39{
40    fn on_enter(&mut self, memory: &mut AiBehaviorMemory<MC>) {
41        memory
42            .commands
43            .schedule(EntityAddComponent::new(memory.entity, TC::default()));
44    }
45
46    fn on_exit(&mut self, memory: &mut AiBehaviorMemory<MC>) {
47        memory
48            .commands
49            .schedule(EntityRemoveComponent::<TC>::new(memory.entity));
50    }
51}
52
53type AiBehaviorFactory<C> = Box<dyn Fn() -> Box<AiBehavior<C>> + Send + Sync>;
54
55#[derive(Default)]
56pub struct AiBehaviors<C>
57where
58    C: Component,
59{
60    templates: HashMap<String, AiBehaviorFactory<C>>,
61}
62
63impl<C> AiBehaviors<C>
64where
65    C: Component,
66{
67    pub fn add_template<F: 'static>(&mut self, name: impl ToString, f: F)
68    where
69        F: Fn() -> Box<dyn DecisionMakingTask<AiBehaviorMemory<C>>> + Send + Sync,
70    {
71        self.templates.insert(name.to_string(), Box::new(f));
72    }
73
74    pub fn with_template<F: 'static>(mut self, name: impl ToString, f: F) -> Self
75    where
76        F: Fn() -> Box<dyn DecisionMakingTask<AiBehaviorMemory<C>>> + Send + Sync,
77    {
78        self.add_template(name, f);
79        self
80    }
81
82    pub fn remove_template(&mut self, name: &str) {
83        self.templates.remove(name);
84    }
85
86    pub(crate) fn instantiate(
87        &self,
88        name: &str,
89    ) -> Result<Box<dyn DecisionMakingTask<AiBehaviorMemory<C>>>, AiBehaviorError> {
90        match self.templates.get(name) {
91            Some(factory) => Ok(factory()),
92            None => Err(AiBehaviorError::TemplateDoesNotExists(name.to_owned())),
93        }
94    }
95}