117 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## ADDED Requirements
### Requirement: Protobuf 协议定义文件
所有客户端-服务端 Hero/Bag/Equipment 消息 MUST 在新的 proto 文件中定义,存放路径 `Packages/cn.etetet.<新业务包>/Proto/<Module>Outer_C_<startId>.proto`。MUST 遵循 ET 框架已有命名规则:消息名 `C2G_xxx` 表示客户端→Gate`G2C_xxx` 表示 Gate→客户端`xxx_yyy` 表示推送消息(无 RpcId
#### Scenario: 协议文件结构
- **WHEN** 创建 `HeroOuter_C_3000.proto` 文件
- **THEN** 文件头部 MUST 声明 `syntax = "proto3"``package ET`
- **AND** 注释每个消息的 `ResponseType` 用于 ET Proto2CS 工具识别
- **AND** 该文件起始消息 ID = 3000每个 message 顺序 +1
### Requirement: 数据传输对象 (DTO)
协议层 MUST 定义以下核心 DTO 结构供 RPC 和推送使用:
- `HeroInfo`: heroId (int64), configId (int32), level, exp, star, starExp, talentIndex, skills (repeated SkillInfo), talentTrees (repeated TalentTreeInfo), equipSlots (repeated EquipSlot)
- `SkillInfo`: skillId (int32), skillLevel (int32)
- `TalentTreeInfo`: pageIndex (int32), name (string), nodes (repeated TalentNodeInfo)
- `TalentNodeInfo`: nodeId (int32), level (int32)
- `EquipSlot`: subType (int32), itemIndex (int64, 0 表示空)
- `ItemInfo`: itemIndex (int64), itemId (int32), count (int64), itemType (int32), heroId (int64)
#### Scenario: 序列化 HeroInfo
- **WHEN** 服务端构造 HeroInfo 并通过 `MessageHelper.SendToClient` 发送
- **THEN** ET 框架自动使用 MemoryPack 序列化
- **AND** 客户端反序列化得到等价 HeroInfo 实例
### Requirement: 客户端→服务端 RPC 消息
协议层 MUST 包含以下 12 个 Hero/Equipment 业务 RPC每个有 `ResponseType` 声明):
| RPC 名 | 说明 |
|---|---|
| C2G_SummonHero | 召唤英雄 |
| C2G_HeroAddExp | 加经验升级 |
| C2G_HeroStarUp | 升星 |
| C2G_HeroSkillUp | 技能升级 |
| C2G_HeroAwake | 觉醒 |
| C2G_TalentUp | 学天赋 |
| C2G_ChangeTalentIndex | 切换天赋页 |
| C2G_ResetTalent | 重置天赋页 |
| C2G_ModifyTalentName | 修改天赋页名 |
| C2G_HeroWearEquip | 穿装备 |
| C2G_TakeOffEquip | 卸装备 |
| C2G_ExchangeHeroItem | 雕像兑换碎片 |
Bag/Equipment 业务额外 RPC
| RPC 名 | 说明 |
|---|---|
| C2G_UseItem | 使用道具 |
| C2G_MakeEquipment | 锻造装备 |
| C2G_ResolveEquipment | 分解装备 |
| C2G_MixMaterial | 合成材料 |
#### Scenario: 每个 RPC 都有错误码字段
- **WHEN** 定义任一 `G2C_xxx` Response
- **THEN** MUST 包含 `int32 Error``string Message` 字段
- **AND** Error 0 = 成功,非 0 = 失败码
### Requirement: 服务端→客户端推送消息
协议层 MUST 包含以下推送消息(无 RpcId、不需要回应
- `Hero_HeroInfo { HeroInfo hero }` - 单个英雄数据变化
- `Hero_HeroInfoList { repeated HeroInfo heroes }` - 全量英雄列表(登录后)
- `Item_ItemInfo { ItemInfo item }` - 单个道具数量变化
- `Item_ItemInfoList { repeated ItemInfo items }` - 全量道具列表(登录后)
- `Item_RemoveItem { int64 itemIndex }` - 道具被完全移除
#### Scenario: 登录后全量同步
- **WHEN** 玩家通过 `C2G_LoginGate` 登录到 Gate 成功
- **THEN** 服务端 MUST 在 200ms 内推送 `Hero_HeroInfoList``Item_ItemInfoList`
- **AND** 客户端按顺序更新两个 Component 缓存
#### Scenario: 业务操作后增量推送
- **WHEN** 服务端处理任意 Hero/Bag 业务请求成功后
- **THEN** MUST 在响应中或之后立刻推送相关 `Hero_HeroInfo` / `Item_ItemInfo`
- **AND** 推送的数据是该操作影响的完整快照(不是 delta diff
### Requirement: 错误码统一定义
所有 Hero/Bag/Equipment 错误码 MUST 在 `Packages/cn.etetet.login/Scripts/Model/Share/ErrorCode.cs` 或新增 `HeroBagErrorCode.cs` 中集中定义为 `public const int xxx`。命名规则:`ERR_<Module>_<Reason>`
#### Scenario: 错误码示例
- **WHEN** 服务端拒绝因碎片不足的招募请求
- **THEN** 返回 `error = ERR_HERO_ITEM_NOT_ENOUGH`
- **AND** 客户端按错误码查表显示本地化文案
### Requirement: 消息 ID 分配
新协议 MUST 占用尚未使用的消息 ID 段(避开 1000 Login / 1100 Router / 11001 StateSync 等已用段)。建议使用 3000-3999 段。
#### Scenario: ID 段不冲突
- **WHEN** 通过 `ET/Proto/Proto2CS` 工具生成代码
- **THEN** 工具 MUST 检查 ID 不与现有 proto 冲突
- **AND** 若冲突则编译失败并提示
### Requirement: 协议代码生成
新增 proto 文件后 MUST 通过 ET 工具菜单 `ET/Proto/Proto2CS` 生成 C# 代码到 `Packages/cn.etetet.proto/CodeMode/Model/{Client|Server|ClientServer}/<Module>Outer_C_<startId>.cs`。生成的代码 MUST 自动注册到 ET 的 MessageDispatcher。
#### Scenario: 重新生成不破坏现有代码
- **WHEN** 修改 proto 文件后再次运行 Proto2CS
- **THEN** 工具 MUST 完全覆盖旧的生成 .cs 文件
- **AND** 不影响业务 Handler 代码Handler 是手写的)
### Requirement: Handler 注册
所有 RPC 消息 MUST 有对应的服务端 Handler 类,命名规则 `C2G_<Name>Handler`,挂 `[MessageHandler(SceneType.Gate)]` 特性。Handler 类 MUST 实现 `MessageSessionHandler<C2G_xxx, G2C_xxx>` 模板。
#### Scenario: 消息路由
- **WHEN** 客户端发送 `C2G_SummonHero`
- **THEN** Gate Scene 的 MessageDispatcher 路由到 `C2G_SummonHeroHandler.Run()`
- **AND** Handler 通过 `session.GetComponent<SessionPlayerComponent>().Player` 获取玩家
- **AND** 修改业务后返回 Response