beetry_core/node.rs
1use mitsein::vec1::Vec1;
2
3use crate::TickStatus;
4
5#[cfg_attr(any(test, feature = "mock"), mockall::automock)]
6/// Runtime contract for executable behavior tree nodes.
7///
8/// Implementations should keep all methods non-blocking. If a node blocks
9/// inside it can stall tree progress and leave execution
10/// stuck until that call returns.
11pub trait Node {
12 /// Advance the node by one execution step.
13 ///
14 /// Returning [`TickStatus::Running`] indicates the node is still in
15 /// progress. Returning [`TickStatus::Success`] or
16 /// [`TickStatus::Failure`] indicates the node has reached a terminal
17 /// state for the current run.
18 fn tick(&mut self) -> TickStatus;
19 /// Reset given node to its default state:
20 /// - should only be called by the behavior tree (root)
21 /// - should not block the thread and ideally be finished during single tick
22 fn reset(&mut self) {}
23
24 /// Interface to abort/cancel running tasks. Signal is generated by
25 /// scheduling (non-leaf) nodes and propagated to children. If leaf
26 /// node's task is running in an executor an abort signal is sent.
27 fn abort(&mut self) {}
28}
29
30/// Boxed type-erased [`Node`].
31pub type BoxNode = Box<dyn Node>;
32
33impl Node for BoxNode {
34 fn tick(&mut self) -> TickStatus {
35 (**self).tick()
36 }
37
38 fn reset(&mut self) {
39 (**self).reset();
40 }
41
42 fn abort(&mut self) {
43 (**self).abort();
44 }
45}
46
47/// Non-empty collection of nodes.
48pub type NonEmptyNodes = Vec1<BoxNode>;