using System; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Timing; namespace Content.Server.AI.WorldState { /// /// Basic StateDate, no frills /// public interface IAiState { void Setup(IEntity owner); } public interface IPlanningState { void Reset(); } public interface ICachedState { void CheckCache(); } public interface IStoredState {} /// /// The default class for state values. Also see CachedStateData and PlanningStateData /// /// public abstract class StateData : IAiState { public abstract string Name { get; } protected IEntity Owner { get; private set; } = default!; public void Setup(IEntity owner) { Owner = owner; } public abstract T? GetValue(); } /// /// For when we want to set StateData but not reset it when re-planning actions /// Useful for group blackboard sharing or to avoid repeating the same action (e.g. bark phrases). /// /// public abstract class StoredStateData : IAiState, IStoredState { // Probably not the best class name but couldn't think of anything better public abstract string Name { get; } private IEntity? Owner { get; set; } private T? _value; public void Setup(IEntity owner) { Owner = owner; } public virtual void SetValue(T? value) { _value = value; } public T? GetValue() { return _value; } } /// /// This is state data that is transient and forgotten every time we re-plan /// e.g. "Current Target" gets updated for every action we consider /// /// public abstract class PlanningStateData : IAiState, IPlanningState { public abstract string Name { get; } protected IEntity? Owner { get; private set; } protected T? Value; public void Setup(IEntity owner) { Owner = owner; } public abstract void Reset(); public T? GetValue() { return Value; } public virtual void SetValue(T? value) { Value = value; } } /// /// This is state data that is cached for n seconds before being discarded. /// Mostly useful to get nearby components and store the value. /// /// public abstract class CachedStateData : IAiState, ICachedState { public abstract string Name { get; } protected IEntity Owner { get; private set; } = default!; private bool _cached; protected T Value = default!; private TimeSpan _lastCache = TimeSpan.Zero; /// /// How long something stays in the cache before new values are retrieved /// protected double CacheTime { get; set; } = 2.0f; public void Setup(IEntity owner) { Owner = owner; } public void CheckCache() { var curTime = IoCManager.Resolve().CurTime; if (!_cached || (curTime - _lastCache).TotalSeconds >= CacheTime) { _cached = false; return; } _cached = true; } /// /// When the cache is stale we'll retrieve the actual value and store it again /// protected abstract T GetTrueValue(); public T GetValue() { CheckCache(); if (!_cached) { Value = GetTrueValue(); _cached = true; _lastCache = IoCManager.Resolve().CurTime; } return Value; } } }