oxygengine_ai/
resources.rs1use 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}