use crate::NodeStatus;
use async_trait::async_trait;
use mecha10_core::Context;
use std::fmt::Debug;
#[async_trait]
pub trait BehaviorNode: Send + Sync + Debug {
async fn tick(&mut self, ctx: &Context) -> anyhow::Result<NodeStatus>;
fn name(&self) -> &str {
std::any::type_name::<Self>()
}
async fn reset(&mut self) -> anyhow::Result<()> {
Ok(())
}
async fn on_init(&mut self, _ctx: &Context) -> anyhow::Result<()> {
Ok(())
}
async fn on_terminate(&mut self, _ctx: &Context) -> anyhow::Result<()> {
Ok(())
}
}
pub type BoxedBehavior = Box<dyn BehaviorNode>;
#[async_trait]
pub trait BehaviorNodeExt: BehaviorNode {
async fn run_until_complete(&mut self, ctx: &Context) -> anyhow::Result<NodeStatus> {
loop {
match self.tick(ctx).await? {
NodeStatus::Success => return Ok(NodeStatus::Success),
NodeStatus::Failure => return Ok(NodeStatus::Failure),
NodeStatus::Running => continue,
}
}
}
async fn run_with_limit(&mut self, ctx: &Context, max_ticks: usize) -> anyhow::Result<NodeStatus> {
for _tick_count in 0..max_ticks {
match self.tick(ctx).await? {
NodeStatus::Success => return Ok(NodeStatus::Success),
NodeStatus::Failure => return Ok(NodeStatus::Failure),
NodeStatus::Running => continue,
}
}
anyhow::bail!("Behavior exceeded maximum ticks ({})", max_ticks)
}
}
impl<T: BehaviorNode + ?Sized> BehaviorNodeExt for T {}