//------------------------------------------------------------ // Game Framework // Copyright © 2013-2021 loyalsoft. All rights reserved. // Homepage: http://www.game7000.com/ // Feedback: http://www.game7000.com/ //------------------------------------------------------------ using System; using System.Collections.Generic; namespace GameFramework.Fsm { /// /// 有限状态机。 /// /// 有限状态机持有者类型。 internal sealed class Fsm : FsmBase, IReference, IFsm where T : class { private T m_Owner; private readonly Dictionary> m_States; private Dictionary m_Datas; private FsmState m_CurrentState; private float m_CurrentStateTime; private bool m_IsDestroyed; /// /// 初始化有限状态机的新实例。 /// public Fsm() { m_Owner = null; m_States = new Dictionary>(); m_Datas = null; m_CurrentState = null; m_CurrentStateTime = 0f; m_IsDestroyed = true; } /// /// 获取有限状态机持有者。 /// public T Owner { get { return m_Owner; } } /// /// 获取有限状态机持有者类型。 /// public override Type OwnerType { get { return typeof(T); } } /// /// 获取有限状态机中状态的数量。 /// public override int FsmStateCount { get { return m_States.Count; } } /// /// 获取有限状态机是否正在运行。 /// public override bool IsRunning { get { return m_CurrentState != null; } } /// /// 获取有限状态机是否被销毁。 /// public override bool IsDestroyed { get { return m_IsDestroyed; } } /// /// 获取当前有限状态机状态。 /// public FsmState CurrentState { get { return m_CurrentState; } } /// /// 获取当前有限状态机状态名称。 /// public override string CurrentStateName { get { return m_CurrentState != null ? m_CurrentState.GetType().FullName : null; } } /// /// 获取当前有限状态机状态持续时间。 /// public override float CurrentStateTime { get { return m_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 = ReferencePool.Acquire>(); fsm.Name = name; fsm.m_Owner = owner; fsm.m_IsDestroyed = false; foreach (FsmState state in states) { if (state == null) { throw new GameFrameworkException("FSM states is invalid."); } Type stateType = state.GetType(); if (fsm.m_States.ContainsKey(stateType)) { throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' state '{1}' is already exist.", new TypeNamePair(typeof(T), name), stateType.FullName)); } fsm.m_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 = ReferencePool.Acquire>(); fsm.Name = name; fsm.m_Owner = owner; fsm.m_IsDestroyed = false; foreach (FsmState state in states) { if (state == null) { throw new GameFrameworkException("FSM states is invalid."); } Type stateType = state.GetType(); if (fsm.m_States.ContainsKey(stateType)) { throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' state '{1}' is already exist.", new TypeNamePair(typeof(T), name), stateType.FullName)); } fsm.m_States.Add(stateType, state); state.OnInit(fsm); } return fsm; } /// /// 清理有限状态机。 /// public void Clear() { if (m_CurrentState != null) { m_CurrentState.OnLeave(this, true); } foreach (KeyValuePair> state in m_States) { state.Value.OnDestroy(this); } Name = null; m_Owner = null; m_States.Clear(); if (m_Datas != null) { foreach (KeyValuePair data in m_Datas) { if (data.Value == null) { continue; } ReferencePool.Release(data.Value); } m_Datas.Clear(); } m_CurrentState = null; m_CurrentStateTime = 0f; m_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)); } m_CurrentStateTime = 0f; m_CurrentState = state; m_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)); } m_CurrentStateTime = 0f; m_CurrentState = state; m_CurrentState.OnEnter(this); } /// /// 是否存在有限状态机状态。 /// /// 要检查的有限状态机状态类型。 /// 是否存在有限状态机状态。 public bool HasState() where TState : FsmState { return m_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 m_States.ContainsKey(stateType); } /// /// 获取有限状态机状态。 /// /// 要获取的有限状态机状态类型。 /// 要获取的有限状态机状态。 public TState GetState() where TState : FsmState { FsmState state = null; if (m_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 (m_States.TryGetValue(stateType, out state)) { return state; } return null; } /// /// 获取有限状态机的所有状态。 /// /// 有限状态机的所有状态。 public FsmState[] GetAllStates() { int index = 0; FsmState[] results = new FsmState[m_States.Count]; foreach (KeyValuePair> state in m_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 m_States) { results.Add(state.Value); } } /// /// 是否存在有限状态机数据。 /// /// 有限状态机数据名称。 /// 有限状态机数据是否存在。 public bool HasData(string name) { if (string.IsNullOrEmpty(name)) { throw new GameFrameworkException("Data name is invalid."); } if (m_Datas == null) { return false; } return m_Datas.ContainsKey(name); } /// /// 获取有限状态机数据。 /// /// 要获取的有限状态机数据的类型。 /// 有限状态机数据名称。 /// 要获取的有限状态机数据。 public TData GetData(string name) where TData : Variable { return (TData)GetData(name); } /// /// 获取有限状态机数据。 /// /// 有限状态机数据名称。 /// 要获取的有限状态机数据。 public Variable GetData(string name) { if (string.IsNullOrEmpty(name)) { throw new GameFrameworkException("Data name is invalid."); } if (m_Datas == null) { return null; } Variable data = null; if (m_Datas.TryGetValue(name, out data)) { return data; } return null; } /// /// 设置有限状态机数据。 /// /// 要设置的有限状态机数据的类型。 /// 有限状态机数据名称。 /// 要设置的有限状态机数据。 public void SetData(string name, TData data) where TData : Variable { SetData(name, (Variable)data); } /// /// 设置有限状态机数据。 /// /// 有限状态机数据名称。 /// 要设置的有限状态机数据。 public void SetData(string name, Variable data) { if (string.IsNullOrEmpty(name)) { throw new GameFrameworkException("Data name is invalid."); } if (m_Datas == null) { m_Datas = new Dictionary(StringComparer.Ordinal); } Variable oldData = GetData(name); if (oldData != null) { ReferencePool.Release(oldData); } m_Datas[name] = data; } /// /// 移除有限状态机数据。 /// /// 有限状态机数据名称。 /// 是否移除有限状态机数据成功。 public bool RemoveData(string name) { if (string.IsNullOrEmpty(name)) { throw new GameFrameworkException("Data name is invalid."); } if (m_Datas == null) { return false; } Variable oldData = GetData(name); if (oldData != null) { ReferencePool.Release(oldData); } return m_Datas.Remove(name); } /// /// 有限状态机轮询。 /// /// 逻辑流逝时间,以秒为单位。 /// 真实流逝时间,以秒为单位。 internal override void Update(float elapseSeconds, float realElapseSeconds) { if (m_CurrentState == null) { return; } m_CurrentStateTime += elapseSeconds; m_CurrentState.OnUpdate(this, elapseSeconds, realElapseSeconds); } /// /// 关闭并清理有限状态机。 /// internal override void Shutdown() { ReferencePool.Release(this); } /// /// 切换当前有限状态机状态。 /// /// 要切换到的有限状态机状态类型。 internal void ChangeState() where TState : FsmState { ChangeState(typeof(TState)); } /// /// 切换当前有限状态机状态。 /// /// 要切换到的有限状态机状态类型。 internal void ChangeState(Type stateType) { if (m_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)); } m_CurrentState.OnLeave(this, false); m_CurrentStateTime = 0f; m_CurrentState = state; m_CurrentState.OnEnter(this); } } }