# P0-2: GameFlow 需求详细文档 ## 对齐说明 本文档以 `docs/requirements/p0-requirements-set.md` 为准。GameFlow 是全局生命周期所有者,负责创建 Feature scope、FeatureContext,并编排 Feature 的进入、切换和关闭。 ## 目标 提供游戏启动、Feature 切换和关闭流程的编排器,保证生命周期顺序、失败清理、取消和非法状态防护。 ## 状态机 ```csharp public enum GameFlowState { Idle, Starting, Running, Switching, NoActiveFeature, ShuttingDown, Disposed } ``` 状态转换: ```text Idle -> Starting -> Running <-> Switching \-> NoActiveFeature Running -> ShuttingDown -> Disposed NoActiveFeature -> Switching -> Running NoActiveFeature -> ShuttingDown -> Disposed ``` 非法状态调用抛 `InvalidOperationException`,错误必须包含当前状态和操作名。 ## 接口 ```csharp public sealed class GameFlow { public GameFlowState State { get; } public Task StartupAsync( Container root, CancellationToken cancellationToken) where TInitialFeature : IFeature; public Task SwitchToAsync( CancellationToken cancellationToken) where TFeature : IFeature; public Task ShutdownAsync(CancellationToken cancellationToken); } ``` ## 启动流程 ```text 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 切换流程 ```text 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`,不排队。 ## 关闭流程 ```text 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 中可拿到同一个取消信号 | ## 依赖关系 ```text GameFlow ├── Container ├── IFeature ├── FeatureContext ├── IConfigProvider ├── ISaveService └── IResourceService ```