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,