From 835f528a9a7895341e5efa9e22d3ccadce137618 Mon Sep 17 00:00:00 2001 From: Valtteri Vallius <36015558+kaphula@users.noreply.github.com> Date: Tue, 22 Oct 2024 01:47:17 +0300 Subject: [PATCH] Optional serde support (#37) This PR makes serde an optional feature. I also added serialization derive traits to `BT` struct so you can now serialize the whole behavior tree. --- bonsai/Cargo.toml | 8 +++++--- bonsai/src/behavior.rs | 7 ++++++- bonsai/src/bt.rs | 8 ++++++-- bonsai/src/event.rs | 9 +++++++-- bonsai/src/state.rs | 9 +++++---- bonsai/src/status.rs | 6 ++++-- examples/Cargo.toml | 2 +- examples/src/graphviz/main.rs | 6 +++--- examples/src/simple_npc_ai/main.rs | 2 +- 9 files changed, 38 insertions(+), 19 deletions(-) diff --git a/bonsai/Cargo.toml b/bonsai/Cargo.toml index 508163f..768e689 100644 --- a/bonsai/Cargo.toml +++ b/bonsai/Cargo.toml @@ -12,7 +12,7 @@ name = "bonsai-bt" readme = "../README.md" repository = "https://github.com/sollimann/bonsai.git" rust-version = "1.80.0" -version = "0.7.0" +version = "0.8.0" [lib] name = "bonsai_bt" @@ -20,8 +20,10 @@ path = "src/lib.rs" [dependencies] petgraph = "0.6.2" -serde = { version = "1.0.137", features = ["derive"] } -serde_json = "1.0.81" +serde = { version = "1.0.137", features = ["derive"] , optional = true } + +[dev-dependencies] +serde_json = { version = "1.0.81" } [[test]] name = "tests" diff --git a/bonsai/src/behavior.rs b/bonsai/src/behavior.rs index 173748b..2b7882a 100644 --- a/bonsai/src/behavior.rs +++ b/bonsai/src/behavior.rs @@ -1,8 +1,12 @@ +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + /// Describes a behavior. /// /// This is used for more complex event logic. /// Can also be used for game AI. -#[derive(Clone, serde::Deserialize, serde::Serialize, PartialEq, Debug)] +#[derive(Clone, PartialEq, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum Behavior { /// Waits an amount of time before continuing /// @@ -125,6 +129,7 @@ pub enum Behavior { } #[cfg(test)] +#[cfg(feature = "serde")] mod tests { use crate::Behavior::{self, Action, Sequence, Wait, WaitForever, WhenAny, While}; diff --git a/bonsai/src/bt.rs b/bonsai/src/bt.rs index bdd57df..ee7b7a1 100644 --- a/bonsai/src/bt.rs +++ b/bonsai/src/bt.rs @@ -1,10 +1,12 @@ use std::fmt::Debug; +use crate::visualizer::NodeType; +use crate::{ActionArgs, Behavior, State, Status, UpdateEvent}; use petgraph::dot::{Config, Dot}; use petgraph::Graph; -use crate::visualizer::NodeType; -use crate::{ActionArgs, Behavior, State, Status, UpdateEvent}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; /// A "blackboard" is a simple key/value storage shared by all the nodes of the Tree. /// @@ -15,6 +17,7 @@ use crate::{ActionArgs, Behavior, State, Status, UpdateEvent}; /// /// An "entry" of the Blackboard is a key/value pair. #[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct BlackBoard(K); impl BlackBoard { @@ -26,6 +29,7 @@ impl BlackBoard { /// The BT struct contains a compiled (immutable) version /// of the behavior and a blackboard key/value storage #[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct BT { /// constructed behavior tree pub state: State, diff --git a/bonsai/src/event.rs b/bonsai/src/event.rs index 5aa4f77..54d0c9d 100644 --- a/bonsai/src/event.rs +++ b/bonsai/src/event.rs @@ -1,9 +1,13 @@ +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + /// Update arguments, such as delta time in seconds. /// To move the behavior tree forward in time it must be ticked on each iteration of the /// game/application loop. /// /// dt: states how much forward in time we should move the behavior tree -#[derive(Copy, Clone, PartialEq, PartialOrd, Debug, serde::Deserialize, serde::Serialize)] +#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct UpdateArgs { /// Delta time in seconds. pub dt: f64, @@ -17,7 +21,8 @@ impl UpdateArgs { } /// Models loop events. -#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize)] +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum Loop { /// Update the state of the application. Update(UpdateArgs), diff --git a/bonsai/src/state.rs b/bonsai/src/state.rs index 0e75c22..1cb0a8d 100644 --- a/bonsai/src/state.rs +++ b/bonsai/src/state.rs @@ -1,13 +1,13 @@ -use std::fmt::Debug; - use crate::event::UpdateEvent; use crate::sequence::{sequence, SequenceArgs}; use crate::state::State::*; use crate::status::Status::*; use crate::when_all::when_all; use crate::{Behavior, Status}; +use std::fmt::Debug; -// use serde_derive::{Deserialize, Serialize}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; /// The action is still running, and thus the action consumes /// all the remaining delta time for the tick @@ -26,7 +26,8 @@ pub struct ActionArgs<'a, E: 'a, A: 'a> { } /// Keeps track of a behavior. -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum State { /// Executes an action. ActionState(A), diff --git a/bonsai/src/status.rs b/bonsai/src/status.rs index 629b02e..1248b16 100644 --- a/bonsai/src/status.rs +++ b/bonsai/src/status.rs @@ -1,4 +1,5 @@ -// use serde_derive::{Deserialize, Serialize}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; /// The result of a behavior or action. /// @@ -7,7 +8,8 @@ /// * Success /// * Failure or /// * Running, if the action is asynchronous and it needs more time to complete -#[derive(Copy, Clone, serde::Deserialize, serde::Serialize, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum Status { /// The behavior or action succeeded. Success, diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 8e96e85..8f16d58 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -8,7 +8,7 @@ rust-version = "1.56.0" version = "0.1.0" [dependencies] -bonsai-bt = { path = "../bonsai" } +bonsai-bt = { path = "../bonsai" , features = ["serde"]} futures = "0.3.24" tokio = { version = "1.21.1", features = [ "rt-multi-thread", diff --git a/examples/src/graphviz/main.rs b/examples/src/graphviz/main.rs index 4f96d1d..3a321ed 100644 --- a/examples/src/graphviz/main.rs +++ b/examples/src/graphviz/main.rs @@ -1,14 +1,14 @@ -use std::collections::HashMap; - use bonsai_bt::{ Behavior::{Action, Sequence, Wait, WaitForever, WhenAny, While}, BT, }; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; type Damage = f64; type Distance = f64; -#[derive(serde::Deserialize, serde::Serialize, Clone, Debug, PartialEq)] +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] enum AttackDrone { /// Circles forever around target pos. Circling, diff --git a/examples/src/simple_npc_ai/main.rs b/examples/src/simple_npc_ai/main.rs index 3487675..e806d1b 100644 --- a/examples/src/simple_npc_ai/main.rs +++ b/examples/src/simple_npc_ai/main.rs @@ -1,7 +1,7 @@ use bonsai_bt::Behavior::WhileAll; use bonsai_bt::{Behavior::Action, Event, Failure, Running, Status, Success, UpdateArgs, BT}; -#[derive(serde::Deserialize, serde::Serialize, Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub enum EnemyNPC { Run, Shoot,