use std::collections::HashMap;
use std::rc::Rc;
use arora_behavior::{BehaviorContext, BehaviorError, BehaviorInterpreter, BehaviorStatus};
use arora_types::data::{DataStore, Key};
use uuid::Uuid;
use crate::error::BehaviorTreeError;
use crate::{run_behavior_tree, schema_groot, tree_node::TreeNode, BehaviorTree, ModuleFunction};
pub struct BehaviorTreeInterpreter {
tree: Option<BehaviorTree>,
function_index: Rc<HashMap<Uuid, ModuleFunction>>,
}
impl BehaviorTreeInterpreter {
pub fn new(function_index: Rc<HashMap<Uuid, ModuleFunction>>) -> Self {
Self {
tree: None,
function_index,
}
}
pub fn load(&mut self, behavior: BehaviorTree) {
self.tree = Some(behavior);
}
pub fn load_groot(
&mut self,
xml: &str,
store: &dyn DataStore,
) -> Result<(), BehaviorTreeError> {
let groot = schema_groot::BehaviorTree::try_from_groot_xml(xml)?;
let mut variables = HashMap::new();
let tree_node: TreeNode = groot
.root
.try_into_tree_node(self.function_index.as_ref(), &mut variables)?;
let id_to_name: HashMap<Uuid, String> =
variables.into_iter().map(|(name, id)| (id, name)).collect();
let resolver = move |name: &str| Some(store.slot(&Key::from(name)));
let behavior: BehaviorTree = tree_node.into_behavior_tree(&resolver, &id_to_name)?;
self.tree = Some(behavior);
Ok(())
}
}
impl BehaviorInterpreter for BehaviorTreeInterpreter {
fn tick(&mut self, ctx: &mut BehaviorContext) -> Result<BehaviorStatus, BehaviorError> {
let Some(tree) = self.tree.as_ref() else {
return Ok(BehaviorStatus::Running);
};
run_behavior_tree(tree, self.function_index.clone(), ctx.caller, false).map_err(|e| {
BehaviorError {
message: format!("behavior tree: {e:?}"),
}
})?;
Ok(BehaviorStatus::Done)
}
}