4.4 KiB
4.4 KiB
P0-2: GameFlow 需求详细文档
对齐说明
本文档以 docs/requirements/p0-requirements-set.md 为准。GameFlow 是全局生命周期所有者,负责创建 Feature scope、FeatureContext,并编排 Feature 的进入、切换和关闭。
目标
提供游戏启动、Feature 切换和关闭流程的编排器,保证生命周期顺序、失败清理、取消和非法状态防护。
状态机
public enum GameFlowState
{
Idle,
Starting,
Running,
Switching,
NoActiveFeature,
ShuttingDown,
Disposed
}
状态转换:
Idle -> Starting -> Running <-> Switching
\-> NoActiveFeature
Running -> ShuttingDown -> Disposed
NoActiveFeature -> Switching -> Running
NoActiveFeature -> ShuttingDown -> Disposed
非法状态调用抛 InvalidOperationException,错误必须包含当前状态和操作名。
接口
public sealed class GameFlow
{
public GameFlowState State { get; }
public Task StartupAsync<TInitialFeature>(
Container root,
CancellationToken cancellationToken)
where TInitialFeature : IFeature;
public Task SwitchToAsync<TFeature>(
CancellationToken cancellationToken)
where TFeature : IFeature;
public Task ShutdownAsync(CancellationToken cancellationToken);
}
启动流程
StartupAsync:
1. State = Starting
2. Resolve IConfigProvider
3. await config.LoadAllAsync(ct)
4. Resolve ISaveService
5. 加载或创建 P0 Sample 所需 Data
6. 注册 Data 到 root Container
7. 创建 TInitialFeature
8. 创建 Feature scope
9. 创建 FeatureContext
10. await feature.LoadAsync(context)
11. await feature.EnterAsync(context)
12. State = Running
失败规则:
- 配置加载失败:清理已创建对象,State 回到 Idle,抛异常。
- 存档加载失败:使用默认 Data,记录警告,继续启动。
- Feature Load/Enter 失败:调用 Dispose 清理,State 回到 Idle,抛异常。
Feature 切换流程
SwitchToAsync:
1. State = Switching
2. await current.ExitAsync(currentContext)
3. current.Dispose()
4. Dispose current FeatureContext / scope / resources
5. 创建新 Feature、scope、FeatureContext
6. await next.LoadAsync(nextContext)
7. await next.EnterAsync(nextContext)
8. State = Running
失败规则:
- 旧 Feature
ExitAsync失败:记录错误,继续 Dispose。 - 旧 Feature
Dispose失败:记录错误,继续创建新 Feature。 - 新 Feature
LoadAsync失败:清理新 Feature,State = NoActiveFeature,抛异常。 - 新 Feature
EnterAsync失败:调用新 Feature Dispose,State = NoActiveFeature,抛异常。 - 切换期间再次调用
SwitchToAsync:P0 抛InvalidOperationException,不排队。
关闭流程
ShutdownAsync:
1. State = ShuttingDown
2. best-effort 调用当前 Feature ExitAsync
3. best-effort 调用当前 Feature Dispose
4. best-effort 保存必要 Data
5. Dispose root Container
6. State = Disposed
规则:
ShutdownAsync一旦进入关闭流程,必须尽量执行到底。- 保存失败记录错误,不阻塞退出。
- Feature 退出/释放失败记录错误,不阻塞退出。
- Container 释放失败记录错误,不阻塞退出。
暂不做
- Feature 栈。
- 并行 Feature。
- Feature 预加载。
- 可配置启动任务列表。
- 切换请求队列。
- Starting/Switching 中断式 Shutdown。
验收标准
| # | 标准 | 通过条件 |
|---|---|---|
| 1 | 正常启动 | Startup 完成后 State == Running,初始 Feature 已 Load + Enter |
| 2 | 启动配置失败 | State 回到 Idle,异常向上传播 |
| 3 | 启动存档失败 | 使用默认 Data,记录警告,继续启动 |
| 4 | 正常切换 | 旧 Feature 已 Exit/Dispose,新 Feature 已 Load/Enter |
| 5 | 新 Feature Load 失败 | State == NoActiveFeature,已清理新 Feature |
| 6 | 新 Feature Enter 失败 | State == NoActiveFeature,已 Dispose 新 Feature |
| 7 | 关闭 best-effort | 保存或释放失败时仍进入 Disposed |
| 8 | 非法状态防护 | 非法调用抛异常并包含当前状态 |
| 9 | CancellationToken 传递 | FeatureContext 中可拿到同一个取消信号 |
依赖关系
GameFlow
├── Container
├── IFeature
├── FeatureContext
├── IConfigProvider
├── ISaveService
└── IResourceService