From c0274074b34ff74cb6744d9a8db13d6b2c60cfe0 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 15 Jan 2026 23:04:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(state):=20=E6=B7=BB=E5=8A=A0=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=9C=BA=E7=B3=BB=E7=BB=9F=E6=A0=B8=E5=BF=83=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现了基础状态机StateMachine类,支持状态注册、切换和生命周期管理 - 创建了上下文感知状态机ContextAwareStateMachine,能够感知架构上下文并发送状态变更事件 - 定义了IState和IStateMachine抽象接口,规范状态和状态机的行为契约 - 添加了StateChangedEvent事件类,用于通知状态变更 - 实现了游戏专用状态机GameStateMachine,提供类型安全的状态检查和获取功能 --- GFramework.Core.Abstractions/state/IState.cs | 26 ++++++ .../state/IStateMachine.cs | 37 ++++++++ .../state/ContextAwareStateMachine.cs | 82 +++++++++++++++++ GFramework.Core/state/StateChangedEvent.cs | 19 ++++ GFramework.Core/state/StateMachine.cs | 87 +++++++++++++++++++ GFramework.Game/state/GameStateMachine.cs | 26 ++++++ 6 files changed, 277 insertions(+) create mode 100644 GFramework.Core.Abstractions/state/IState.cs create mode 100644 GFramework.Core.Abstractions/state/IStateMachine.cs create mode 100644 GFramework.Core/state/ContextAwareStateMachine.cs create mode 100644 GFramework.Core/state/StateChangedEvent.cs create mode 100644 GFramework.Core/state/StateMachine.cs create mode 100644 GFramework.Game/state/GameStateMachine.cs diff --git a/GFramework.Core.Abstractions/state/IState.cs b/GFramework.Core.Abstractions/state/IState.cs new file mode 100644 index 0000000..8159804 --- /dev/null +++ b/GFramework.Core.Abstractions/state/IState.cs @@ -0,0 +1,26 @@ +namespace GFramework.Core.Abstractions.state; + +/// +/// 状态机状态接口,定义了状态的基本行为和转换规则 +/// +public interface IState +{ + /// + /// 当状态被激活进入时调用 + /// + /// 从哪个状态转换而来,可能为null表示初始状态 + void OnEnter(IState? from); + + /// + /// 当状态退出时调用 + /// + /// 将要转换到的目标状态,可能为null表示结束状态 + void OnExit(IState? to); + + /// + /// 判断当前状态是否可以转换到目标状态 + /// + /// 目标状态 + /// 如果可以转换则返回true,否则返回false + bool CanTransitionTo(IState target); +} \ No newline at end of file diff --git a/GFramework.Core.Abstractions/state/IStateMachine.cs b/GFramework.Core.Abstractions/state/IStateMachine.cs new file mode 100644 index 0000000..f0b6d61 --- /dev/null +++ b/GFramework.Core.Abstractions/state/IStateMachine.cs @@ -0,0 +1,37 @@ +namespace GFramework.Core.Abstractions.state; + +/// +/// 状态机接口,用于管理状态的注册、切换和验证 +/// +public interface IStateMachine +{ + /// + /// 获取当前激活的状态 + /// + IState? Current { get; } + + /// + /// 注册一个状态到状态机中 + /// + /// 要注册的状态实例 + void Register(IState state); + + /// + /// 从状态机中注销指定类型的状态 + /// + /// 要注销的状态类型,必须实现IState接口 + void Unregister() where T : IState; + + /// + /// 检查是否可以切换到指定类型的状态 + /// + /// 目标状态类型,必须实现IState接口 + /// 如果可以切换则返回true,否则返回false + bool CanChangeTo() where T : IState; + + /// + /// 切换到指定类型的状态 + /// + /// 要切换到的状态类型,必须实现IState接口 + void ChangeTo() where T : IState; +} \ No newline at end of file diff --git a/GFramework.Core/state/ContextAwareStateMachine.cs b/GFramework.Core/state/ContextAwareStateMachine.cs new file mode 100644 index 0000000..606cc0b --- /dev/null +++ b/GFramework.Core/state/ContextAwareStateMachine.cs @@ -0,0 +1,82 @@ +using GFramework.Core.Abstractions.architecture; +using GFramework.Core.Abstractions.enums; +using GFramework.Core.Abstractions.rule; +using GFramework.Core.Abstractions.state; +using GFramework.Core.Abstractions.system; +using GFramework.Core.extensions; + +namespace GFramework.Core.state; + +/// +/// 上下文感知状态机,继承自StateMachine并实现ISystem接口 +/// 该状态机能够感知架构上下文,并在状态切换时发送状态变更事件 +/// +public class ContextAwareStateMachine : StateMachine, ISystem +{ + /// + /// 架构上下文对象,用于提供系统运行所需的上下文信息 + /// + protected IArchitectureContext Context = null!; + + /// + /// 设置架构上下文的方法 + /// + /// 要设置的架构上下文对象 + public void SetContext(IArchitectureContext context) + { + Context = context; + } + + /// + /// 获取当前架构上下文的方法 + /// + /// 当前的架构上下文对象 + public IArchitectureContext GetContext() + { + return Context; + } + + /// + /// 处理架构生命周期阶段的方法 + /// + /// 当前所处的架构生命周期阶段 + public virtual void OnArchitecturePhase(ArchitecturePhase phase) + { + } + + /// + /// 初始化方法,在系统启动时调用 + /// 遍历所有状态实例,为实现了IContextAware接口的状态设置上下文 + /// + public virtual void Init() + { + foreach (var state in States.Values.OfType()) + { + state.SetContext(Context); + } + } + + /// + /// 销毁方法,在系统关闭时调用 + /// + public virtual void Destroy() + { + } + + /// + /// 内部状态切换方法,重写基类方法以添加状态变更事件通知功能 + /// + /// 要切换到的下一个状态 + protected override void ChangeInternal(IState next) + { + var old = Current; + base.ChangeInternal(next); + + // 发送状态变更事件,通知监听者状态已发生改变 + this.SendEvent(new StateChangedEvent + { + OldState = old, + NewState = Current + }); + } +} \ No newline at end of file diff --git a/GFramework.Core/state/StateChangedEvent.cs b/GFramework.Core/state/StateChangedEvent.cs new file mode 100644 index 0000000..3918874 --- /dev/null +++ b/GFramework.Core/state/StateChangedEvent.cs @@ -0,0 +1,19 @@ +using GFramework.Core.Abstractions.state; + +namespace GFramework.Core.state; + +/// +/// 表示状态变更事件的数据类 +/// +public sealed class StateChangedEvent +{ + /// + /// 获取变更前的旧状态 + /// + public IState? OldState { get; init; } + + /// + /// 获取变更后的新状态 + /// + public IState? NewState { get; init; } +} \ No newline at end of file diff --git a/GFramework.Core/state/StateMachine.cs b/GFramework.Core/state/StateMachine.cs new file mode 100644 index 0000000..c845340 --- /dev/null +++ b/GFramework.Core/state/StateMachine.cs @@ -0,0 +1,87 @@ +using GFramework.Core.Abstractions.state; + +namespace GFramework.Core.state; + +/// +/// 状态机实现类,用于管理状态的注册、切换和生命周期 +/// +public class StateMachine : IStateMachine +{ + /// + /// 存储所有已注册状态的字典,键为状态类型,值为状态实例 + /// + protected readonly Dictionary States = new(); + + /// + /// 获取当前激活的状态 + /// + public IState? Current { get; private set; } + + /// + /// 注册一个状态到状态机中 + /// + /// 要注册的状态实例 + public void Register(IState state) + => States[state.GetType()] = state; + + /// + /// 从状态机中注销指定类型的状态 + /// + /// 要注销的状态类型 + public void Unregister() where T : IState + { + var type = typeof(T); + if (!States.TryGetValue(type, out var state)) return; + + // 如果当前状态是要注销的状态,则先执行退出逻辑 + if (Current == state) + { + Current.OnExit(null); + Current = null; + } + + States.Remove(type); + } + + /// + /// 检查是否可以切换到指定类型的状态 + /// + /// 目标状态类型 + /// 如果可以切换则返回true,否则返回false + public bool CanChangeTo() where T : IState + { + if (!States.TryGetValue(typeof(T), out var target)) + return false; + + return Current?.CanTransitionTo(target) ?? true; + } + + /// + /// 切换到指定类型的状态 + /// + /// 目标状态类型 + /// 当目标状态未注册时抛出 + public void ChangeTo() where T : IState + { + if (!States.TryGetValue(typeof(T), out var target)) + throw new InvalidOperationException("State not registered."); + + ChangeInternal(target); + } + + /// + /// 内部状态切换方法,处理状态切换的核心逻辑 + /// + /// 下一个状态实例 + protected virtual void ChangeInternal(IState next) + { + if (Current == next) return; + if (Current != null && !Current.CanTransitionTo(next)) return; + + var old = Current; + old?.OnExit(next); + + Current = next; + Current.OnEnter(old); + } +} \ No newline at end of file diff --git a/GFramework.Game/state/GameStateMachine.cs b/GFramework.Game/state/GameStateMachine.cs new file mode 100644 index 0000000..64298e7 --- /dev/null +++ b/GFramework.Game/state/GameStateMachine.cs @@ -0,0 +1,26 @@ +using GFramework.Core.Abstractions.state; +using GFramework.Core.state; + +namespace GFramework.Game.state; + +/// +/// 游戏状态机类,继承自ContextAwareStateMachine,用于管理游戏中的各种状态 +/// +public sealed class GameStateMachine : ContextAwareStateMachine +{ + /// + /// 检查当前状态是否为指定类型的状态 + /// + /// 要检查的状态类型,必须实现IState接口 + /// 如果当前状态是指定类型则返回true,否则返回false + public bool IsIn() where T : IState + => Current is T; + + /// + /// 获取当前状态的实例,如果当前状态是指定类型则进行类型转换 + /// + /// 要获取的状态类型,必须是引用类型并实现IState接口 + /// 如果当前状态是指定类型则返回转换后的实例,否则返回null + public T? Get() where T : class, IState + => Current as T; +} \ No newline at end of file