🔍 s&box Package Code Search
Search C# source code, UI razor templates, shaders, and configs across s&box packages.
🔗 Raw Facepunch API Link: https://public.facepunch.com/sbox/code/search/1/?ident=utopia.npbehavesbox&take=20
Showing code results for query:
*
(89 total matches found)
Game
library
using System.Collections.Generic;
using Sandbox.Diagnostics;
namespace NPBehave
{
public class Parallel : Composite
{
public enum Policy
{
One,
All,
}
// public enum Wait
// {
// NEVER,
// ON_FAILURE,
// ON_SUCCESS,
// BOTH
// }
// private Wait waitForPendingChildrenRule;
private Policy _failurePolicy;
private Policy _successPolicy;
private int _childrenCount = 0;
private int _runningCount = 0;
private int _succeededCount = 0;
private int _failedCount = 0;
private Dictionary<Node, bool> _childrenResults;
private bool _successState;
private bool _childrenAborted;
public Parallel(Policy successPolicy, Policy failurePolicy, /*Wait waitForPendingChildrenRule,*/ params Node[] children) : base("Parallel", children)
{
_successPolicy = successPolicy;
_failurePolicy = failurePolicy;
// this.waitForPendingChildrenRule = waitForPendingChildrenRule;
_childrenCount = children.Length;
_childrenResults = new Dictionary<Node, bool>();
}
protected override void DoStart()
{
foreach (Node child in Children)
{
Assert.AreEqual(child.CurrentState, State.Inactive);
}
_childrenAborted = false;
_runningCount = 0;
_succeededCount = 0;
_failedCount = 0;
foreach (Node child in Children)
{
_runningCount++;
child.Start();
}
}
protected override void DoStop()
{
Assert.True(_runningCount + _succeededCount + _failedCount == _childrenCount);
foreach (Node child in Children)
{
if (child.IsActive)
{
child.Stop();
}
}
}
protected override void DoChildStopped(Node child, bool result)
{
_runningCount--;
if (result)
{
_succeededCount++;
}
else
{
_failedCount++;
}
_childrenResults[child] = result;
bool allChildrenStarted = _runningCount + _succeededCount + _failedCount == _childrenCount;
if (allChildrenStarted)
{
if (_runningCount == 0)
{
if (!_childrenAborted) // if children got aborted because rule was evaluated previously, we don't want to override the successState
{
if (_failurePolicy == Policy.One && _failedCount > 0)
{
_successState = false;
}
else if (_successPolicy == Policy.One && _succeededCount > 0)
{
_successState = true;
}
else if (_successPolicy == Policy.All && _succeededCount == _childrenCount)
{
_successState = true;
}
else
{
_successState = false;
}
}
Stopped(_successState);
}
else if (!_childrenAborted)
{
Assert.False(_succeededCount == _childrenCount);
Assert.False(_failedCount == _childrenCount);
if (_failurePolicy == Policy.One && _failedCount > 0/* && waitForPendingChildrenRule != Wait.ON_FAILURE && waitForPendingChildrenRule != Wait.BOTH*/)
{
_successState = false;
_childrenAborted = true;
}
else if (_successPolicy == Policy.One && _succeededCount > 0/* && waitForPendingChildrenRule != Wait.ON_SUCCESS && waitForPendingChildrenRule != Wait.BOTH*/)
{
_successState = true;
_childrenAborted = true;
}
if (_childrenAborted)
{
foreach (Node currentChild in Children)
{
if (currentChild.IsActive)
{
currentChild.Stop();
}
}
}
}
}
}
public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)
{
if (immediateRestart)
{
Assert.False(abortForChild.IsActive);
if (_childrenResults[abortForChild])
{
_succeededCount--;
}
else
{
_failedCount--;
}
_runningCount++;
abortForChild.Start();
}
else
{
throw new Exception("On Parallel Nodes all children have the same priority, thus the method does nothing if you pass false to 'immediateRestart'!");
}
}
}
}
Game
library
using System.Collections;
using Sandbox.Diagnostics;
namespace NPBehave
{
public class RandomSequence : Composite
{
static System.Random _rng = new System.Random();
#if DEBUG
static public void DebugSetSeed( int seed )
{
_rng = new System.Random( seed );
}
#endif
private int _currentIndex = -1;
private int[] _randomizedOrder;
public RandomSequence(params Node[] children) : base("Random Sequence", children)
{
_randomizedOrder = new int[children.Length];
for (int i = 0; i < Children.Length; i++)
{
_randomizedOrder[i] = i;
}
}
protected override void DoStart()
{
foreach (Node child in Children)
{
Assert.AreEqual(child.CurrentState, State.Inactive);
}
_currentIndex = -1;
// Shuffling
int n = _randomizedOrder.Length;
while (n > 1)
{
int k = _rng.Next(n--);
(_randomizedOrder[n], _randomizedOrder[k]) = (_randomizedOrder[k], _randomizedOrder[n]);
}
ProcessChildren();
}
protected override void DoStop()
{
Children[_randomizedOrder[_currentIndex]].Stop();
}
protected override void DoChildStopped(Node child, bool result)
{
if (result)
{
ProcessChildren();
}
else
{
Stopped(false);
}
}
private void ProcessChildren()
{
if (++_currentIndex < Children.Length)
{
if (IsStopRequested)
{
Stopped(false);
}
else
{
Children[_randomizedOrder[_currentIndex]].Start();
}
}
else
{
Stopped(true);
}
}
public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)
{
int indexForChild = 0;
bool found = false;
foreach (Node currentChild in Children)
{
if (currentChild == abortForChild)
{
found = true;
}
else if (!found)
{
indexForChild++;
}
else if (found && currentChild.IsActive)
{
if (immediateRestart)
{
_currentIndex = indexForChild - 1;
}
else
{
_currentIndex = Children.Length;
}
currentChild.Stop();
break;
}
}
}
public override string ToString()
{
return $"{base.ToString()}[{_currentIndex}]";
}
}
}
Game
library
namespace NPBehave
{
public class Succeeder : Decorator
{
public Succeeder(Node decoratee) : base("Succeeder", decoratee)
{
}
protected override void DoStart()
{
Decoratee.Start();
}
protected override void DoStop()
{
Decoratee.Stop();
}
protected override void DoChildStopped(Node child, bool result)
{
Stopped(true);
}
}
}
Game
library
using System;
namespace NPBehave
{
public class Exception : System.Exception
{
public Exception(string message) : base(message)
{
}
}
}
Game
library
namespace NPBehave
{
public class Repeater : Decorator
{
private int _loopCount = -1;
private int _currentLoop;
/// <param name="loopCount">number of times to execute the decoratee. Set to -1 to repeat forever, be careful with endless loops!</param>
/// <param name="decoratee">Decorated Node</param>
public Repeater(int loopCount, Node decoratee) : base("Repeater", decoratee)
{
_loopCount = loopCount;
}
/// <param name="decoratee">Decorated Node, repeated forever</param>
public Repeater(Node decoratee) : base("Repeater", decoratee)
{
}
protected override void DoStart()
{
if (_loopCount != 0)
{
_currentLoop = 0;
Decoratee.Start();
}
else
{
Stopped(true);
}
}
protected override void DoStop()
{
Clock.RemoveTimer(RestartDecoratee);
if (Decoratee.IsActive)
{
Decoratee.Stop();
}
else
{
Stopped(false);
}
}
protected override void DoChildStopped(Node child, bool result)
{
if (result)
{
if (IsStopRequested || (_loopCount > 0 && ++_currentLoop >= _loopCount))
{
Stopped(true);
}
else
{
Clock.AddTimer(0, 0, RestartDecoratee);
}
}
else
{
Stopped(false);
}
}
protected void RestartDecoratee()
{
Decoratee.Start();
}
}
}
Game
library
using System.Collections;
using Sandbox.Diagnostics;
namespace NPBehave
{
public class Selector : Composite
{
private int _currentIndex = -1;
public Selector(params Node[] children) : base("Selector", children)
{
}
#if DEBUG
public override string DebugIcon => "rule";
#endif
protected override void DoStart()
{
foreach (Node child in Children)
{
Assert.AreEqual(child.CurrentState, State.Inactive);
}
_currentIndex = -1;
ProcessChildren();
}
protected override void DoStop()
{
Children[_currentIndex].Stop();
}
protected override void DoChildStopped(Node child, bool result)
{
if (result)
{
Stopped(true);
}
else
{
ProcessChildren();
}
}
private void ProcessChildren()
{
if (++_currentIndex < Children.Length)
{
if (IsStopRequested)
{
Stopped(false);
}
else
{
Children[_currentIndex].Start();
}
}
else
{
Stopped(false);
}
}
public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)
{
int indexForChild = 0;
bool found = false;
foreach (Node currentChild in Children)
{
if (currentChild == abortForChild)
{
found = true;
}
else if (!found)
{
indexForChild++;
}
else if (found && currentChild.IsActive)
{
if (immediateRestart)
{
_currentIndex = indexForChild - 1;
}
else
{
_currentIndex = Children.Length;
}
currentChild.Stop();
break;
}
}
}
public override string ToString()
{
return $"{base.ToString()}[{_currentIndex}]";
}
}
}
Game
library
namespace NPBehave
{
public class BlackboardCondition : ObservingDecorator
{
private string _key;
private object _value;
private Operator _op;
public string Key
{
get
{
return _key;
}
}
public object Value
{
get
{
return _value;
}
}
public Operator Operator
{
get
{
return _op;
}
}
#if DEBUG
public override string DebugIcon => "quiz";
public override string ComputedLabel
{
get
{
return $"{Key} {OperatorToString(Operator)} {Value}";
}
}
public string OperatorToString( Operator _op )
{
return _op switch
{
Operator.IsSet => "?=",
Operator.IsNotSet => "?!=",
Operator.IsEqual => "==",
Operator.IsNotEqual => "!=",
Operator.IsGreaterOrEqual => ">=",
Operator.IsGreater => ">",
Operator.IsSmallerOrEqual => "<=",
Operator.IsSmaller => "<",
Operator.AlwaysTrue => "ALWAYS_TRUE",
_ => $"<{_op}>"
};
}
#endif
public BlackboardCondition(string key, Operator op, object value, Stops stopsOnChange, Node decoratee) : base("BlackboardCondition", stopsOnChange, decoratee)
{
_op = op;
_key = key;
_value = value;
StopsOnChange = stopsOnChange;
}
public BlackboardCondition(string key, Operator op, Stops stopsOnChange, Node decoratee) : base("BlackboardCondition", stopsOnChange, decoratee)
{
_op = op;
_key = key;
StopsOnChange = stopsOnChange;
}
protected override void StartObserving()
{
RootNode.Blackboard.AddObserver(_key, OnValueChanged);
}
protected override void StopObserving()
{
RootNode.Blackboard.RemoveObserver(_key, OnValueChanged);
}
private void OnValueChanged(Blackboard.Type type, object newValue)
{
Evaluate();
}
protected override bool IsConditionMet()
{
if (_op == Operator.AlwaysTrue)
{
return true;
}
if (!RootNode.Blackboard.IsSet(_key))
{
return _op == Operator.IsNotSet;
}
object o = RootNode.Blackboard.Get(_key);
switch (_op)
{
case Operator.IsSet: return true;
case Operator.IsEqual: return Equals(o, _value);
case Operator.IsNotEqual: return !Equals(o, _value);
case Operator.IsGreaterOrEqual:
if (o is float)
{
return (float)o >= (float)_value;
}
else if (o is int)
{
return (int)o >= (int)_value;
}
else
{
Log.Error( $"Type not compareable: {o.GetType()}" );
return false;
}
case Operator.IsGreater:
if (o is float)
{
return (float)o > (float)_value;
}
else if (o is int)
{
return (int)o > (int)_value;
}
else
{
Log.Error( $"Type not compareable: {o.GetType()}" );
return false;
}
case Operator.IsSmallerOrEqual:
if (o is float)
{
return (float)o <= (float)_value;
}
else if (o is int)
{
return (int)o <= (int)_value;
}
else
{
Log.Error( $"Type not compareable: {o.GetType()}" );
return false;
}
case Operator.IsSmaller:
if (o is float)
{
return (float)o < (float)_value;
}
else if (o is int)
{
return (int)o < (int)_value;
}
else
{
Log.Error( $"Type not compareable: {o.GetType()}" );
return false;
}
default: return false;
}
}
public override string ToString()
{
return $"({_op}) {_key} ? {_value}";
}
}
}
Game
library
using System;
namespace NPBehave
{
public class Condition : ObservingDecorator
{
private Func<bool> _condition;
private float _checkInterval;
private float _checkVariance;
public Condition(Func<bool> condition, Node decoratee) : base("Condition", Stops.None, decoratee)
{
_condition = condition;
_checkInterval = 0.0f;
_checkVariance = 0.0f;
}
public Condition(Func<bool> condition, Stops stopsOnChange, Node decoratee) : base("Condition", stopsOnChange, decoratee)
{
_condition = condition;
_checkInterval = 0.0f;
_checkVariance = 0.0f;
}
public Condition(Func<bool> condition, Stops stopsOnChange, float checkInterval, float randomVariance, Node decoratee) : base("Condition", stopsOnChange, decoratee)
{
_condition = condition;
_checkInterval = checkInterval;
_checkVariance = randomVariance;
}
protected override void StartObserving()
{
RootNode.Clock.AddTimer(_checkInterval, _checkVariance, -1, Evaluate);
}
protected override void StopObserving()
{
RootNode.Clock.RemoveTimer(Evaluate);
}
protected override bool IsConditionMet()
{
return _condition();
}
}
}
Game
library
namespace NPBehave
{
public abstract class Decorator : Container
{
protected Node Decoratee;
public Decorator(string name, Node decoratee) : base(name)
{
Decoratee = decoratee;
Decoratee.SetParent(this);
}
public override void SetRoot(Root rootNode)
{
base.SetRoot(rootNode);
Decoratee.SetRoot(rootNode);
}
#if DEBUG
public override string DebugIcon => "brush";
public override Node[] DebugChildren
{
get
{
return new Node[] { Decoratee };
}
}
#endif
public override void ParentCompositeStopped(Composite composite)
{
base.ParentCompositeStopped(composite);
Decoratee.ParentCompositeStopped(composite);
}
}
}
Game
library
using System.Collections;
using Sandbox.Diagnostics;
namespace NPBehave
{
public abstract class ObservingDecorator : Decorator
{
protected Stops StopsOnChange;
private bool _isObserving;
public ObservingDecorator(string name, Stops stopsOnChange, Node decoratee) : base(name, decoratee)
{
StopsOnChange = stopsOnChange;
_isObserving = false;
}
protected override void DoStart()
{
if (StopsOnChange != Stops.None)
{
if (!_isObserving)
{
_isObserving = true;
StartObserving();
}
}
if (!IsConditionMet())
{
Stopped(false);
}
else
{
Decoratee.Start();
}
}
protected override void DoStop()
{
Decoratee.Stop();
}
protected override void DoChildStopped(Node child, bool result)
{
Assert.AreNotEqual(((Node)this).CurrentState, State.Inactive);
if (StopsOnChange is Stops.None or Stops.Self)
{
if (_isObserving)
{
_isObserving = false;
StopObserving();
}
}
Stopped(result);
}
protected override void DoParentCompositeStopped(Composite parentComposite)
{
if (_isObserving)
{
_isObserving = false;
StopObserving();
}
}
protected void Evaluate()
{
if (IsActive && !IsConditionMet())
{
if (StopsOnChange is Stops.Self or Stops.Both or Stops.ImmediateRestart)
{
// Debug.Log( this.key + " stopped self ");
Stop();
}
}
else if (!IsActive && IsConditionMet())
{
if (StopsOnChange == Stops.LowerPriority || StopsOnChange == Stops.Both || StopsOnChange == Stops.ImmediateRestart || StopsOnChange == Stops.LowerPriorityImmediateRestart)
{
// Debug.Log( this.key + " stopped other ");
Container parentNode = ParentNode;
Node childNode = this;
while (parentNode != null && !(parentNode is Composite))
{
childNode = parentNode;
parentNode = parentNode.ParentNode;
}
Assert.NotNull(parentNode, "NTBtrStops is only valid when attached to a parent composite");
Assert.NotNull(childNode);
if (parentNode is Parallel)
{
Assert.True(StopsOnChange == Stops.ImmediateRestart, "On Parallel Nodes all children have the same priority, thus Stops.LOWER_PRIORITY or Stops.BOTH are unsupported in this context!");
}
if (StopsOnChange == Stops.ImmediateRestart || StopsOnChange == Stops.LowerPriorityImmediateRestart)
{
if (_isObserving)
{
_isObserving = false;
StopObserving();
}
}
((Composite)parentNode)?.StopLowerPriorityChildrenForChild(childNode, StopsOnChange is Stops.ImmediateRestart or Stops.LowerPriorityImmediateRestart);
}
}
}
protected abstract void StartObserving();
protected abstract void StopObserving();
protected abstract bool IsConditionMet();
}
}
Game
library
using Sandbox.Diagnostics;
namespace NPBehave
{
public class TimeMin : Decorator
{
private float _limit = 0.0f;
private float _randomVariation;
private bool _waitOnFailure = false;
private bool _isLimitReached = false;
private bool _isDecorateeDone = false;
private bool _isDecorateeSuccess = false;
public TimeMin(float limit, Node decoratee) : base("TimeMin", decoratee)
{
_limit = limit;
_randomVariation = _limit * 0.05f;
_waitOnFailure = false;
Assert.True(limit > 0f, "limit has to be set");
}
public TimeMin(float limit, bool waitOnFailure, Node decoratee) : base("TimeMin", decoratee)
{
_limit = limit;
_randomVariation = _limit * 0.05f;
_waitOnFailure = waitOnFailure;
Assert.True(limit > 0f, "limit has to be set");
}
public TimeMin(float limit, float randomVariation, bool waitOnFailure, Node decoratee) : base("TimeMin", decoratee)
{
_limit = limit;
_randomVariation = randomVariation;
_waitOnFailure = waitOnFailure;
Assert.True(limit > 0f, "limit has to be set");
}
protected override void DoStart()
{
_isDecorateeDone = false;
_isDecorateeSuccess = false;
_isLimitReached = false;
Clock.AddTimer(_limit, _randomVariation, 0, TimeoutReached);
Decoratee.Start();
}
protected override void DoStop()
{
if (Decoratee.IsActive)
{
Clock.RemoveTimer(TimeoutReached);
_isLimitReached = true;
Decoratee.Stop();
}
else
{
Clock.RemoveTimer(TimeoutReached);
Stopped(false);
}
}
protected override void DoChildStopped(Node child, bool result)
{
_isDecorateeDone = true;
_isDecorateeSuccess = result;
if (_isLimitReached || (!result && !_waitOnFailure))
{
Clock.RemoveTimer(TimeoutReached);
Stopped(_isDecorateeSuccess);
}
else
{
Assert.True(Clock.HasTimer(TimeoutReached));
}
}
private void TimeoutReached()
{
_isLimitReached = true;
if (_isDecorateeDone)
{
Stopped(_isDecorateeSuccess);
}
else
{
Assert.True(Decoratee.IsActive);
}
}
}
}
UnitTest
library
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
Game
library
using System.Collections;
using Sandbox.Diagnostics;
namespace NPBehave
{
public class RandomSelector : Composite
{
static System.Random _rng = new System.Random();
#if DEBUG
static public void DebugSetSeed( int seed )
{
_rng = new System.Random( seed );
}
#endif
private int _currentIndex = -1;
private int[] _randomizedOrder;
public RandomSelector(params Node[] children) : base("Random Selector", children)
{
_randomizedOrder = new int[children.Length];
for (int i = 0; i < Children.Length; i++)
{
_randomizedOrder[i] = i;
}
}
protected override void DoStart()
{
foreach (Node child in Children)
{
Assert.AreEqual(child.CurrentState, State.Inactive);
}
_currentIndex = -1;
// Shuffling
int n = _randomizedOrder.Length;
while (n > 1)
{
int k = _rng.Next(n--);
(_randomizedOrder[n], _randomizedOrder[k]) = (_randomizedOrder[k], _randomizedOrder[n]);
}
ProcessChildren();
}
protected override void DoStop()
{
Children[_randomizedOrder[_currentIndex]].Stop();
}
protected override void DoChildStopped(Node child, bool result)
{
if (result)
{
Stopped(true);
}
else
{
ProcessChildren();
}
}
private void ProcessChildren()
{
if (++_currentIndex < Children.Length)
{
if (IsStopRequested)
{
Stopped(false);
}
else
{
Children[_randomizedOrder[_currentIndex]].Start();
}
}
else
{
Stopped(false);
}
}
public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)
{
int indexForChild = 0;
bool found = false;
foreach (Node currentChild in Children)
{
if (currentChild == abortForChild)
{
found = true;
}
else if (!found)
{
indexForChild++;
}
else if (found && currentChild.IsActive)
{
if (immediateRestart)
{
_currentIndex = indexForChild - 1;
}
else
{
_currentIndex = Children.Length;
}
currentChild.Stop();
break;
}
}
}
public override string ToString()
{
return $"{base.ToString()}[{_currentIndex}]";
}
}
}
Game
library
using System.Collections.Generic;
using Sandbox;
namespace NPBehave
{
public class Debugger : Component
{
public Root BehaviorTree;
private static Blackboard _customGlobalStats = null;
public static Blackboard CustomGlobalStats
{
get
{
if (_customGlobalStats == null)
{
_customGlobalStats = SandboxContext.GetSharedBlackboard("_GlobalStats");;
}
return _customGlobalStats;
}
}
private Blackboard _customStats = null;
public Blackboard CustomStats
{
get
{
if (_customStats == null)
{
_customStats = new Blackboard(CustomGlobalStats, SandboxContext.GetClock());
}
return _customStats;
}
}
public void DebugCounterInc(string key)
{
if (!CustomStats.IsSet(key))
{
CustomStats[key] = 0;
}
CustomStats[key] = CustomStats.Get<int>(key) + 1;
}
public void DebugCounterDec(string key)
{
if (!CustomStats.IsSet(key))
{
CustomStats[key] = 0;
}
CustomStats[key] = CustomStats.Get<int>(key) - 1;
}
public static void GlobalDebugCounterInc(string key)
{
if (!CustomGlobalStats.IsSet(key))
{
CustomGlobalStats[key] = 0;
}
CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) + 1;
}
public static void GlobalDebugCounterDec(string key)
{
if (!CustomGlobalStats.IsSet(key))
{
CustomGlobalStats[key] = 0;
}
CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) - 1;
}
}
}
Game
library
namespace NPBehave
{
public class Inverter : Decorator
{
public Inverter(Node decoratee) : base("Inverter", decoratee)
{
}
protected override void DoStart()
{
Decoratee.Start();
}
protected override void DoStop()
{
Decoratee.Stop();
}
protected override void DoChildStopped(Node child, bool result)
{
Stopped(!result);
}
}
}
Game
library
namespace NPBehave
{
public enum Stops
{
/// <summary>
/// The decorator will only check it's condition once it is started and will never stop any running nodes.
/// </summary>
None,
/// <summary>
/// The decorator will check it's condition once it is started and if it is met,
/// it will observe the blackboard for changes.
/// Once the condition is no longer met, it will stop itself allowing the parent composite to proceed with it's next node.
/// </summary>
Self,
/// <summary>
/// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.
/// Once the condition is met, it will stop the lower priority node allowing the parent composite to proceed with it's next node
/// </summary>
LowerPriority,
/// <summary>
/// The decorator will stop both: self and lower priority nodes.
/// </summary>
Both,
/// <summary>
/// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.
/// Once the condition is met, it will stop the lower priority node and order the parent composite to restart the Decorator immediately.
/// </summary>
ImmediateRestart,
/// <summary>
/// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.
/// Once the condition is met, it will stop the lower priority node and order the parent composite to restart the Decorator immediately.
/// As in BOTH it will also stop itself as soon as the condition is no longer met.
/// </summary>
LowerPriorityImmediateRestart
}
}
Game
library
using Sandbox.Diagnostics;
namespace NPBehave
{
public class Action : Task
{
public enum Result
{
Success,
Failed,
Blocked,
Progress
}
public enum Request
{
Start,
Update,
Cancel,
}
private System.Func<bool> _singleFrameFunc = null;
private System.Func<bool, Result> _multiFrameFunc = null;
private System.Func<Request, Result> _multiFrameFunc2 = null;
private System.Action _action = null;
private bool _bWasBlocked = false;
public Action(System.Action action) : base("Action")
{
_action = action;
}
public Action(System.Func<bool, Result> multiframeFunc) : base("Action")
{
_multiFrameFunc = multiframeFunc;
}
public Action(System.Func<Request, Result> multiframeFunc2) : base("Action")
{
_multiFrameFunc2 = multiframeFunc2;
}
public Action(System.Func<bool> singleFrameFunc) : base("Action")
{
_singleFrameFunc = singleFrameFunc;
}
protected override void DoStart()
{
if (_action != null)
{
_action.Invoke();
Stopped(true);
}
else if (_multiFrameFunc != null)
{
Result result = _multiFrameFunc.Invoke(false);
if ( result == Result.Progress )
{
RootNode.Clock.AddUpdateObserver( OnUpdateFunc );
}
else if ( result == Result.Blocked )
{
_bWasBlocked = true;
RootNode.Clock.AddUpdateObserver( OnUpdateFunc );
}
else
{
Stopped(result == Result.Success);
}
}
else if (_multiFrameFunc2 != null)
{
Result result = _multiFrameFunc2.Invoke(Request.Start);
if (result == Result.Progress)
{
RootNode.Clock.AddUpdateObserver(OnUpdateFunc2);
}
else if ( result == Result.Blocked )
{
_bWasBlocked = true;
RootNode.Clock.AddUpdateObserver( OnUpdateFunc2 );
}
else
{
Stopped(result == Result.Success);
}
}
else if (_singleFrameFunc != null)
{
Stopped(_singleFrameFunc.Invoke());
}
}
private void OnUpdateFunc()
{
Result result = _multiFrameFunc.Invoke(false);
if (result != Result.Progress && result != Result.Blocked)
{
RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc);
Stopped(result == Result.Success);
}
}
private void OnUpdateFunc2()
{
Result result = _multiFrameFunc2.Invoke( _bWasBlocked ? Request.Start : Request.Update);
if ( result == Result.Blocked )
{
_bWasBlocked = true;
}
else if ( result == Result.Progress )
{
_bWasBlocked = false;
}
else
{
RootNode.Clock.RemoveUpdateObserver( OnUpdateFunc2 );
Stopped( result == Result.Success );
}
}
protected override void DoStop()
{
if (_multiFrameFunc != null)
{
Result result = _multiFrameFunc.Invoke(true);
Assert.AreNotEqual(result, Result.Progress, "The Task has to return Result.SUCCESS, Result.FAILED/BLOCKED after beeing cancelled!");
RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc);
Stopped(result == Result.Success);
}
else if (_multiFrameFunc2 != null)
{
Result result = _multiFrameFunc2.Invoke(Request.Cancel);
Assert.AreNotEqual(result, Result.Progress, "The Task has to return Result.SUCCESS or Result.FAILED/BLOCKED after beeing cancelled!");
RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc2);
Stopped(result == Result.Success);
}
else
{
Assert.True(false, $"DoStop called for a single frame action on {this}" );
}
}
}
}
Game
library
using NPBehave;
namespace Sandbox.Samples;
public class NPBehaveExampleHelloWorldAI : Component
{
private Root _behaviorTree;
void Start()
{
_behaviorTree = new Root(
new Sequence(
new Action(() => Log.Info("Hello, World!"))
)
);
_behaviorTree.Start();
}
}
Game
library
using System.Collections.Generic;
namespace NPBehave
{
public class Blackboard
{
public enum Type
{
Add,
Remove,
Change
}
private struct Notification
{
public string Key;
public Type Type;
public object Value;
public Notification(string key, Type type, object value)
{
Key = key;
Type = type;
Value = value;
}
}
private Clock _clock;
private Dictionary<string, object> _data = new Dictionary<string, object>();
private Dictionary<string, List<System.Action<Type, object>>> _observers = new Dictionary<string, List<System.Action<Type, object>>>();
private bool _isNotifiyng = false;
private Dictionary<string, List<System.Action<Type, object>>> _addObservers = new Dictionary<string, List<System.Action<Type, object>>>();
private Dictionary<string, List<System.Action<Type, object>>> _removeObservers = new Dictionary<string, List<System.Action<Type, object>>>();
private List<Notification> _notifications = new List<Notification>();
private List<Notification> _notificationsDispatch = new List<Notification>();
private Blackboard _parentBlackboard;
private HashSet<Blackboard> _children = new HashSet<Blackboard>();
public Blackboard(Blackboard parent, Clock clock)
{
_clock = clock;
_parentBlackboard = parent;
}
public Blackboard(Clock clock)
{
_parentBlackboard = null;
_clock = clock;
}
public void Enable()
{
_parentBlackboard?._children.Add(this);
}
public void Disable()
{
_parentBlackboard?._children.Remove(this);
if (_clock != null)
{
_clock.RemoveTimer(NotifiyObservers);
}
}
public object this[string key]
{
get
{
return Get(key);
}
set
{
Set(key, value);
}
}
public void Set(string key)
{
if (!IsSet(key))
{
Set(key, null);
}
}
public void Set(string key, object value)
{
if (_parentBlackboard != null && _parentBlackboard.IsSet(key))
{
_parentBlackboard.Set(key, value);
}
else
{
if (_data.TryAdd(key, value))
{
_notifications.Add(new Notification(key, Type.Add, value));
_clock.AddTimer(0f, 0, NotifiyObservers);
}
else
{
if ((_data[key] == null && value != null) || (_data[key] != null && !_data[key].Equals(value)))
{
_data[key] = value;
_notifications.Add(new Notification(key, Type.Change, value));
_clock.AddTimer(0f, 0, NotifiyObservers);
}
}
}
}
public void Unset(string key)
{
if (_data.ContainsKey(key))
{
_data.Remove(key);
_notifications.Add(new Notification(key, Type.Remove, null));
_clock.AddTimer(0f, 0, NotifiyObservers);
}
}
public T Get<T>(string key)
{
object result = Get(key);
if (result == null)
{
return default(T);
}
return (T)result;
}
public object Get(string key)
{
return _data.TryGetValue(key, out var value) ? value : _parentBlackboard?.Get(key);
}
public bool IsSet(string key)
{
return _data.ContainsKey(key) || (_parentBlackboard != null && _parentBlackboard.IsSet(key));
}
public void AddObserver(string key, System.Action<Type, object> observer)
{
List<System.Action<Type, object>> observers = GetObserverList(_observers, key);
if (!_isNotifiyng)
{
if (!observers.Contains(observer))
{
observers.Add(observer);
}
}
else
{
if (!observers.Contains(observer))
{
List<System.Action<Type, object>> addObservers = GetObserverList(_addObservers, key);
if (!addObservers.Contains(observer))
{
addObservers.Add(observer);
}
}
List<System.Action<Type, object>> removeObservers = GetObserverList(_removeObservers, key);
if (removeObservers.Contains(observer))
{
removeObservers.Remove(observer);
}
}
}
public void RemoveObserver(string key, System.Action<Type, object> observer)
{
List<System.Action<Type, object>> observers = GetObserverList(_observers, key);
if (!_isNotifiyng)
{
if (observers.Contains(observer))
{
observers.Remove(observer);
}
}
else
{
List<System.Action<Type, object>> removeObservers = GetObserverList(_removeObservers, key);
if (!removeObservers.Contains(observer))
{
if (observers.Contains(observer))
{
removeObservers.Add(observer);
}
}
List<System.Action<Type, object>> addObservers = GetObserverList(_addObservers, key);
if (addObservers.Contains(observer))
{
addObservers.Remove(observer);
}
}
}
#if DEBUG
public List<string> Keys
{
get
{
if (_parentBlackboard != null)
{
List<string> keys = this._parentBlackboard.Keys;
keys.AddRange(_data.Keys);
return keys;
}
else
{
return new List<string>(_data.Keys);
}
}
}
public int NumObservers
{
get
{
int count = 0;
foreach (var key in _observers.Keys)
{
count += _observers[key].Count;
}
return count;
}
}
#endif
private void NotifiyObservers()
{
if (_notifications.Count == 0)
{
return;
}
_notificationsDispatch.Clear();
_notificationsDispatch.AddRange(_notifications);
foreach (Blackboard child in _children)
{
child._notifications.AddRange(_notifications);
child._clock.AddTimer(0f, 0, child.NotifiyObservers);
}
_notifications.Clear();
_isNotifiyng = true;
foreach (Notification notification in _notificationsDispatch)
{
if (!_observers.ContainsKey(notification.Key))
{
// Debug.Log("1 do not notify for key:" + notification.key + " value: " + notification.value);
continue;
}
List<System.Action<Type, object>> observers = GetObserverList(_observers, notification.Key);
foreach (System.Action<Type, object> observer in observers)
{
if (_removeObservers.TryGetValue( notification.Key, out List<System.Action<Type, object>> value ) && value.Contains(observer))
{
continue;
}
observer(notification.Type, notification.Value);
}
}
foreach (string key in _addObservers.Keys)
{
GetObserverList(_observers, key).AddRange(_addObservers[key]);
}
foreach (string key in _removeObservers.Keys)
{
foreach (System.Action<Type, object> action in _removeObservers[key])
{
GetObserverList(_observers, key).Remove(action);
}
}
_addObservers.Clear();
_removeObservers.Clear();
_isNotifiyng = false;
}
private List<System.Action<Type, object>> GetObserverList(Dictionary<string, List<System.Action<Type, object>>> target, string key)
{
List<System.Action<Type, object>> observers;
if (target.TryGetValue(key, out var value))
{
observers = value;
}
else
{
observers = new List<System.Action<Type, object>>();
target[key] = observers;
}
return observers;
}
}
}
Game
library
using System.Collections.Generic;
using Sandbox;
namespace NPBehave
{
public class Debugger : Component
{
public Root BehaviorTree;
private static Blackboard _customGlobalStats = null;
public static Blackboard CustomGlobalStats
{
get
{
if (_customGlobalStats == null)
{
_customGlobalStats = SandboxContext.GetSharedBlackboard("_GlobalStats");;
}
return _customGlobalStats;
}
}
private Blackboard _customStats = null;
public Blackboard CustomStats
{
get
{
if (_customStats == null)
{
_customStats = new Blackboard(CustomGlobalStats, SandboxContext.GetClock());
}
return _customStats;
}
}
public void DebugCounterInc(string key)
{
if (!CustomStats.IsSet(key))
{
CustomStats[key] = 0;
}
CustomStats[key] = CustomStats.Get<int>(key) + 1;
}
public void DebugCounterDec(string key)
{
if (!CustomStats.IsSet(key))
{
CustomStats[key] = 0;
}
CustomStats[key] = CustomStats.Get<int>(key) - 1;
}
public static void GlobalDebugCounterInc(string key)
{
if (!CustomGlobalStats.IsSet(key))
{
CustomGlobalStats[key] = 0;
}
CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) + 1;
}
public static void GlobalDebugCounterDec(string key)
{
if (!CustomGlobalStats.IsSet(key))
{
CustomGlobalStats[key] = 0;
}
CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) - 1;
}
}
}
Debug: View Raw JSON Response
{
"TotalCount": 89,
"Files": [
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Composite/Parallel.cs",
"FileName": "Parallel.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using System.Collections.Generic;\nusing Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n public class Parallel : Composite\n {\n public enum Policy\n {\n One,\n All,\n }\n\n // public enum Wait\n // {\n // NEVER,\n // ON_FAILURE,\n // ON_SUCCESS,\n // BOTH\n // }\n\n // private Wait waitForPendingChildrenRule;\n private Policy _failurePolicy;\n private Policy _successPolicy;\n private int _childrenCount = 0;\n private int _runningCount = 0;\n private int _succeededCount = 0;\n private int _failedCount = 0;\n private Dictionary<Node, bool> _childrenResults;\n private bool _successState;\n private bool _childrenAborted;\n\n public Parallel(Policy successPolicy, Policy failurePolicy, /*Wait waitForPendingChildrenRule,*/ params Node[] children) : base(\"Parallel\", children)\n {\n _successPolicy = successPolicy;\n _failurePolicy = failurePolicy;\n // this.waitForPendingChildrenRule = waitForPendingChildrenRule;\n _childrenCount = children.Length;\n _childrenResults = new Dictionary<Node, bool>();\n }\n\n protected override void DoStart()\n {\n foreach (Node child in Children)\n {\n Assert.AreEqual(child.CurrentState, State.Inactive);\n }\n\n _childrenAborted = false;\n _runningCount = 0;\n _succeededCount = 0;\n _failedCount = 0;\n foreach (Node child in Children)\n {\n _runningCount++;\n child.Start();\n }\n }\n\n protected override void DoStop()\n {\n Assert.True(_runningCount + _succeededCount + _failedCount == _childrenCount);\n\n foreach (Node child in Children)\n {\n if (child.IsActive)\n {\n child.Stop();\n }\n }\n }\n\n protected override void DoChildStopped(Node child, bool result)\n {\n _runningCount--;\n if (result)\n {\n _succeededCount++;\n }\n else\n {\n _failedCount++;\n }\n _childrenResults[child] = result;\n\n bool allChildrenStarted = _runningCount + _succeededCount + _failedCount == _childrenCount;\n if (allChildrenStarted)\n {\n if (_runningCount == 0)\n {\n if (!_childrenAborted) // if children got aborted because rule was evaluated previously, we don't want to override the successState \n {\n if (_failurePolicy == Policy.One && _failedCount > 0)\n {\n _successState = false;\n }\n else if (_successPolicy == Policy.One && _succeededCount > 0)\n {\n _successState = true;\n }\n else if (_successPolicy == Policy.All && _succeededCount == _childrenCount)\n {\n _successState = true;\n }\n else\n {\n _successState = false;\n }\n }\n Stopped(_successState);\n }\n else if (!_childrenAborted)\n {\n Assert.False(_succeededCount == _childrenCount);\n Assert.False(_failedCount == _childrenCount);\n\n if (_failurePolicy == Policy.One && _failedCount > 0/* && waitForPendingChildrenRule != Wait.ON_FAILURE && waitForPendingChildrenRule != Wait.BOTH*/)\n {\n _successState = false;\n _childrenAborted = true;\n }\n else if (_successPolicy == Policy.One && _succeededCount > 0/* && waitForPendingChildrenRule != Wait.ON_SUCCESS && waitForPendingChildrenRule != Wait.BOTH*/)\n {\n _successState = true;\n _childrenAborted = true;\n }\n\n if (_childrenAborted)\n {\n foreach (Node currentChild in Children)\n {\n if (currentChild.IsActive)\n {\n currentChild.Stop();\n }\n }\n }\n }\n }\n }\n\n public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)\n {\n if (immediateRestart)\n {\n Assert.False(abortForChild.IsActive);\n if (_childrenResults[abortForChild])\n {\n _succeededCount--;\n }\n else\n {\n _failedCount--;\n }\n _runningCount++;\n abortForChild.Start();\n }\n else\n {\n throw new Exception(\"On Parallel Nodes all children have the same priority, thus the method does nothing if you pass false to 'immediateRestart'!\");\n }\n }\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Composite/RandomSequence.cs",
"FileName": "RandomSequence.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using System.Collections;\nusing Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n public class RandomSequence : Composite\n {\n static System.Random _rng = new System.Random();\n\n\n#if DEBUG\n static public void DebugSetSeed( int seed )\n {\n _rng = new System.Random( seed );\n }\n#endif\n\n private int _currentIndex = -1;\n private int[] _randomizedOrder;\n\n public RandomSequence(params Node[] children) : base(\"Random Sequence\", children)\n {\n _randomizedOrder = new int[children.Length];\n for (int i = 0; i < Children.Length; i++)\n {\n _randomizedOrder[i] = i;\n }\n }\n\n protected override void DoStart()\n {\n foreach (Node child in Children)\n {\n Assert.AreEqual(child.CurrentState, State.Inactive);\n }\n\n _currentIndex = -1;\n\n // Shuffling\n int n = _randomizedOrder.Length;\n while (n > 1)\n {\n int k = _rng.Next(n--);\n (_randomizedOrder[n], _randomizedOrder[k]) = (_randomizedOrder[k], _randomizedOrder[n]);\n }\n\n ProcessChildren();\n }\n\n protected override void DoStop()\n {\n Children[_randomizedOrder[_currentIndex]].Stop();\n }\n\n\n protected override void DoChildStopped(Node child, bool result)\n {\n if (result)\n {\n ProcessChildren();\n }\n else\n {\n Stopped(false);\n }\n }\n\n private void ProcessChildren()\n {\n if (++_currentIndex < Children.Length)\n {\n if (IsStopRequested)\n {\n Stopped(false);\n }\n else\n {\n Children[_randomizedOrder[_currentIndex]].Start();\n }\n }\n else\n {\n Stopped(true);\n }\n }\n\n public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)\n {\n int indexForChild = 0;\n bool found = false;\n foreach (Node currentChild in Children)\n {\n if (currentChild == abortForChild)\n {\n found = true;\n }\n else if (!found)\n {\n indexForChild++;\n }\n else if (found && currentChild.IsActive)\n {\n if (immediateRestart)\n {\n _currentIndex = indexForChild - 1;\n }\n else\n {\n _currentIndex = Children.Length;\n }\n currentChild.Stop();\n break;\n }\n }\n }\n\n public override string ToString()\n {\n return $\"{base.ToString()}[{_currentIndex}]\";\n }\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Decorator/Succeeder.cs",
"FileName": "Succeeder.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "namespace NPBehave\n{\n public class Succeeder : Decorator\n {\n public Succeeder(Node decoratee) : base(\"Succeeder\", decoratee)\n {\n }\n\n protected override void DoStart()\n {\n Decoratee.Start();\n }\n\n protected override void DoStop()\n {\n Decoratee.Stop();\n }\n\n protected override void DoChildStopped(Node child, bool result)\n {\n Stopped(true);\n }\n }\n}"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "Code/BehaviorTree/Exception.cs",
"FileName": "Exception.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using System;\n\nnamespace NPBehave\n{\n public class Exception : System.Exception\n {\n public Exception(string message) : base(message)\n {\n }\n }\n}"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "Code/BehaviorTree/Decorator/Repeater.cs",
"FileName": "Repeater.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "namespace NPBehave\n{\n public class Repeater : Decorator\n {\n private int _loopCount = -1;\n private int _currentLoop;\n\n /// <param name=\"loopCount\">number of times to execute the decoratee. Set to -1 to repeat forever, be careful with endless loops!</param>\n /// <param name=\"decoratee\">Decorated Node</param>\n public Repeater(int loopCount, Node decoratee) : base(\"Repeater\", decoratee)\n {\n _loopCount = loopCount;\n }\n\n /// <param name=\"decoratee\">Decorated Node, repeated forever</param>\n public Repeater(Node decoratee) : base(\"Repeater\", decoratee)\n {\n }\n\n protected override void DoStart()\n {\n if (_loopCount != 0)\n {\n _currentLoop = 0;\n Decoratee.Start();\n }\n else\n {\n Stopped(true);\n }\n }\n\n protected override void DoStop()\n {\n Clock.RemoveTimer(RestartDecoratee);\n \n if (Decoratee.IsActive)\n {\n Decoratee.Stop();\n }\n else\n {\n Stopped(false);\n }\n }\n\n protected override void DoChildStopped(Node child, bool result)\n {\n if (result)\n {\n if (IsStopRequested || (_loopCount > 0 && ++_currentLoop >= _loopCount))\n {\n Stopped(true);\n }\n else\n {\n Clock.AddTimer(0, 0, RestartDecoratee);\n }\n }\n else\n {\n Stopped(false);\n }\n }\n\n protected void RestartDecoratee()\n {\n Decoratee.Start();\n }\n }\n}"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Composite/Selector.cs",
"FileName": "Selector.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using System.Collections;\nusing Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n public class Selector : Composite\n {\n private int _currentIndex = -1;\n\n public Selector(params Node[] children) : base(\"Selector\", children)\n {\n }\n\n\t\t#if DEBUG\n\t public override string DebugIcon => \"rule\";\n\t\t#endif\n protected override void DoStart()\n {\n foreach (Node child in Children)\n {\n Assert.AreEqual(child.CurrentState, State.Inactive);\n }\n\n _currentIndex = -1;\n\n ProcessChildren();\n }\n\n protected override void DoStop()\n {\n Children[_currentIndex].Stop();\n }\n\n protected override void DoChildStopped(Node child, bool result)\n {\n if (result)\n {\n Stopped(true);\n }\n else\n {\n ProcessChildren();\n }\n }\n\n private void ProcessChildren()\n {\n if (++_currentIndex < Children.Length)\n {\n if (IsStopRequested)\n {\n Stopped(false);\n }\n else\n {\n Children[_currentIndex].Start();\n }\n }\n else\n {\n Stopped(false);\n }\n }\n\n public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)\n {\n int indexForChild = 0;\n bool found = false;\n foreach (Node currentChild in Children)\n {\n if (currentChild == abortForChild)\n {\n found = true;\n }\n else if (!found)\n {\n indexForChild++;\n }\n else if (found && currentChild.IsActive)\n {\n if (immediateRestart)\n {\n _currentIndex = indexForChild - 1;\n }\n else\n {\n _currentIndex = Children.Length;\n }\n currentChild.Stop();\n break;\n }\n }\n }\n\n public override string ToString()\n {\n return $\"{base.ToString()}[{_currentIndex}]\";\n }\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Decorator/BlackboardCondition.cs",
"FileName": "BlackboardCondition.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "namespace NPBehave\n{\n public class BlackboardCondition : ObservingDecorator\n {\n private string _key;\n private object _value;\n private Operator _op;\n\n public string Key\n {\n get\n {\n return _key;\n }\n }\n\n public object Value\n {\n get\n {\n return _value;\n }\n }\n\n public Operator Operator\n {\n get\n {\n return _op;\n }\n }\n \n #if DEBUG\n\t public override string DebugIcon => \"quiz\";\n\t public override string ComputedLabel\n\t {\n\t\t get\n\t\t {\n\t\t\t return $\"{Key} {OperatorToString(Operator)} {Value}\";\n\t\t }\n\t }\n\n\t public string OperatorToString( Operator _op )\n\t {\n\t\t return _op switch\n\t\t {\n\t\t\t Operator.IsSet => \"?=\",\n\t\t\t Operator.IsNotSet => \"?!=\",\n\t\t\t Operator.IsEqual => \"==\",\n\t\t\t Operator.IsNotEqual => \"!=\",\n\t\t\t Operator.IsGreaterOrEqual => \">=\",\n\t\t\t Operator.IsGreater => \">\",\n\t\t\t Operator.IsSmallerOrEqual => \"<=\",\n\t\t\t Operator.IsSmaller => \"<\",\n\t\t\t Operator.AlwaysTrue => \"ALWAYS_TRUE\",\n\t\t\t _ => $\"<{_op}>\"\n\t\t };\n\t }\n\n\n#endif\n\n public BlackboardCondition(string key, Operator op, object value, Stops stopsOnChange, Node decoratee) : base(\"BlackboardCondition\", stopsOnChange, decoratee)\n {\n _op = op;\n _key = key;\n _value = value;\n StopsOnChange = stopsOnChange;\n }\n \n public BlackboardCondition(string key, Operator op, Stops stopsOnChange, Node decoratee) : base(\"BlackboardCondition\", stopsOnChange, decoratee)\n {\n _op = op;\n _key = key;\n StopsOnChange = stopsOnChange;\n }\n\n\n protected override void StartObserving()\n {\n RootNode.Blackboard.AddObserver(_key, OnValueChanged);\n }\n\n protected override void StopObserving()\n {\n RootNode.Blackboard.RemoveObserver(_key, OnValueChanged);\n }\n\n private void OnValueChanged(Blackboard.Type type, object newValue)\n {\n Evaluate();\n }\n\n protected override bool IsConditionMet()\n {\n if (_op == Operator.AlwaysTrue)\n {\n return true;\n }\n\n if (!RootNode.Blackboard.IsSet(_key))\n {\n return _op == Operator.IsNotSet;\n }\n\n object o = RootNode.Blackboard.Get(_key);\n\n switch (_op)\n {\n case Operator.IsSet: return true;\n case Operator.IsEqual: return Equals(o, _value);\n case Operator.IsNotEqual: return !Equals(o, _value);\n\n case Operator.IsGreaterOrEqual:\n if (o is float)\n {\n return (float)o >= (float)_value;\n }\n else if (o is int)\n {\n return (int)o >= (int)_value;\n }\n else\n {\n Log.Error( $\"Type not compareable: {o.GetType()}\" );\n return false;\n }\n\n case Operator.IsGreater:\n if (o is float)\n {\n return (float)o > (float)_value;\n }\n else if (o is int)\n {\n return (int)o > (int)_value;\n }\n else\n {\n\t Log.Error( $\"Type not compareable: {o.GetType()}\" );\n return false;\n }\n\n case Operator.IsSmallerOrEqual:\n if (o is float)\n {\n return (float)o <= (float)_value;\n }\n else if (o is int)\n {\n return (int)o <= (int)_value;\n }\n else\n {\n\t Log.Error( $\"Type not compareable: {o.GetType()}\" );\n return false;\n }\n\n case Operator.IsSmaller:\n if (o is float)\n {\n return (float)o < (float)_value;\n }\n else if (o is int)\n {\n return (int)o < (int)_value;\n }\n else\n {\n\t Log.Error( $\"Type not compareable: {o.GetType()}\" );\n return false;\n }\n\n default: return false;\n }\n }\n\n public override string ToString()\n {\n return $\"({_op}) {_key} ? {_value}\";\n }\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Decorator/Condition.cs",
"FileName": "Condition.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using System;\n\nnamespace NPBehave\n{\n public class Condition : ObservingDecorator\n {\n private Func<bool> _condition;\n private float _checkInterval;\n private float _checkVariance;\n\n public Condition(Func<bool> condition, Node decoratee) : base(\"Condition\", Stops.None, decoratee)\n {\n _condition = condition;\n _checkInterval = 0.0f;\n _checkVariance = 0.0f;\n }\n\n public Condition(Func<bool> condition, Stops stopsOnChange, Node decoratee) : base(\"Condition\", stopsOnChange, decoratee)\n {\n _condition = condition;\n _checkInterval = 0.0f;\n _checkVariance = 0.0f;\n }\n\n public Condition(Func<bool> condition, Stops stopsOnChange, float checkInterval, float randomVariance, Node decoratee) : base(\"Condition\", stopsOnChange, decoratee)\n {\n _condition = condition;\n _checkInterval = checkInterval;\n _checkVariance = randomVariance;\n }\n\n protected override void StartObserving()\n {\n RootNode.Clock.AddTimer(_checkInterval, _checkVariance, -1, Evaluate);\n }\n\n protected override void StopObserving()\n {\n RootNode.Clock.RemoveTimer(Evaluate);\n }\n\n protected override bool IsConditionMet()\n {\n return _condition();\n }\n }\n}"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Decorator/Decorator.cs",
"FileName": "Decorator.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "namespace NPBehave\n{\n\n public abstract class Decorator : Container\n {\n protected Node Decoratee;\n\n public Decorator(string name, Node decoratee) : base(name)\n {\n Decoratee = decoratee;\n Decoratee.SetParent(this);\n }\n\n public override void SetRoot(Root rootNode)\n {\n base.SetRoot(rootNode);\n Decoratee.SetRoot(rootNode);\n }\n\n\n#if DEBUG\n\n\t public override string DebugIcon => \"brush\";\n\t public override Node[] DebugChildren\n {\n get\n {\n return new Node[] { Decoratee };\n }\n }\n#endif\n\n public override void ParentCompositeStopped(Composite composite)\n {\n base.ParentCompositeStopped(composite);\n Decoratee.ParentCompositeStopped(composite);\n }\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Decorator/ObservingDecorator.cs",
"FileName": "ObservingDecorator.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using System.Collections;\nusing Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n public abstract class ObservingDecorator : Decorator\n {\n protected Stops StopsOnChange;\n private bool _isObserving;\n\n public ObservingDecorator(string name, Stops stopsOnChange, Node decoratee) : base(name, decoratee)\n {\n StopsOnChange = stopsOnChange;\n _isObserving = false;\n }\n\n protected override void DoStart()\n {\n if (StopsOnChange != Stops.None)\n {\n if (!_isObserving)\n {\n _isObserving = true;\n StartObserving();\n }\n }\n\n if (!IsConditionMet())\n {\n Stopped(false);\n }\n else\n {\n Decoratee.Start();\n }\n }\n\n protected override void DoStop()\n {\n Decoratee.Stop();\n }\n\n protected override void DoChildStopped(Node child, bool result)\n {\n Assert.AreNotEqual(((Node)this).CurrentState, State.Inactive);\n if (StopsOnChange is Stops.None or Stops.Self)\n {\n if (_isObserving)\n {\n _isObserving = false;\n StopObserving();\n }\n }\n Stopped(result);\n }\n\n protected override void DoParentCompositeStopped(Composite parentComposite)\n {\n if (_isObserving)\n {\n _isObserving = false;\n StopObserving();\n }\n }\n\n protected void Evaluate()\n {\n if (IsActive && !IsConditionMet())\n {\n if (StopsOnChange is Stops.Self or Stops.Both or Stops.ImmediateRestart)\n {\n // Debug.Log( this.key + \" stopped self \");\n Stop();\n }\n }\n else if (!IsActive && IsConditionMet())\n {\n if (StopsOnChange == Stops.LowerPriority || StopsOnChange == Stops.Both || StopsOnChange == Stops.ImmediateRestart || StopsOnChange == Stops.LowerPriorityImmediateRestart)\n {\n // Debug.Log( this.key + \" stopped other \");\n Container parentNode = ParentNode;\n Node childNode = this;\n while (parentNode != null && !(parentNode is Composite))\n {\n childNode = parentNode;\n parentNode = parentNode.ParentNode;\n }\n Assert.NotNull(parentNode, \"NTBtrStops is only valid when attached to a parent composite\");\n Assert.NotNull(childNode);\n if (parentNode is Parallel)\n {\n Assert.True(StopsOnChange == Stops.ImmediateRestart, \"On Parallel Nodes all children have the same priority, thus Stops.LOWER_PRIORITY or Stops.BOTH are unsupported in this context!\");\n }\n\n if (StopsOnChange == Stops.ImmediateRestart || StopsOnChange == Stops.LowerPriorityImmediateRestart)\n {\n if (_isObserving)\n {\n _isObserving = false;\n StopObserving();\n }\n }\n\n ((Composite)parentNode)?.StopLowerPriorityChildrenForChild(childNode, StopsOnChange is Stops.ImmediateRestart or Stops.LowerPriorityImmediateRestart);\n }\n }\n }\n\n protected abstract void StartObserving();\n\n protected abstract void StopObserving();\n\n protected abstract bool IsConditionMet();\n\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Decorator/TimeMin.cs",
"FileName": "TimeMin.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n public class TimeMin : Decorator\n {\n private float _limit = 0.0f;\n private float _randomVariation;\n private bool _waitOnFailure = false;\n private bool _isLimitReached = false;\n private bool _isDecorateeDone = false;\n private bool _isDecorateeSuccess = false;\n\n public TimeMin(float limit, Node decoratee) : base(\"TimeMin\", decoratee)\n {\n _limit = limit;\n _randomVariation = _limit * 0.05f;\n _waitOnFailure = false;\n Assert.True(limit > 0f, \"limit has to be set\");\n }\n\n public TimeMin(float limit, bool waitOnFailure, Node decoratee) : base(\"TimeMin\", decoratee)\n {\n _limit = limit;\n _randomVariation = _limit * 0.05f;\n _waitOnFailure = waitOnFailure;\n Assert.True(limit > 0f, \"limit has to be set\");\n }\n\n public TimeMin(float limit, float randomVariation, bool waitOnFailure, Node decoratee) : base(\"TimeMin\", decoratee)\n {\n _limit = limit;\n _randomVariation = randomVariation;\n _waitOnFailure = waitOnFailure;\n Assert.True(limit > 0f, \"limit has to be set\");\n }\n\n protected override void DoStart()\n {\n _isDecorateeDone = false;\n _isDecorateeSuccess = false;\n _isLimitReached = false;\n Clock.AddTimer(_limit, _randomVariation, 0, TimeoutReached);\n Decoratee.Start();\n }\n\n protected override void DoStop()\n {\n if (Decoratee.IsActive)\n {\n Clock.RemoveTimer(TimeoutReached);\n _isLimitReached = true;\n Decoratee.Stop();\n }\n else\n {\n Clock.RemoveTimer(TimeoutReached);\n Stopped(false);\n }\n }\n\n protected override void DoChildStopped(Node child, bool result)\n {\n _isDecorateeDone = true;\n _isDecorateeSuccess = result;\n if (_isLimitReached || (!result && !_waitOnFailure))\n {\n Clock.RemoveTimer(TimeoutReached);\n Stopped(_isDecorateeSuccess);\n }\n else\n {\n Assert.True(Clock.HasTimer(TimeoutReached));\n }\n }\n\n private void TimeoutReached()\n {\n _isLimitReached = true;\n if (_isDecorateeDone)\n {\n Stopped(_isDecorateeSuccess);\n }\n else\n {\n Assert.True(Decoratee.IsActive);\n }\n }\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "UnitTests/LibraryTest.cs",
"FileName": "LibraryTest.cs",
"PackageType": "library",
"CodeKind": "UnitTest",
"AssetVersionId": 72229,
"Code": "using Sandbox;\r\n\r\n[TestClass]\r\npublic partial class LibraryTests\r\n{\r\n\t[TestMethod]\r\n\tpublic void SceneTest()\r\n\t{\r\n\t\tvar scene = new Scene();\r\n\t\tusing ( scene.Push() )\r\n\t\t{\r\n\t\t\tvar go = new GameObject();\r\n\r\n\t\t\tAssert.AreEqual( 1, scene.Directory.GameObjectCount );\r\n\t\t}\r\n\t}\r\n\r\n}\r\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Composite/RandomSelector.cs",
"FileName": "RandomSelector.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using System.Collections;\nusing Sandbox.Diagnostics;\n\n\nnamespace NPBehave\n{\n public class RandomSelector : Composite\n {\n static System.Random _rng = new System.Random();\n\n#if DEBUG\n static public void DebugSetSeed( int seed )\n {\n _rng = new System.Random( seed );\n }\n#endif\n\n private int _currentIndex = -1;\n private int[] _randomizedOrder;\n\n public RandomSelector(params Node[] children) : base(\"Random Selector\", children)\n {\n _randomizedOrder = new int[children.Length];\n for (int i = 0; i < Children.Length; i++)\n {\n _randomizedOrder[i] = i;\n }\n }\n\n\n protected override void DoStart()\n {\n foreach (Node child in Children)\n {\n Assert.AreEqual(child.CurrentState, State.Inactive);\n }\n\n _currentIndex = -1;\n\n // Shuffling\n int n = _randomizedOrder.Length;\n while (n > 1)\n {\n int k = _rng.Next(n--);\n (_randomizedOrder[n], _randomizedOrder[k]) = (_randomizedOrder[k], _randomizedOrder[n]);\n }\n\n ProcessChildren();\n }\n\n\n\n protected override void DoStop()\n {\n Children[_randomizedOrder[_currentIndex]].Stop();\n }\n\n protected override void DoChildStopped(Node child, bool result)\n {\n if (result)\n {\n Stopped(true);\n }\n else\n {\n ProcessChildren();\n }\n }\n\n private void ProcessChildren()\n {\n if (++_currentIndex < Children.Length)\n {\n if (IsStopRequested)\n {\n Stopped(false);\n }\n else\n {\n Children[_randomizedOrder[_currentIndex]].Start();\n }\n }\n else\n {\n Stopped(false);\n }\n }\n\n public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)\n {\n int indexForChild = 0;\n bool found = false;\n foreach (Node currentChild in Children)\n {\n if (currentChild == abortForChild)\n {\n found = true;\n }\n else if (!found)\n {\n indexForChild++;\n }\n else if (found && currentChild.IsActive)\n {\n if (immediateRestart)\n {\n _currentIndex = indexForChild - 1;\n }\n else\n {\n _currentIndex = Children.Length;\n }\n currentChild.Stop();\n break;\n }\n }\n }\n\n public override string ToString()\n {\n return $\"{base.ToString()}[{_currentIndex}]\";\n }\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Debugger.cs",
"FileName": "Debugger.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using System.Collections.Generic;\nusing Sandbox;\n\nnamespace NPBehave\n{\n public class Debugger : Component\n {\n public Root BehaviorTree;\n\n private static Blackboard _customGlobalStats = null;\n public static Blackboard CustomGlobalStats\n {\n get \n {\n if (_customGlobalStats == null)\n {\n _customGlobalStats = SandboxContext.GetSharedBlackboard(\"_GlobalStats\");;\n }\n return _customGlobalStats;\n }\n }\n\n private Blackboard _customStats = null;\n public Blackboard CustomStats\n {\n get \n {\n if (_customStats == null)\n {\n _customStats = new Blackboard(CustomGlobalStats, SandboxContext.GetClock());\n }\n return _customStats;\n }\n }\n\n public void DebugCounterInc(string key)\n {\n if (!CustomStats.IsSet(key))\n {\n CustomStats[key] = 0;\n }\n CustomStats[key] = CustomStats.Get<int>(key) + 1;\n }\n\n public void DebugCounterDec(string key)\n {\n if (!CustomStats.IsSet(key))\n {\n CustomStats[key] = 0;\n }\n CustomStats[key] = CustomStats.Get<int>(key) - 1;\n }\n\n public static void GlobalDebugCounterInc(string key)\n {\n if (!CustomGlobalStats.IsSet(key))\n {\n CustomGlobalStats[key] = 0;\n }\n CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) + 1;\n }\n\n public static void GlobalDebugCounterDec(string key)\n {\n if (!CustomGlobalStats.IsSet(key))\n {\n CustomGlobalStats[key] = 0;\n }\n CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) - 1;\n }\n\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Decorator/Inverter.cs",
"FileName": "Inverter.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "namespace NPBehave\n{\n public class Inverter : Decorator\n {\n public Inverter(Node decoratee) : base(\"Inverter\", decoratee)\n {\n }\n\n protected override void DoStart()\n {\n Decoratee.Start();\n }\n\n protected override void DoStop()\n {\n Decoratee.Stop();\n }\n\n protected override void DoChildStopped(Node child, bool result)\n {\n Stopped(!result);\n }\n }\n}"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Stops.cs",
"FileName": "Stops.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "namespace NPBehave\n{\n public enum Stops\n {\n\t /// <summary>\n\t /// The decorator will only check it's condition once it is started and will never stop any running nodes.\n\t /// </summary>\n None,\n\t /// <summary>\n\t /// The decorator will check it's condition once it is started and if it is met,\n\t /// it will observe the blackboard for changes.\n\t /// Once the condition is no longer met, it will stop itself allowing the parent composite to proceed with it's next node.\n\t /// </summary>\n Self,\n\t \n\t /// <summary>\n\t /// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.\n\t /// Once the condition is met, it will stop the lower priority node allowing the parent composite to proceed with it's next node\n\t /// </summary>\n LowerPriority,\n\t \n\t /// <summary>\n\t /// The decorator will stop both: self and lower priority nodes.\n\t /// </summary>\n Both,\n\t \n\t /// <summary>\n\t /// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.\n\t /// Once the condition is met, it will stop the lower priority node and order the parent composite to restart the Decorator immediately.\n\t /// </summary>\n ImmediateRestart,\n\t \n\t /// <summary>\n\t /// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.\n\t /// Once the condition is met, it will stop the lower priority node and order the parent composite to restart the Decorator immediately.\n\t /// As in BOTH it will also stop itself as soon as the condition is no longer met.\n\t /// </summary>\n LowerPriorityImmediateRestart\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "BehaviorTree/Task/Action.cs",
"FileName": "Action.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n public class Action : Task\n {\n public enum Result\n {\n Success,\n Failed,\n Blocked,\n Progress\n }\n\n public enum Request\n {\n Start,\n Update,\n Cancel,\n }\n\n private System.Func<bool> _singleFrameFunc = null;\n private System.Func<bool, Result> _multiFrameFunc = null;\n private System.Func<Request, Result> _multiFrameFunc2 = null;\n private System.Action _action = null;\n private bool _bWasBlocked = false;\n\n public Action(System.Action action) : base(\"Action\")\n {\n _action = action;\n }\n\n public Action(System.Func<bool, Result> multiframeFunc) : base(\"Action\")\n {\n _multiFrameFunc = multiframeFunc;\n }\n\n public Action(System.Func<Request, Result> multiframeFunc2) : base(\"Action\")\n {\n _multiFrameFunc2 = multiframeFunc2;\n }\n\n\n public Action(System.Func<bool> singleFrameFunc) : base(\"Action\")\n {\n _singleFrameFunc = singleFrameFunc;\n }\n\n protected override void DoStart()\n {\n if (_action != null)\n {\n _action.Invoke();\n Stopped(true);\n }\n else if (_multiFrameFunc != null)\n {\n Result result = _multiFrameFunc.Invoke(false);\n if ( result == Result.Progress )\n {\n RootNode.Clock.AddUpdateObserver( OnUpdateFunc );\n }\n else if ( result == Result.Blocked )\n {\n _bWasBlocked = true;\n RootNode.Clock.AddUpdateObserver( OnUpdateFunc );\n }\n else\n {\n Stopped(result == Result.Success);\n }\n }\n else if (_multiFrameFunc2 != null)\n {\n Result result = _multiFrameFunc2.Invoke(Request.Start);\n if (result == Result.Progress)\n {\n RootNode.Clock.AddUpdateObserver(OnUpdateFunc2);\n }\n else if ( result == Result.Blocked )\n {\n _bWasBlocked = true;\n RootNode.Clock.AddUpdateObserver( OnUpdateFunc2 );\n }\n else\n {\n Stopped(result == Result.Success);\n }\n }\n else if (_singleFrameFunc != null)\n {\n Stopped(_singleFrameFunc.Invoke());\n }\n }\n\n private void OnUpdateFunc()\n {\n Result result = _multiFrameFunc.Invoke(false);\n if (result != Result.Progress && result != Result.Blocked)\n {\n RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc);\n Stopped(result == Result.Success);\n }\n }\n\n private void OnUpdateFunc2()\n {\n Result result = _multiFrameFunc2.Invoke( _bWasBlocked ? Request.Start : Request.Update);\n\n if ( result == Result.Blocked )\n {\n _bWasBlocked = true;\n }\n else if ( result == Result.Progress )\n {\n _bWasBlocked = false;\n }\n else\n {\n RootNode.Clock.RemoveUpdateObserver( OnUpdateFunc2 );\n Stopped( result == Result.Success );\n }\n }\n\n protected override void DoStop()\n {\n if (_multiFrameFunc != null)\n {\n Result result = _multiFrameFunc.Invoke(true);\n Assert.AreNotEqual(result, Result.Progress, \"The Task has to return Result.SUCCESS, Result.FAILED/BLOCKED after beeing cancelled!\");\n RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc);\n Stopped(result == Result.Success);\n }\n else if (_multiFrameFunc2 != null)\n {\n Result result = _multiFrameFunc2.Invoke(Request.Cancel);\n Assert.AreNotEqual(result, Result.Progress, \"The Task has to return Result.SUCCESS or Result.FAILED/BLOCKED after beeing cancelled!\");\n RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc2);\n Stopped(result == Result.Success);\n }\n else\n {\n Assert.True(false, $\"DoStop called for a single frame action on {this}\" );\n }\n }\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "Samples/NPBehaveExampleHelloWorldAI.cs",
"FileName": "NPBehaveExampleHelloWorldAI.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using NPBehave;\r\n\r\nnamespace Sandbox.Samples;\r\n\r\npublic class NPBehaveExampleHelloWorldAI : Component\r\n{\r\n\tprivate Root _behaviorTree;\r\n\r\n\tvoid Start()\r\n\t{\r\n\t\t_behaviorTree = new Root(\r\n\t\t\tnew Sequence(\r\n\t\t\t\tnew Action(() => Log.Info(\"Hello, World!\"))\r\n\t\t\t)\r\n\t\t);\r\n\t\t_behaviorTree.Start();\r\n\t}\r\n}\r\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "Code/BehaviorTree/Blackboard.cs",
"FileName": "Blackboard.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using System.Collections.Generic;\n\nnamespace NPBehave\n{\n public class Blackboard\n {\n public enum Type\n {\n Add,\n Remove,\n Change\n }\n private struct Notification\n {\n public string Key;\n public Type Type;\n public object Value;\n public Notification(string key, Type type, object value)\n {\n Key = key;\n Type = type;\n Value = value;\n }\n }\n\n private Clock _clock;\n private Dictionary<string, object> _data = new Dictionary<string, object>();\n private Dictionary<string, List<System.Action<Type, object>>> _observers = new Dictionary<string, List<System.Action<Type, object>>>();\n private bool _isNotifiyng = false;\n private Dictionary<string, List<System.Action<Type, object>>> _addObservers = new Dictionary<string, List<System.Action<Type, object>>>();\n private Dictionary<string, List<System.Action<Type, object>>> _removeObservers = new Dictionary<string, List<System.Action<Type, object>>>();\n private List<Notification> _notifications = new List<Notification>();\n private List<Notification> _notificationsDispatch = new List<Notification>();\n private Blackboard _parentBlackboard;\n private HashSet<Blackboard> _children = new HashSet<Blackboard>();\n\n public Blackboard(Blackboard parent, Clock clock)\n {\n _clock = clock;\n _parentBlackboard = parent;\n }\n public Blackboard(Clock clock)\n {\n _parentBlackboard = null;\n _clock = clock;\n }\n\n public void Enable()\n {\n\t _parentBlackboard?._children.Add(this);\n }\n\n public void Disable()\n {\n\t _parentBlackboard?._children.Remove(this);\n if (_clock != null)\n {\n _clock.RemoveTimer(NotifiyObservers);\n }\n }\n\n public object this[string key]\n {\n get\n {\n return Get(key);\n }\n set\n {\n Set(key, value);\n }\n }\n\n public void Set(string key)\n {\n if (!IsSet(key))\n {\n Set(key, null);\n }\n }\n\n public void Set(string key, object value)\n {\n if (_parentBlackboard != null && _parentBlackboard.IsSet(key))\n {\n _parentBlackboard.Set(key, value);\n }\n else\n {\n if (_data.TryAdd(key, value))\n {\n\t _notifications.Add(new Notification(key, Type.Add, value));\n _clock.AddTimer(0f, 0, NotifiyObservers);\n }\n else\n {\n if ((_data[key] == null && value != null) || (_data[key] != null && !_data[key].Equals(value)))\n {\n _data[key] = value;\n _notifications.Add(new Notification(key, Type.Change, value));\n _clock.AddTimer(0f, 0, NotifiyObservers);\n }\n }\n }\n }\n\n public void Unset(string key)\n {\n if (_data.ContainsKey(key))\n {\n _data.Remove(key);\n _notifications.Add(new Notification(key, Type.Remove, null));\n _clock.AddTimer(0f, 0, NotifiyObservers);\n }\n }\n\n public T Get<T>(string key)\n {\n object result = Get(key);\n if (result == null)\n {\n return default(T);\n }\n return (T)result;\n }\n\n public object Get(string key)\n {\n\t return _data.TryGetValue(key, out var value) ? value : _parentBlackboard?.Get(key);\n }\n\n public bool IsSet(string key)\n {\n return _data.ContainsKey(key) || (_parentBlackboard != null && _parentBlackboard.IsSet(key));\n }\n\n public void AddObserver(string key, System.Action<Type, object> observer)\n {\n List<System.Action<Type, object>> observers = GetObserverList(_observers, key);\n if (!_isNotifiyng)\n {\n if (!observers.Contains(observer))\n {\n observers.Add(observer);\n }\n }\n else\n {\n if (!observers.Contains(observer))\n {\n List<System.Action<Type, object>> addObservers = GetObserverList(_addObservers, key);\n if (!addObservers.Contains(observer))\n {\n addObservers.Add(observer);\n }\n }\n\n List<System.Action<Type, object>> removeObservers = GetObserverList(_removeObservers, key);\n if (removeObservers.Contains(observer))\n {\n removeObservers.Remove(observer);\n }\n }\n }\n\n public void RemoveObserver(string key, System.Action<Type, object> observer)\n {\n List<System.Action<Type, object>> observers = GetObserverList(_observers, key);\n if (!_isNotifiyng)\n {\n if (observers.Contains(observer))\n {\n observers.Remove(observer);\n }\n }\n else\n {\n List<System.Action<Type, object>> removeObservers = GetObserverList(_removeObservers, key);\n if (!removeObservers.Contains(observer))\n {\n if (observers.Contains(observer))\n {\n removeObservers.Add(observer);\n }\n }\n\n List<System.Action<Type, object>> addObservers = GetObserverList(_addObservers, key);\n if (addObservers.Contains(observer))\n {\n addObservers.Remove(observer);\n }\n }\n }\n\n\n#if DEBUG\n public List<string> Keys\n {\n get\n {\n if (_parentBlackboard != null)\n {\n List<string> keys = this._parentBlackboard.Keys;\n keys.AddRange(_data.Keys);\n return keys;\n }\n else\n {\n return new List<string>(_data.Keys);\n }\n }\n }\n\n public int NumObservers\n {\n get\n {\n int count = 0;\n foreach (var key in _observers.Keys)\n {\n count += _observers[key].Count;\n }\n return count;\n }\n }\n#endif\n\n\n private void NotifiyObservers()\n {\n if (_notifications.Count == 0)\n {\n return;\n }\n\n _notificationsDispatch.Clear();\n _notificationsDispatch.AddRange(_notifications);\n foreach (Blackboard child in _children)\n {\n child._notifications.AddRange(_notifications);\n child._clock.AddTimer(0f, 0, child.NotifiyObservers);\n }\n _notifications.Clear();\n\n _isNotifiyng = true;\n foreach (Notification notification in _notificationsDispatch)\n {\n if (!_observers.ContainsKey(notification.Key))\n {\n // Debug.Log(\"1 do not notify for key:\" + notification.key + \" value: \" + notification.value);\n continue;\n }\n\n List<System.Action<Type, object>> observers = GetObserverList(_observers, notification.Key);\n foreach (System.Action<Type, object> observer in observers)\n {\n if (_removeObservers.TryGetValue( notification.Key, out List<System.Action<Type, object>> value ) && value.Contains(observer))\n {\n continue;\n }\n observer(notification.Type, notification.Value);\n }\n }\n\n foreach (string key in _addObservers.Keys)\n {\n GetObserverList(_observers, key).AddRange(_addObservers[key]);\n }\n foreach (string key in _removeObservers.Keys)\n {\n foreach (System.Action<Type, object> action in _removeObservers[key])\n {\n GetObserverList(_observers, key).Remove(action);\n }\n }\n _addObservers.Clear();\n _removeObservers.Clear();\n\n _isNotifiyng = false;\n }\n\n private List<System.Action<Type, object>> GetObserverList(Dictionary<string, List<System.Action<Type, object>>> target, string key)\n {\n List<System.Action<Type, object>> observers;\n if (target.TryGetValue(key, out var value))\n {\n observers = value;\n }\n else\n {\n observers = new List<System.Action<Type, object>>();\n target[key] = observers;\n }\n return observers;\n }\n }\n}\n"
},
{
"Ident": "utopia.npbehavesbox",
"Path": "Code/BehaviorTree/Debugger.cs",
"FileName": "Debugger.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 72229,
"Code": "using System.Collections.Generic;\nusing Sandbox;\n\nnamespace NPBehave\n{\n public class Debugger : Component\n {\n public Root BehaviorTree;\n\n private static Blackboard _customGlobalStats = null;\n public static Blackboard CustomGlobalStats\n {\n get \n {\n if (_customGlobalStats == null)\n {\n _customGlobalStats = SandboxContext.GetSharedBlackboard(\"_GlobalStats\");;\n }\n return _customGlobalStats;\n }\n }\n\n private Blackboard _customStats = null;\n public Blackboard CustomStats\n {\n get \n {\n if (_customStats == null)\n {\n _customStats = new Blackboard(CustomGlobalStats, SandboxContext.GetClock());\n }\n return _customStats;\n }\n }\n\n public void DebugCounterInc(string key)\n {\n if (!CustomStats.IsSet(key))\n {\n CustomStats[key] = 0;\n }\n CustomStats[key] = CustomStats.Get<int>(key) + 1;\n }\n\n public void DebugCounterDec(string key)\n {\n if (!CustomStats.IsSet(key))\n {\n CustomStats[key] = 0;\n }\n CustomStats[key] = CustomStats.Get<int>(key) - 1;\n }\n\n public static void GlobalDebugCounterInc(string key)\n {\n if (!CustomGlobalStats.IsSet(key))\n {\n CustomGlobalStats[key] = 0;\n }\n CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) + 1;\n }\n\n public static void GlobalDebugCounterDec(string key)\n {\n if (!CustomGlobalStats.IsSet(key))\n {\n CustomGlobalStats[key] = 0;\n }\n CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) - 1;\n }\n\n }\n}\n"
}
]
}