behaviortree-core 0.1.0

Core implementaion of behaviortree
Documentation
// Copyright © 2026 Stephan Kunz
//! Core behavior traits.

use alloc::boxed::Box;
use core::{any::Any, ops::Range};

use dataport::PortList;
#[cfg(feature = "std")]
use libloading::Library;
use tinyscript::SharedRuntime;

#[cfg(feature = "std")]
use crate::Arc;
use crate::{
	BehaviorCreationFn, BehaviorResult, ConstString, behavior_data::BehaviorData, behavior_description::BehaviorDescription,
	behavior_kind::BehaviorKind, behavior_state::BehaviorState, error::Error, tree::BehaviorTreeElementList,
};

/// Supertrait for execution of a [`Behavior`].
/// The contained functions are generated by the derive macros.
pub trait BehaviorExecution: Any + Behavior {
	/// Dynamic downcasting.
	fn as_any(&self) -> &dyn Any;

	/// Mutable dynamic downcasting.
	fn as_any_mut(&mut self) -> &mut dyn Any;

	/// Get the [`BehaviorKind`] of the behavior.
	fn kind(&self) -> BehaviorKind;

	/// Access the [`PortList`]
	fn portlist(&self) -> &dyn PortList;

	/// Access the [`PortList`]
	fn portlist_mut(&mut self) -> &mut dyn PortList;
}

/// Defines the methods common to all behaviors.
/// These methods are available when traversing a behavior tree.
#[async_trait::async_trait]
pub trait Behavior: Send + Sync {
	/// Method called during stop/cancel/halt of a behavior,
	/// intended to reset the internal fields of your behavior.
	///
	/// It is not necessary to care about children and maintaining state,
	/// which at this point has already be done by the tree.
	///
	/// Default implementation does nothing.
	/// # Errors
	/// - if something prevents stopping the behavior properly
	fn on_halt(&mut self) -> Result<(), Error> {
		Ok(())
	}

	/// Method is called before starting to tick a behavior,
	/// intended to do preliminary stuff for your behavior.
	///
	/// In general it is not necessary to care about children
	/// and maintaining state, which will be done by the
	/// default `start()` method.
	///
	/// Default implementation does nothing.
	/// # Errors
	/// - if something prevents starting the behavior properly
	fn on_start(
		&mut self,
		_behavior: &mut BehaviorData,
		_children: &mut BehaviorTreeElementList,
		_runtime: &SharedRuntime,
	) -> Result<(), Error> {
		Ok(())
	}

	/// Method is called on first tick of a behavior instead of `tick()`.
	/// If this method returns [`BehaviorState::Running`], the
	/// behavior becomes asynchronous.
	///
	/// Default implementation calls `on_start(...)` and then tick(...).
	/// # Errors
	/// - if something prevents starting the behavior properly
	async fn start(
		&mut self,
		behavior: &mut BehaviorData,
		children: &mut BehaviorTreeElementList,
		runtime: &SharedRuntime,
	) -> BehaviorResult {
		self.on_start(behavior, children, runtime)?;
		self.tick(behavior, children, runtime).await
	}

	/// Method to tick a behavior.
	/// # Errors
	async fn tick(
		&mut self,
		behavior: &mut BehaviorData,
		children: &mut BehaviorTreeElementList,
		runtime: &SharedRuntime,
	) -> BehaviorResult;

	/// Method to halt a behavior.
	///
	/// Default implementation calls `children.halt(...)` and then `self.on_halt(...)`.
	/// # Errors
	fn halt(
		&mut self,
		_behavior: &mut BehaviorData,
		children: &mut BehaviorTreeElementList,
		runtime: &SharedRuntime,
	) -> BehaviorResult {
		children.halt(runtime)?;
		self.on_halt()?;
		Ok(BehaviorState::Idle)
	}
}

// Methods to be provided by behavior factories/registries.
pub trait BehaviorRegistry {
	/// Add a behavior to the registry
	/// # Errors
	/// - if the behavior entry already exists
	fn add_behavior(&mut self, desc: BehaviorDescription, creation_fn: Box<BehaviorCreationFn>) -> Result<(), Error>;

	/// Add a behavior tree definition to the registry.
	/// # Errors
	/// - if the behavior tree definition is already registered.
	fn add_tree_defintion(&mut self, id: &str, tree_definition: ConstString, range: Range<usize>) -> Result<(), Error>;
	/// Get a reference to the registered libraries.
	/// Typically these are cloned to ensure their existence during further operation.
	#[cfg(feature = "std")]
	#[must_use]
	fn libraries(&self) -> &alloc::vec::Vec<Arc<Library>>;

	/// Get a reference to the prepared scripting runtime.
	/// Typically this is cloned to be used with its registered extensions.
	#[must_use]
	fn runtime(&self) -> &tinyscript::Runtime;

	/// Register an enums key/value pair.
	/// # Errors
	/// - if the key is already used
	fn register_enum_tuple(&mut self, key: &str, value: i8) -> Result<(), Error>;
}