//------------------------------------------------------------
// 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);
}
}
}