using System;
using System.Collections.Generic;
namespace SK.Framework
{
///
/// 状态机
///
public class StateMachine
{
//状态列表 存储状态机内所有状态
protected readonly List states = new List();
//状态切换条件列表
protected List conditions = new List();
///
/// 状态机名称
///
public string Name { get; set; }
///
/// 当前状态
///
public IState CurrentState { get; protected set; }
///
/// 添加状态
///
/// 状态
/// 添加成功返回true 否则返回false
public bool Add(IState state)
{
//判断是否已经存在
if (!states.Contains(state))
{
//判断是否存在同名状态
if (states.Find(m => m.Name == state.Name) == null)
{
//存储到列表
states.Add(state);
//执行状态初始化事件
state.OnInitialization();
return true;
}
}
return false;
}
///
/// 添加状态
///
/// 状态类型
/// 状态命名
/// 添加成功返回true 否则返回false
public bool Add(string stateName = null) where T : IState, new()
{
Type type = typeof(T);
T t = (T)Activator.CreateInstance(type);
t.Name = string.IsNullOrEmpty(stateName) ? type.Name : stateName;
return Add(t);
}
///
/// 移除状态
///
/// 状态
/// 移除成功返回true 否则返回false
public bool Remove(IState state)
{
//判断是否存在
if (states.Contains(state))
{
//如果要移除的状态为当前状态 首先执行当前状态退出事件
if (CurrentState == state)
{
CurrentState.OnExit();
CurrentState = null;
}
//执行状态终止事件
state.OnTermination();
return states.Remove(state);
}
return false;
}
///
/// 移除状态
///
/// 状态名称
/// 移除成功返回true 否则返回false
public bool Remove(string stateName)
{
var targetIndex = states.FindIndex(m => m.Name == stateName);
if (targetIndex != -1)
{
var targetState = states[targetIndex];
if (CurrentState == targetState)
{
CurrentState.OnExit();
CurrentState = null;
}
targetState.OnTermination();
return states.Remove(targetState);
}
return false;
}
///
/// 移除状态
///
/// 状态类型
/// 移除成返回true 否则返回false
public bool Remove() where T : IState
{
return Remove(typeof(T).Name);
}
///
/// 切换状态
///
/// 状态
/// 切换成功返回true 否则返回false
public bool Switch(IState state)
{
//如果当前状态已经是切换的目标状态 无需切换 返回false
if (CurrentState == state) return false;
//当前状态不为空则执行状态退出事件
CurrentState?.OnExit();
//判断切换的目标状态是否存在于列表中
if (!states.Contains(state)) return false;
//更新当前状态
CurrentState = state;
//更新后 当前状态不为空则执行状态进入事件
CurrentState?.OnEnter();
return true;
}
///
/// 切换状态
///
/// 状态名称
/// 切换成功返回true 否则返回false
public bool Switch(string stateName)
{
//根据状态名称在列表中查询
var targetState = states.Find(m => m.Name == stateName);
return Switch(targetState);
}
///
/// 切换状态
///
/// 状态类型
/// 切换成返回true 否则返回false
public bool Switch() where T : IState
{
return Switch(typeof(T).Name);
}
///
/// 切换至下一状态
///
public void Switch2Next()
{
if (states.Count != 0)
{
//如果当前状态不为空 则根据当前状态找到下一个状态
if (CurrentState != null)
{
int index = states.IndexOf(CurrentState);
//当前状态的索引值+1后若小于列表中的数量 则下一状态的索引为index+1
//否则表示当前状态已经是列表中的最后一个 下一状态则回到列表中的第一个状态 索引为0
index = index + 1 < states.Count ? index + 1 : 0;
IState targetState = states[index];
//首先执行当前状态的退出事件 再更新到下一状态
CurrentState.OnExit();
CurrentState = targetState;
}
//当前状态为空 则直接进入列表中的第一个状态
else
{
CurrentState = states[0];
}
//执行状态进入事件
CurrentState.OnEnter();
}
}
///
/// 切换至上一状态
///
public void Switch2Last()
{
if (states.Count != 0)
{
//如果当前状态不为空 则根据当前状态找到上一个状态
if (CurrentState != null)
{
int index = states.IndexOf(CurrentState);
//当前状态的索引值-1后若大等于0 则下一状态的索引为index-1
//否则表示当前状态是列表中的第一个 上一状态则回到列表中的最后一个状态
index = index - 1 >= 0 ? index - 1 : states.Count - 1;
IState targetState = states[index];
//首先执行当前状态的退出事件 再更新到上一状态
CurrentState.OnExit();
CurrentState = targetState;
}
//当前状态为空 则直接进入列表中的最后一个状态
else
{
CurrentState = states[states.Count - 1];
}
//执行状态进入事件
CurrentState.OnEnter();
}
}
///
/// 切换至空状态(退出当前状态)
///
public void Switch2Null()
{
if (CurrentState != null)
{
CurrentState.OnExit();
CurrentState = null;
}
}
///
/// 获取状态
///
/// 状态类型
/// 状态名称
/// 状态
public T GetState(string stateName) where T : IState
{
return (T)states.Find(m => m.Name == stateName);
}
///
/// 获取状态
///
/// 状态类型
/// 状态
public T GetState() where T : IState
{
return (T)states.Find(m => m.Name == typeof(T).Name);
}
///
/// 销毁状态机
///
public void Destroy()
{
FSM.Instance.Destroy(this);
}
///
/// 状态机刷新事件
///
public void OnUpdate()
{
//若当前状态不为空 执行状态停留事件
CurrentState?.OnStay();
//检测所有状态切换条件
for (int i = 0; i < conditions.Count; i++)
{
var condition = conditions[i];
//条件满足
if (condition.predicate.Invoke())
{
//源状态名称为空 表示从任意状态切换至目标状态
if (string.IsNullOrEmpty(condition.sourceStateName))
{
Switch(condition.targetStateName);
}
//源状态名称不为空 表示从指定状态切换至目标状态
else
{
//首先判断当前的状态是否为指定的状态
if (CurrentState.Name == condition.sourceStateName)
{
Switch(condition.targetStateName);
}
}
}
}
}
///
/// 状态机销毁事件
///
public void OnDestroy()
{
//执行状态机内所有状态的状态终止事件
for (int i = 0; i < states.Count; i++)
{
states[i].OnTermination();
}
}
///
/// 设置状态切换条件
///
/// 切换条件
/// 目标状态名称
/// 状态机
public StateMachine SwitchWhen(Func predicate, string targetStateName)
{
conditions.Add(new StateSwitchCondition(predicate, null, targetStateName));
return this;
}
///
/// 设置状态切换条件
///
/// 切换条件
/// 源状态名称
/// 目标状态名称
///
public StateMachine SwitchWhen(Func predicate, string sourceStateName, string targetStateName)
{
conditions.Add(new StateSwitchCondition(predicate, sourceStateName, targetStateName));
return this;
}
///
/// 构建状态
///
/// 状态类型
/// 状态名称
/// 状态构建器
public StateBuilder Build(string stateName = null) where T : State, new()
{
Type type = typeof(T);
T t = (T)Activator.CreateInstance(type);
t.Name = string.IsNullOrEmpty(stateName) ? type.Name : stateName;
if (states.Find(m => m.Name == t.Name) == null)
{
states.Add(t);
}
return new StateBuilder(t, this);
}
///
/// 创建状态机
///
/// 状态机名称
/// 状态机
public static StateMachine Create(string stateMachineName)
{
return FSM.Instance.Create(stateMachineName);
}
///
/// 创建状态机
///
/// 状态机类型
/// 状态机名称
/// 状态机
public static T Create(string stateMachineName = null) where T : StateMachine, new()
{
return FSM.Instance.Create(stateMachineName);
}
///
/// 销毁状态机
///
/// 状态机名称
/// 销毁成功返回true 否则返回false
public static bool Destroy(string stateMachineName)
{
return FSM.Instance.Destroy(stateMachineName);
}
///
/// 销毁状态机
///
/// 状态机类型
/// 销毁成功返回true 否则返回false
public static bool Destroy() where T : StateMachine
{
return FSM.Instance.Destroy(typeof(T).Name);
}
///
/// 获取状态机
///
/// 状态机名称
/// 状态机
public static StateMachine Get(string stateMachineName)
{
return FSM.Instance.GetMachine(stateMachineName);
}
///
/// 获取状态机
///
/// 状态机类型
/// 状态机名称
/// 状态机
public static T Get(string stateMachineName) where T : StateMachine
{
return FSM.Instance.GetMachine(stateMachineName);
}
///
/// 获取状态机
///
/// 状态机类型
/// 状态机
public static T Get() where T : StateMachine
{
return FSM.Instance.GetMachine(typeof(T).Name);
}
}
}