using System; using System.Collections.Generic; namespace TEngine { /// /// 有限状态机。 /// /// 有限状态机持有者类型。 internal sealed class Fsm : FsmBase, IMemory, IFsm where T : class { private T _owner; private readonly Dictionary> _states; private Dictionary _dataMap; private FsmState _currentState; private float _currentStateTime; private bool _isDestroyed; /// /// 初始化有限状态机的新实例。 /// public Fsm() { _owner = null; _states = new Dictionary>(); _dataMap = null; _currentState = null; _currentStateTime = 0f; _isDestroyed = true; } /// /// 获取有限状态机持有者。 /// public T Owner => _owner; /// /// 获取有限状态机持有者类型。 /// public override Type OwnerType => typeof(T); /// /// 获取有限状态机中状态的数量。 /// public override int FsmStateCount => _states.Count; /// /// 获取有限状态机是否正在运行。 /// public override bool IsRunning => _currentState != null; /// /// 获取有限状态机是否被销毁。 /// public override bool IsDestroyed => _isDestroyed; /// /// 获取当前有限状态机状态。 /// public FsmState CurrentState => _currentState; /// /// 获取当前有限状态机状态名称。 /// public override string CurrentStateName => _currentState?.GetType().FullName; /// /// 获取当前有限状态机状态持续时间。 /// public override float CurrentStateTime => _currentStateTime; /// /// 创建有限状态机。 /// /// 有限状态机名称。 /// 有限状态机持有者。 /// 有限状态机状态集合。 /// 创建的有限状态机。 public static Fsm Create(string name, T owner, params FsmState[] states) { if (owner == null) { throw new GameFrameworkException("FSM owner is invalid."); } if (states == null || states.Length < 1) { throw new GameFrameworkException("FSM states is invalid."); } Fsm fsm = MemoryPool.Acquire>(); fsm.Name = name; fsm._owner = owner; fsm._isDestroyed = false; foreach (FsmState state in states) { if (state == null) { throw new GameFrameworkException("FSM states is invalid."); } Type stateType = state.GetType(); if (fsm._states.ContainsKey(stateType)) { throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' state '{1}' is already exist.", new TypeNamePair(typeof(T), name), stateType.FullName)); } fsm._states.Add(stateType, state); state.OnInit(fsm); } return fsm; } /// /// 创建有限状态机。 /// /// 有限状态机名称。 /// 有限状态机持有者。 /// 有限状态机状态集合。 /// 创建的有限状态机。 public static Fsm Create(string name, T owner, List> states) { if (owner == null) { throw new GameFrameworkException("FSM owner is invalid."); } if (states == null || states.Count < 1) { throw new GameFrameworkException("FSM states is invalid."); } Fsm fsm = MemoryPool.Acquire>(); fsm.Name = name; fsm._owner = owner; fsm._isDestroyed = false; foreach (FsmState state in states) { if (state == null) { throw new GameFrameworkException("FSM states is invalid."); } Type stateType = state.GetType(); if (fsm._states.ContainsKey(stateType)) { throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' state '{1}' is already exist.", new TypeNamePair(typeof(T), name), stateType.FullName)); } fsm._states.Add(stateType, state); state.OnInit(fsm); } return fsm; } /// /// 清理有限状态机。 /// public void Clear() { if (_currentState != null) { _currentState.OnLeave(this, true); } foreach (KeyValuePair> state in _states) { state.Value.OnDestroy(this); } Name = null; _owner = null; _states?.Clear(); _dataMap?.Clear(); _currentState = null; _currentStateTime = 0f; _isDestroyed = true; } /// /// 开始有限状态机。 /// /// 要开始的有限状态机状态类型。 public void Start() where TState : FsmState { if (IsRunning) { throw new GameFrameworkException("FSM is running, can not start again."); } FsmState state = GetState(); if (state == null) { throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' can not start state '{1}' which is not exist.", new TypeNamePair(typeof(T), Name), typeof(TState).FullName)); } _currentStateTime = 0f; _currentState = state; _currentState.OnEnter(this); } /// /// 开始有限状态机。 /// /// 要开始的有限状态机状态类型。 public void Start(Type stateType) { if (IsRunning) { throw new GameFrameworkException("FSM is running, can not start again."); } if (stateType == null) { throw new GameFrameworkException("State type is invalid."); } if (!typeof(FsmState).IsAssignableFrom(stateType)) { throw new GameFrameworkException(Utility.Text.Format("State type '{0}' is invalid.", stateType.FullName)); } FsmState state = GetState(stateType); if (state == null) { throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' can not start state '{1}' which is not exist.", new TypeNamePair(typeof(T), Name), stateType.FullName)); } _currentStateTime = 0f; _currentState = state; _currentState.OnEnter(this); } /// /// 是否存在有限状态机状态。 /// /// 要检查的有限状态机状态类型。 /// 是否存在有限状态机状态。 public bool HasState() where TState : FsmState { return _states.ContainsKey(typeof(TState)); } /// /// 是否存在有限状态机状态。 /// /// 要检查的有限状态机状态类型。 /// 是否存在有限状态机状态。 public bool HasState(Type stateType) { if (stateType == null) { throw new GameFrameworkException("State type is invalid."); } if (!typeof(FsmState).IsAssignableFrom(stateType)) { throw new GameFrameworkException(Utility.Text.Format("State type '{0}' is invalid.", stateType.FullName)); } return _states.ContainsKey(stateType); } /// /// 获取有限状态机状态。 /// /// 要获取的有限状态机状态类型。 /// 要获取的有限状态机状态。 public TState GetState() where TState : FsmState { FsmState state = null; if (_states.TryGetValue(typeof(TState), out state)) { return (TState)state; } return null; } /// /// 获取有限状态机状态。 /// /// 要获取的有限状态机状态类型。 /// 要获取的有限状态机状态。 public FsmState GetState(Type stateType) { if (stateType == null) { throw new GameFrameworkException("State type is invalid."); } if (!typeof(FsmState).IsAssignableFrom(stateType)) { throw new GameFrameworkException(Utility.Text.Format("State type '{0}' is invalid.", stateType.FullName)); } FsmState state = null; if (_states.TryGetValue(stateType, out state)) { return state; } return null; } /// /// 获取有限状态机的所有状态。 /// /// 有限状态机的所有状态。 public FsmState[] GetAllStates() { int index = 0; FsmState[] results = new FsmState[_states.Count]; foreach (KeyValuePair> state in _states) { results[index++] = state.Value; } return results; } /// /// 获取有限状态机的所有状态。 /// /// 有限状态机的所有状态。 public void GetAllStates(List> results) { if (results == null) { throw new GameFrameworkException("Results is invalid."); } results.Clear(); foreach (KeyValuePair> state in _states) { results.Add(state.Value); } } /// /// 是否存在有限状态机数据。 /// /// 有限状态机数据名称。 /// 有限状态机数据是否存在。 public bool HasData(string name) { if (string.IsNullOrEmpty(name)) { throw new GameFrameworkException("Data name is invalid."); } if (_dataMap == null) { return false; } return _dataMap.ContainsKey(name); } /// /// 获取有限状态机数据。 /// /// 要获取的有限状态机数据的类型。 /// 有限状态机数据名称。 /// 要获取的有限状态机数据。 public TData GetData(string name) { return (TData)GetData(name); } /// /// 获取有限状态机数据。 /// /// 有限状态机数据名称。 /// 要获取的有限状态机数据。 public object GetData(string name) { if (string.IsNullOrEmpty(name)) { throw new GameFrameworkException("Data name is invalid."); } if (_dataMap == null) { return null; } if (_dataMap.TryGetValue(name, out var data)) { return data; } return null; } /// /// 设置有限状态机数据。 /// /// 要设置的有限状态机数据的类型。 /// 有限状态机数据名称。 /// 要设置的有限状态机数据。 public void SetData(string name, TData data) { SetData(name, (object)data); } /// /// 设置有限状态机数据。 /// /// 有限状态机数据名称。 /// 要设置的有限状态机数据。 public void SetData(string name, object data) { if (string.IsNullOrEmpty(name)) { throw new GameFrameworkException("Data name is invalid."); } if (_dataMap == null) { _dataMap = new Dictionary(StringComparer.Ordinal); } _dataMap[name] = data; } /// /// 移除有限状态机数据。 /// /// 有限状态机数据名称。 /// 是否移除有限状态机数据成功。 public bool RemoveData(string name) { if (string.IsNullOrEmpty(name)) { throw new GameFrameworkException("Data name is invalid."); } if (_dataMap == null) { return false; } return _dataMap.Remove(name); } /// /// 有限状态机轮询。 /// /// 逻辑流逝时间,以秒为单位。 /// 真实流逝时间,以秒为单位。 internal override void Update(float elapseSeconds, float realElapseSeconds) { if (_currentState == null) { return; } _currentStateTime += elapseSeconds; _currentState.OnUpdate(this, elapseSeconds, realElapseSeconds); } /// /// 关闭并清理有限状态机。 /// internal override void Shutdown() { MemoryPool.Release(this); } /// /// 切换当前有限状态机状态。 /// /// 要切换到的有限状态机状态类型。 internal void ChangeState() where TState : FsmState { ChangeState(typeof(TState)); } /// /// 切换当前有限状态机状态。 /// /// 要切换到的有限状态机状态类型。 internal void ChangeState(Type stateType) { if (_currentState == null) { throw new GameFrameworkException("Current state is invalid."); } FsmState state = GetState(stateType); if (state == null) { throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' can not change state to '{1}' which is not exist.", new TypeNamePair(typeof(T), Name), stateType.FullName)); } _currentState.OnLeave(this, false); _currentStateTime = 0f; _currentState = state; _currentState.OnEnter(this); } } }