using System; using System.Collections.Generic; using System.Threading; using System.Windows.Forms; using MrWu.Debug; namespace GlobalSever.FSM { /// /// 状态机 /// public class FSM where T : class { /// /// 所有状态 /// private readonly Dictionary> m_States = new Dictionary>(); /// /// 状态切换事件 /// public Action, FSMState> OnStateChanged; /// /// 状态准备切换事件 (延时的情况,还没有真正切换) /// public Action, FSMState> OnStatePreChanged; /// /// 状态机持有者 /// public T Owner { get; private set; } /// /// 是否正在运行 /// public bool IsRunning => CurrentState != null; /// /// 有限状态机是否被销毁 /// public bool IsDestroyed { get; private set; } /// /// 状态机内存 /// public FSMMem Mem { get; private set; } /// /// 上一个状态 /// public FSMState LastState { get; private set; } /// /// 当前状态机的状态 /// public FSMState CurrentState { get; private set; } /// /// 开启状态 /// public FSMState StartState { get; private set; } /// /// 结束状态 /// public FSMState EndState { get; private set; } public static FSM Create(T owner, FSMMem mem, params FSMState[] states) { if (owner == null) { throw new Exception("FSM owner is invalid."); } if (states == null || states.Length < 1) { throw new Exception("FSM states is invalid."); } FSM fsm = new FSM(); fsm.Mem = mem; fsm.Owner = owner; fsm.IsDestroyed = false; for (int i = 0; i < states.Length; i++) { FSMState state = states[i]; if (state == null) { throw new Exception("FSM states is invalid."); } Type stateType = state.StateType; if (fsm.m_States.ContainsKey(stateType)) { throw new Exception($"FSM state '{stateType}' is already exist."); } fsm.m_States.Add(stateType, state); if (i + 1 < states.Length) state.NextState = states[i + 1]; if (i - 1 >= 0) state.LastState = states[i - 1]; if (i == 0) fsm.StartState = state; if (i == states.Length - 1) fsm.EndState = state; state.OnInit(fsm); } return fsm; } /// /// 创建有限状态机 /// /// /// public static FSM Create(T owner, params FSMState[] states) { return Create(owner, new FSMMem(), states); } /// /// 创建独立的状态机 /// public void CreateSingle(FSMState state) { if (state == null) { throw new Exception("FSM states is invalid."); } Type stateType = state.StateType; if (m_States.ContainsKey(stateType)) { throw new Exception($"FSM state '{stateType}' is already exist."); } m_States.Add(stateType, state); state.OnInit(this); } /// /// 清理有限状态机 /// public void Clear() { Stop(); foreach (KeyValuePair> state in m_States) { state.Value.OnDestroy(this); } Owner = null; m_States.Clear(); IsDestroyed = true; } /// /// 默认从起始节点开始 /// public void Start() { Start(StartState.StateType); } /// /// 从某个节点恢复 /// public void Recover(int stateId) { foreach (var state in m_States) { if (state.Value.StateId == stateId) { Start(state.Key); break; } } } /// /// 通过内存恢复状态机 /// public void Recover() { var state = GetState(Mem.NowStateId); Mem.NowStateType = state.StateType; Debug.Info($"[FSM] Recover Success. State = {Mem.NowStateType} Id = {Mem.NowStateId}"); ReallyChangeState(Mem.NowStateType); } /// /// 开始有限状态机 /// /// public void Start() where TState : FSMState { Start(typeof(TState)); } /// /// 开始有限状态机 /// /// /// public void Start(Type stateType) { if (IsRunning) { throw new Exception("FSM is running, can not start again."); } if (stateType == null) { throw new Exception("State type is invalid."); } if (!typeof(FSMState).IsAssignableFrom(stateType)) { throw new Exception($"State type '{stateType}' is invalid."); } Debug.Info($"[FSM] Start Success. State = {stateType}"); ReallyChangeState(stateType); } /// /// 是否存在有限状态机 /// /// /// public bool HasState() where TState : FSMState { return m_States.ContainsKey(typeof(TState)); } /// /// 是否存在有限状态机 /// /// /// public bool HasState(Type stateType) { if (stateType == null) { throw new Exception("State type is invalid."); } if (!typeof(FSMState).IsAssignableFrom(stateType)) { throw new Exception($"State type '{stateType}' is invalid."); } 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 Exception("State type is invalid."); } if (!typeof(FSMState).IsAssignableFrom(stateType)) { throw new Exception($"State type '{stateType}' is invalid."); } FSMState state = null; if (m_States.TryGetValue(stateType,out state)) { return state; } return null; } public FSMState GetState(int stateId) { foreach (var s in m_States) { if (s.Value.StateId == stateId) return s.Value; } throw new Exception($"State Id '{stateId}' is invalid."); } /// /// 有限状态机更新 /// /// 与上次更新的时间间隔 public void Update(int interval) { //更新持续时间 if (!IsRunning) { return; } Mem.RunDuratime += interval; CurrentState.RunDuratime += interval; CurrentState.Update(this,interval); if (Mem.NeedChange && Mem.RunDuratime - Mem.LastUpdateTime >= Mem.NowChangeDelayTime) { Mem.NowChangeDelayTime = 0; Mem.NeedChange = false; // Debug.Info($"[FSM] Start State = {Mem.NowStateType}"); ReallyChangeState(Mem.NowStateType); } } /// /// 关闭有限状态机 /// public void ShutDown() { Clear(); } public void Stop() { if (CurrentState != null) { CurrentState.OnLeave(this); } CurrentState = null; Mem.NowStateId = -1; Mem.NowStateType = null; Mem.NeedChange = false; } public void ChangeStateImmediate() where K : FSMState { Mem.NowStateType = typeof(K); Mem.NeedChange = false; ReallyChangeState(Mem.NowStateType); Debug.Info($"[FSM] Change State Immediate = {Mem.NowStateType}"); } public void ChangeState() where K : FSMState { ChangeState(typeof(K)); } /// /// 切换当前有限状态机状态 /// /// 目标状态 public void ChangeState(Type stateType, int delayTime = 0) { if (!IsRunning) { throw new Exception("Current state is invalid."); } Debug.Info($"[FSM] Change State = {stateType} Delay = {delayTime}"); Mem.NowStateType = stateType; Mem.NowStateId = GetState(stateType).StateId; Mem.NeedChange = true; Mem.NowChangeDelayTime = delayTime; Mem.LastUpdateTime = Mem.RunDuratime; } void ReallyChangeState(Type stateType) { FSMState state = GetState(stateType); if (state == null) { throw new Exception($"FSM can not change state to '{stateType}' which is not exist."); } if (CurrentState != null) { CurrentState.OnLeave(this); LastState = CurrentState; } CurrentState = state; Mem.NowStateId = CurrentState.StateId; Mem.NowStateType = CurrentState.StateType; OnStateChanged?.Invoke(this, CurrentState); CurrentState.OnEnter(this); } } }