Implement 40250 classic client port
This commit is contained in:
+66
-24
@@ -8,10 +8,14 @@
|
||||
> 渲染细节另见 `PARITY-GAP.md`,动画、材质和资产管线另见 `BACKLOG.md`,网络实现另见
|
||||
> `CLIENT-PORT.md`。
|
||||
>
|
||||
> 更新日期:2026-08-31(增量 38)
|
||||
> 更新日期:2026-09-01(增量 45)
|
||||
>
|
||||
> **状态列图例**:✅ 达到本文末“1:1 完成判据” · 🟡 有首版 / 部分语义 · ⬜ 未实现 ·
|
||||
> ❌ 明确不做(超出 m2dev-client 参考范围,除非另立需求)。
|
||||
|
||||
> **当前 40250 范围调整(增量 45)**:真实 FreeBSD + MySQL 服务端的完整登录 / 功能验收暂缓,
|
||||
> 不作为本阶段交付门槛;公会相关功能暂缓。当前目标 40250 服务端不提供龙魂玩法,龙魂不纳入本阶段
|
||||
> 支持范围,已有兼容代码不代表服务端可用;运行时龙魂入口已禁用,但保留 `ds_refine` 等协议兼容代码。
|
||||
>
|
||||
> ### 不做清单(❌)
|
||||
>
|
||||
@@ -21,9 +25,38 @@
|
||||
> - **反作弊(anti-cheat)**:`CG_HACK`(0x0B03) 客户端异常上报,以及桌面外壳的
|
||||
> `ProcessCRC` / `ProcessScanner` / 内存扫描等。自用客户端不需要,**标注为不做**,
|
||||
> 除非服务端强制校验才回头做最小上报。
|
||||
> - **龙魂精炼(当前 40250 目标服务端)**:目标服务端不提供该玩法,本阶段不实现 / 不验收;
|
||||
> 客户端保留的兼容代码不计入当前支持范围。
|
||||
>
|
||||
> ### 变更记录
|
||||
>
|
||||
> - **2026-09-01 增量 45(P8 交互边界与龙魂运行时范围)**:补齐 NPC 点击路由、Cube NPC
|
||||
> 前置 / 配方材料 / 金币校验与制作状态、商店购买 / 出售数量和错误反馈、交换重复 / 满槽 /
|
||||
> 金币边界、仓库 / 商城密码与满包回滚、个人摊位标准 Godot 拖放路径;缺失可选 `.sub` 贴图
|
||||
> 安全降级。龙魂入口运行时禁用,公会和真实服务器验收继续按当前范围暂缓。
|
||||
> - **2026-09-01 增量 44(交付范围调整)**:真实 FreeBSD + MySQL 完整验收、公会相关功能均
|
||||
> 暂缓;当前目标 40250 服务端不提供龙魂玩法,龙魂从本阶段支持范围排除。保留本地协议 / 状态 / UI
|
||||
> 首版与离线回归结果,后续恢复服务端条件后再单独推进 deferred 项。
|
||||
> - **2026-09-01 增量 43(队伍角色 / 能量 / 私店招牌复核)**:对照 40250 服务端
|
||||
> `CParty::Update` 修正队伍角色 6 为 `HASTE`(迅捷),补齐 `affects[7]` 的服务端槽位语义,
|
||||
> 并在 `party_ui.gd` 按 Leadership 10/20/25/35/40 门控攻击/坦克/迅捷/辅助/宗师/防御,
|
||||
> Leadership 18 门控组队治疗;`p8_test.gd` 覆盖低 Leadership 的禁用路径。Cube HUD 已有
|
||||
> `POINT_ENERGY` 快照显示;`GC_SHOP_SIGN` 已解析并在 `NetWorld` 以 `ShopSign` Label3D
|
||||
> 作为无 `.sub` 资源 fallback,`GC_SYMBOL_DATA` 也已有会徽下载链路。剩余仍是原版资源、真
|
||||
> `.sub` 拖放 / 视觉和 Cube NPC 交互;live FreeBSD + MySQL E2E 暂缓。
|
||||
> - **2026-09-01 增量 42(选魔石窗口闭环复核)**:确认 `GC_SCRIPT` 的 `[SELECT_ITEM]` 已由
|
||||
> `QuestDialog` 转发到 `SelectItemUI`;选择窗按原 `uiselectitem.RefreshSlot` 过滤魔石 / grade、
|
||||
> 映射背包格并发送 `CG_SCRIPT_SELECT_ITEM`,关闭发送 0,`select_item_ui_test.gd` 已覆盖。仍需
|
||||
> 完整原版资源、图标和 CJK 输入环境下的视觉验收。
|
||||
> - **2026-09-01 增量 41(创建公会 UI 闭环)**:`GC_REQUEST_MAKE_GUILD` 触发公会创建窗口,
|
||||
> 对应 `CG_ANSWER_MAKE_GUILD` 已接入名称输入、12 字上限、空名 / 控制字符校验和发送失败提示;
|
||||
> 新增 `guild_creation_ui_test.gd` 覆盖请求、校验和合法名称应答。服务端敏感词 / 重名错误及实际建会
|
||||
> 状态仍需真服验收。
|
||||
> - **2026-09-01 增量 40(强制改名 UI 闭环)**:`SimplePlayer.change_name` 已从 classic / m2dev
|
||||
> 角色列表透传到 `M2Client.char_list`;选人页按 40250 原版语义,在角色带该标志时点击“开始”
|
||||
> 弹出改名窗,校验名称后发送 `CG_CHANGE_NAME`,成功的 `GC_CHANGE_NAME` 刷新槽位并清除标志,
|
||||
> `AppFlow` 接通请求、成功和失败回传,新增 `char_create_delete_test.gd` 回归覆盖。P1 行不再把
|
||||
> 改名 UI 列为未实现;仍需真服验证强制改名、重名 / 非法名错误码和服务端状态。
|
||||
> - **2026-08-31 增量 30(EterGrnLib 对齐复核)**:查代码确认以下已落地,表内相关行同步。
|
||||
> ① **材质 blend / two-sided 改读 GR2 材质信息**(`metin2_model::decide_blend/decide_two_sided`
|
||||
> 优先 `gr2::MaterialInfo.alpha_blend/two_sided` = `dump_materials` 端口 `Material.cpp:233`,
|
||||
@@ -63,17 +96,18 @@
|
||||
> - **2026-08-31 增量 37(组队成员信息板 + `CG_PARTY_SET_STATE`)**:
|
||||
> ① **C++**:`wire.h` 加 `CGPartySetState{u16 hdr,u16 len,u32 pid,u8 role,u8 on}`(断言 10)
|
||||
> + `EPartyRole` 枚举(NORMAL 0/LEADER 1/ATTACKER 2/TANKER 3/BUFFER 4/SKILL_MASTER 5/
|
||||
> BERSERKER 6/DEFENDER 7);`game_client.send_party_set_state(pid,role,on)`;
|
||||
> HASTE 6/DEFENDER 7);`game_client.send_party_set_state(pid,role,on)`;
|
||||
> `M2Client.party_set_state(pid,role,on)` + bind;`get_party()` dict 补 `state`(完整角色字节)
|
||||
> 和 `affects[7]`。
|
||||
> ② **`party_ui.gd`** 从「名字 + 一条 HP」重做成 1:1 迁移 `assets/root/uiparty.py`
|
||||
> `PartyMemberInfoBoard` + `partymemberinfoboard.py` 布局:每员 strip = 角色状态按钮
|
||||
> (队长可点 → 弹角色菜单 普通/攻击/坦克/狂战/辅助/宗师/防御 → `party_set_state`;普通 =
|
||||
> (队长可点 → 弹角色菜单 普通/攻击/坦克/迅捷/辅助/宗师/防御 → `party_set_state`;普通 =
|
||||
> 清当前角色 `on=false`;+ 踢出 → `party_leave` = `SendPartyRemovePacket`)+ 名字(+★队长)
|
||||
> + HP gauge + `affects[7]` 非零 → 附加效果 chip(tooltip 带值,槽位名暂定)。点名字 →
|
||||
> `set_target(vid)`。顶部:EXP 分配开关(`party_set_distribute` 0 不均分 / 1 均分)+
|
||||
> 组队治疗(`party_use_skill(PARTY_SKILL_HEAL=1, 0)`)。队长判定 = `get_party()` 里本地
|
||||
> `get_main_vid()` 那条的 `leader`。角色菜单按党技能等级门控(Tanker≥10…Defender≥40)暂略。
|
||||
> `get_main_vid()` 那条的 `leader`。角色菜单按 40250 服务端 Leadership 门控:攻击≥10、坦克/迅捷≥20、
|
||||
> 辅助≥25、宗师≥35、防御≥40;治疗要求 Leadership≥18。
|
||||
> ③ **修 `p8_test` 隐患**:`_init` 原来 `_run()` 未 `await`,`_run` 第一个 `await process_frame`
|
||||
> 之后的所有断言(含增量 34 的 `shop_ex` 多货架)从未真正生效 —— 改成 `await _run()` 后
|
||||
> 暴露 `shop_ui.refresh()` 的 `queue_free` 延迟 bug(旧 row 当帧未消失 → `get_child_count`
|
||||
@@ -224,6 +258,11 @@
|
||||
> `get_observers()` 与 `land_areas_changed` / `observer_event` 已接入;小地图现在消费观战者
|
||||
> 状态并绘制紫色菱形标记。实体、回环、Godot 桥接和 `p9_test.gd` 覆盖。缺失 header 清单由
|
||||
> 5 项降为 **1 项**(仅剩 `CG_TEXT`,参考端未发现实际发送方)。
|
||||
> - **2026-09-01 增量 39(`CG_TEXT` wire 尺寸覆盖)**:按 40250 `TPacketCGText` /
|
||||
> `CInputHandshake::Analyze` 补齐 `CG_TEXT` 的 1 字节固定前缀和 classic `packet_size_cg()`
|
||||
> 表项,并加入 wire 回归断言。该包后续文本由服务端按换行特殊解析,仅作为握手阶段管理通道;
|
||||
> Cube 继续使用已验证的 `CG_CHAT`/`CHAT_TYPE_COMMAND`,不把管理命令暴露为普通游戏 API。
|
||||
> 主网络层缺失 header 清单由 1 项降为 0 项。
|
||||
> - **2026-08-31 增量 19(钓鱼动作消费)**:`NetWorld` 和 `NetPlay` 现在消费
|
||||
> `fishing_event` 的 START / STOP / REACT / SUCCESS / FAIL 子头,记录方向并尝试驱动远端及
|
||||
> 本地主角的钓鱼动作;FISH 子头按参考客户端语义保留为鱼获物品事件,不误当作角色 VID。
|
||||
@@ -272,7 +311,7 @@
|
||||
> - **2026-08-31 增量 3**:两个 ⬜ 项落地首版 —— **私人商店 / 道具商城**
|
||||
> (`CG_MYSHOP` / `GC_MALL_OPEN|SET|DEL` / `CG_MALL_CHECKOUT` + `private_shop_ui` /
|
||||
> `mall_ui`)、**Cube 제작**(`GC_CHAT/COMMAND` 的 `cube …` 总线 → `CubeState` +
|
||||
> `cube_ui`)。仍缺能量条、原版拖放 UI 细节。
|
||||
> `cube_ui`)。能量值已由 `POINT_ENERGY` 快照接入 HUD;仍缺原版拖放 UI 细节。
|
||||
> **拍卖行**经核查 m2dev-client 无此系统 → 标注 ❌ 不做(见上「不做清单」)。
|
||||
> **反作弊**(`CG_HACK` + `ProcessCRC`/`ProcessScanner`)→ 标注 ❌ 不做。
|
||||
> **「协议覆盖审计」段**改为逐条清单:脚本核对 `wire.h` vs `Packet.h`,主网络层
|
||||
@@ -291,7 +330,7 @@
|
||||
## 结论
|
||||
|
||||
`mtgodot-poc` 已经不是早期“只能登录、移动和攻击”的骨架:登录到 PHASE_GAME、基础战斗、
|
||||
背包 / 装备、技能 UI、任务、聊天、组队 / 好友、商店 / 交易 / 仓库、公会、精炼、龙魂、
|
||||
背包 / 装备、技能 UI、任务、聊天、组队 / 好友、商店 / 交易 / 仓库、精炼,
|
||||
地图和部分特效都已有可运行首版。
|
||||
|
||||
当前的主要差距已从“有没有功能”转为:
|
||||
@@ -313,7 +352,7 @@
|
||||
- 背包、基础装备换模、地面物品、技能窗口和快捷栏读取;
|
||||
- 聊天、私聊、基础任务对话和任务日志;
|
||||
- 组队、好友、情侣名 / 爱意值状态、NPC 商店、交易、仓库;
|
||||
- 公会、公会技能、公会战、会徽上 / 下载、精炼、龙魂精炼;
|
||||
- 公会、公会技能、公会战、会徽上 / 下载、精炼(公会相关验收暂缓);
|
||||
- 地形、建筑、水体、**NPC / 怪物真模型(vnum→npclist.txt→目录)**、小地图、频道、昼夜和天气首版;
|
||||
- GR2 模型 / 动画、换装首版、武器 / 盾挂点、距离 LOD / 淡入、角色接触阴影、
|
||||
`item_proto` 驱动的球面高光和 `.mse` 粒子首版。
|
||||
@@ -324,7 +363,7 @@
|
||||
|
||||
| 优先级 | 状态 | 模块 | 当前实现 | 需要迁移的原客户端语义 |
|
||||
|---|---|---|---|---|
|
||||
| P1 | 🟡 | 选人 / 建号 / 删号 / 改名 | `CG_CHARACTER_CREATE`(0x0201) / `CG_CHARACTER_DELETE`(0x0202) / `CG_CHANGE_NAME`(0x010B) / `GC_PLAYER_CREATE_SUCCESS`(0x020C) / `GC_PLAYER_CREATE_FAILURE`(0x020D) / `GC_PLAYER_DELETE_SUCCESS`(0x020E) / `GC_PLAYER_DELETE_WRONG_SOCIAL_ID`(0x020F) / `GC_CHANGE_NAME`(0x010C) 全部有尺寸断言;`GameClient` 发送接口、角色槽位补丁和 `drain_*_events()`;`M2Client` 同名建删改 API、4 个建删结果信号及 `char_name_changed`;`net.loopback_flow` 覆盖建删和改名名称字节 / pid 广播。**真机验证(2026-08-31,`net_e2e MT_E2E_CHARCREATE=1`)**:建号、`GC_PLAYER_CREATE_FAILURE`、`GC_EMPIRE` 已验。选人页有建号 / 删号弹窗与国家国旗 | `CG_CHARACTER_DELETE` 破坏性,真机未验;改名 UI / 改名卡消耗和重复名错误提示未接;建号缺外形 / 发型选择与属性再分配 UI(现发 `shape=0` + 职业基础四维);缺 `SELECT_EMPIRE` 选国界面;原版选人台座、镜头动画、`OnCreateFailure` 完整错误码文案 |
|
||||
| P1 | 🟡 | 选人 / 建号 / 删号 / 改名 | `CG_CHARACTER_CREATE`(0x0201) / `CG_CHARACTER_DELETE`(0x0202) / `CG_CHANGE_NAME`(0x010B) / `GC_PLAYER_CREATE_SUCCESS`(0x020C) / `GC_PLAYER_CREATE_FAILURE`(0x020D) / `GC_PLAYER_DELETE_SUCCESS`(0x020E) / `GC_PLAYER_DELETE_WRONG_SOCIAL_ID`(0x020F) / `GC_CHANGE_NAME`(0x010C) 全部有尺寸断言;`GameClient` 发送接口、角色槽位补丁和 `drain_*_events()`;`M2Client` 同名建删改 API、4 个建删结果信号及 `char_name_changed`;`net.loopback_flow` 覆盖建删和改名名称字节 / pid 广播。**真机验证(2026-08-31,`net_e2e MT_E2E_CHARCREATE=1`)**:建号、`GC_PLAYER_CREATE_FAILURE`、`GC_EMPIRE` 已验。选人页有建号 / 删号弹窗、强制改名弹窗与国家国旗 | `CG_CHARACTER_DELETE` 破坏性,真机未验;强制改名、重名 / 非法名错误码和服务端状态未真服验收;建号缺外形 / 发型选择与属性再分配 UI(现发 `shape=0` + 职业基础四维);原版选人台座、镜头动画、`OnCreateFailure` 完整错误码文案 |
|
||||
| P0 | 🟡 | 技能施放协议 | `CG_USE_SKILL`、`CG_FLY_TARGETING`、`CG_ADD_FLY_TARGETING` 与 `CG_SHOOT` 已有尺寸断言、原生发送接口和 loopback 字节验证;服务端 `GC_FLY_TARGETING` / `GC_ADD_FLY_TARGETING` 已进入 `EntityStore`,通过 `M2Client.fly_targeting` 暴露,且已补入 `GameClient` 世界分派;`GC_CHANGE_SKILL_GROUP` 会更新 `get_skill_group()` 并使技能快照失效;快捷栏先发 `use_skill(skill_id,target_vid)`,再同步 `CG_MOVE` 技能动作;弓技能会在 `.msa` FLY 事件发送 `CG_SHOOT`。真服单会话已发送 `CG_USE_SKILL` / `CG_FLY_TARGETING` / `CG_ADD_FLY_TARGETING` / `CG_SHOOT`,均无断连 / unknown | 仍需实现范围 / 多目标选择器来自动驱动 `ADD_FLY_TARGETING`;冷却、目标合法性、真实弹道和客户端表现也须按技能类型细分;尚未在真服观察到对应 GC 飞行目标推送 |
|
||||
| P0 | 🟡 | 快捷栏持久化 | 已覆盖 36 槽(4 页 × 9 格)、F1–F4 切页和 1–9 激活;拖放 / 清除 / 交换会分别发送 `CG_QUICKSLOT_ADD/DEL/SWAP`,服务器 `GC_*` 可完整恢复;技能冷却读取对应 `.msk` 的 `CoolTimeFormula` | 仍需补命令 / 表情快捷槽、物品拖放来源、鼠标物品态及原 UI 的完整快捷栏交互;冷却还未叠加原客户端的施法速度与所有特殊技能规则 |
|
||||
| P0 | 🟡 | 物品操作 | 已有移动、使用、丢弃、拾取;Shift 选“来源→目标”发 `ITEM_USE_TO_ITEM`,Ctrl+右键向当前目标 `ITEM_GIVE`,Alt+右键以数量框发 `ITEM_DROP2`;`ITEM_OWNERSHIP` 会实时更新地面名条;`GC_VIEW_EQUIP` 已保存 11 格检查快照并弹出装备查看窗 | 仍需复刻原鼠标物品态、操作确认 / 错误提示、宝石专用规则,以及装备查看窗的原版槽位图标、3D 纸娃娃与交互 |
|
||||
@@ -333,14 +372,15 @@
|
||||
| P0 | 🟡 | PVP / 决斗 / 阵营 | `GC_PVP` 和 `DUEL_START` 已进入状态层,并以 `pvp_changed` / `duel_started` 信号提供给 Godot;挑战 / 战斗 / 复仇关系会在世界实体上显示标签;实体已有部分 empire / alignment / pk 字段 | 仍需 PK 模式上行、原版名字颜色、可攻击判定、阵营规则和原版目标板 / 决斗 UI |
|
||||
| P1 | 🟡 | Actor 战斗运行时 | 有骨骼动画、基础 combo / 硬直 / 相机抖动;动作切换按 Granny `EaseInCurve(0,0,1,1)` 的 `2w²−w³` 逐骨 crossfade;角色 mesh 支持距离 LOD、15% 迟滞和约 0.18s 新旧 mesh 淡入(`LodGhost` + `lod_fade` uniform);右手武器 / 左手盾按 `weaponComposite[0] = weaponInvWorld[0]·weaponLocal[0]` grip 复合挂 `equip_right_hand`(探针实测 Δ≤0.06 m,非标准米级偏移文件夹断回退);`.msa` motion event 已分派声音、EffectPosition 特效、震屏和屏闪(FLY / WARP 留钩子);玩家 / 怪物强制实时投影并附脚底接触阴影 Decal;实体 `attack_speed` 与本地 `POINT_ATT_SPEED` 已按原版 100 基准影响攻击请求间隔 | 仍需用真实 `.msa` motion duration、武器 / 坐骑规则和服务端合法性校准攻击节奏;另补 combo 取消窗口、精确受击 / 击退、角色碰撞、同步碰撞、武器拖尾、剩余 motion event / 骨骼挂点语义、GPU skin LOD、双持 / 左手武器和目标锁定相机;`03150` 类偏移网格需 per-weapon 偏移数据或修 .gr2 |
|
||||
| P1 | 🟡 | 飞行物与命中特效 | `GC_FLY_TARGETING` / `GC_ADD_FLY_TARGETING` 保存 shooter 的目标队列和 VID / 坐标;`GC_CREATE_FLY` 可消费队列并生成 tween 发光球 | 对齐 `FlyingObjectManager`:真实技能弹道模型、命中时机 / 命中特效、消失条件、声音与 EffectLib 特效 |
|
||||
| P1 | 🟡 | 任务 / NPC | 支持 `[ENTER]`、`[CLEAR]`、`[NEXT]`、`[DONE]`、基础 `[QUESTION]`、`[INPUT]` 文本框和任务日志;`M2Client.script_select_item()` / `quest_cancel()` 已可发送原协议应答,Escape 会走取消包;真服单会话已发送 `CG_SCRIPT_SELECT_ITEM`(8B) 与 `CG_QUEST_CANCEL`(4B),取消触发 1 条 quest-change 且无断连 / unknown | 补选道具网格、原版 CJK IME / 输入校验、QuestButton、立绘、完整 EventManager 标签、世界箭头和屏幕边缘指示;选道具包本轮未出现脚本业务回包 |
|
||||
| P1 | 🟡 | 任务 / NPC | 支持 `[ENTER]`、`[CLEAR]`、`[NEXT]`、`[DONE]`、基础 `[QUESTION]`、`[INPUT]`、`[SELECT_ITEM]` 文本流程和任务日志;`SelectItemUI` 按原 `uiselectitem.RefreshSlot` 过滤魔石 / grade、映射背包格并发送 `CG_SCRIPT_SELECT_ITEM`,`quest_cancel()` 发送取消包;真服单会话已发送 `CG_SCRIPT_SELECT_ITEM`(8B) 与 `CG_QUEST_CANCEL`(4B),取消触发 1 条 quest-change 且无断连 / unknown | 补原版 CJK IME / 输入校验、QuestButton、立绘、完整 EventManager 标签、世界箭头和屏幕边缘指示;选道具业务回包与完整资源视觉仍需真服 / 资源环境验收 |
|
||||
| P1 | 🟡 | 商店 / 交易 / 仓库 | 普通 NPC 商店、交易状态和仓库列表已有首版;**`SHOP_GC_START_EX` 多货架已解析(`m_shop_tabs`,`get_shop()`),`shop_ui` 带货架按钮 + `tabIdx*40+slot` 买位置** | 补图标格网格、数量输入、交易回滚提示、仓库密码 / 改密码、完整拖放规则、`coin_type` 非金币货币显示 |
|
||||
| P1 | 🟡 | 私人商店 / 道具商城 | **首版**:`CG_MYSHOP`(0x0802) `CGMyShopHead`(38) + `MyShopItem`(13)×N 有尺寸断言 + `GameClient::send_open_private_shop` / `send_close_private_shop`(=`SHOP_CG_END`) + loopback 字节级;`GC_MALL_OPEN`(0x0841)/`GC_MALL_SET`(0x0842)/`GC_MALL_DEL`(0x0843) 路由进 `EntityStore`(`m_mall[135]` + `mall_open/size/slot/dirty`),`CG_MALL_CHECKOUT`(0x0840) `CGMallCheckout`(8) 发送;`M2Client` `open/close_private_shop`、`get_mall_items`/`mall_checkout` + `mall_opened`/`mall_changed` 信号;`ui/private_shop_ui.gd`(**已重做成 `PrivateShopBuilder.itemStock` 模型:40 格 grid + 拿起 / 落位 / 逐件价格弹窗 / 点占用格撤下 / 개설按格号排序 + display_pos + 上限 39**)、`ui/mall_ui.gd`(列表 + 取出)。**真机验证(2026-08-31,`net_e2e MT_E2E_MYSHOP=1`)**:`CG_MYSHOP` 38B head + 13B item×1 被真服接受,无断连 / 无 shop error,`SHOP_CG_END` 关店正常。`CG_MALL_CHECKOUT` 送出不断连,但 mall 需点 NPC 才 open。他人开店 `SHOP_GC_START_EX` 多货架已解析(见增量 34)。⬜ `SYMBOL_DATA`/`GC_SHOP_SIGN` 头顶招牌 3D、真 `.sub` 版 `privateshopbuilder.py` uiscript、鼠标真拖放物品态 |
|
||||
| P1 | 🟡 | 私人商店 / 道具商城 | **首版**:`CG_MYSHOP`(0x0802) `CGMyShopHead`(38) + `MyShopItem`(13)×N 有尺寸断言 + `GameClient::send_open_private_shop` / `send_close_private_shop`(=`SHOP_CG_END`) + loopback 字节级;`GC_MALL_OPEN`(0x0841)/`GC_MALL_SET`(0x0842)/`GC_MALL_DEL`(0x0843) 路由进 `EntityStore`(`m_mall[135]` + `mall_open/size/slot/dirty`),`CG_MALL_CHECKOUT`(0x0840) `CGMallCheckout`(8) 发送;`M2Client` `open/close_private_shop`、`get_mall_items`/`mall_checkout` + `mall_opened`/`mall_changed` 信号;`ui/private_shop_ui.gd`(**已重做成 `PrivateShopBuilder.itemStock` 模型:40 格 grid + 拿起 / 落位 / 逐件价格弹窗 / 点占用格撤下 / 개설按格号排序 + display_pos + 上限 39**)、`ui/mall_ui.gd`(列表 + 取出)。**真机验证(2026-08-31,`net_e2e MT_E2E_MYSHOP=1`)**:`CG_MYSHOP` 38B head + 13B item×1 被真服接受,无断连 / 无 shop error,`SHOP_CG_END` 关店正常。`CG_MALL_CHECKOUT` 送出不断连,但 mall 需点 NPC 才 open。他人开店 `SHOP_GC_START_EX` 多货架已解析(见增量 34)。`GC_SHOP_SIGN` 已在 `NetWorld` 提供 `ShopSign` Label3D fallback,`GC_SYMBOL_DATA` 已接会徽下载;仍缺真 `.sub` 版 `privateshopbuilder.py` uiscript、资源视觉和鼠标真拖放物品态 |
|
||||
| — | ❌ | 拍卖行 / auction house | 不做 | m2dev-client 无此系统(`0x08xx` 段只有 shop/myshop/safebox/mall,全源码 / 协议 / 资产零 `auction` 命中)。需自定义协议 + 服务端支持才能实现,**标注为不做**,除非后续明确提需求 |
|
||||
| P1 | 🟡 | Cube (제작) / 能量系统 | **首版**:Cube 走 `GC_CHAT`/`CHAT_TYPE_COMMAND` 文本总线(对齐 `ServerCommand()`),`EntityStore::apply_server_command` 解析 `cube open/close/info/success/fail/r_list/m_info`(配方 `v,c` 列表 + `@`/`&`/`|`/`/` 分层材料 + 金币)→ `CubeState` + `drain_cube_events()`;`GameClient::send_cube_make/material_info/result_list`(`/cube make|mInfo|rList`);`M2Client` `get_cube`/`cube_make`/`cube_request_*` + `cube_opened`/`cube_closed`/`cube_changed`/`cube_result` 信号;`ui/cube_ui.gd`(配方列表 + 材料/金币 + 제작)。`net.entity_store` + `net.loopback_flow` 覆盖。真机(2026-08-31)`/cube rList` 送出不断连,但服务器只在玩家站到 cube NPC 前才回应 → `cube open=0`,需 NPC 交互完整验。⬜ 能量条(`POINT_ENERGY` / affect)、原 `uiCube.py` 材料格 3D 图标 / 拖放 / 결과 애니、NPC 前完整验 send 命令字 |
|
||||
| P1 | 🟡 | 组队 | 邀请、接受、离队;**成员信息板(`party_ui.gd`,1:1 迁移 `uiparty.PartyMemberInfoBoard`):每员角色状态按钮(队长弹菜单 → `CG_PARTY_SET_STATE` 0x0704 分配 攻/坦/狂/辅/宗/防 或踢人)+ 名字(★队长) + HP gauge + `affects[7]` 附加效果 chip;顶部 EXP 分配开关(`party_set_distribute`)+ 组队治疗(`party_use_skill(1,0)`)**;真服单会话 `CG_PARTY_USE_SKILL`(9B) 后仍在线;小地图 / Atlas 绿色队员点 + 队长环 | 补角色菜单按党技能等级门控(Tanker≥10…Defender≥40)、`affects[7]` 精确槽位语义、真版 `.sub` 图标 / 颜色、队伍技能冷却 / 权限、离线颜色语义 |
|
||||
| P1 | 🟡 | Cube (제작) / 能量系统 | **首版**:Cube 走 `GC_CHAT`/`CHAT_TYPE_COMMAND` 文本总线(对齐 `ServerCommand()`),`EntityStore::apply_server_command` 解析 `cube open/close/info/success/fail/r_list/m_info`(配方 `v,c` 列表 + `@`/`&`/`|`/`/` 分层材料 + 金币)→ `CubeState` + `drain_cube_events()`;`GameClient::send_cube_make/material_info/result_list`(`/cube make|mInfo|rList`);`M2Client` `get_cube`/`cube_make`/`cube_request_*` + `cube_opened`/`cube_closed`/`cube_changed`/`cube_result` 信号;`ui/cube_ui.gd`(配方列表 + 材料/金币 + 제작)。`net.entity_store` + `net.loopback_flow` 覆盖。真机(2026-08-31)`/cube rList` 送出不断连,但服务器只在玩家站到 cube NPC 前才回应 → `cube open=0`,需 NPC 交互完整验。`POINT_ENERGY` 已由 HUD 快照显示;仍缺原 `uiCube.py` 材料格 3D 图标 / 拖放 / 결과 애니、NPC 前完整验 send 命令字 |
|
||||
| P1 | 🟡 | 组队 | 邀请、接受、离队;**成员信息板(`party_ui.gd`,1:1 迁移 `uiparty.PartyMemberInfoBoard`):每员角色状态按钮(队长弹菜单 → `CG_PARTY_SET_STATE` 0x0704 分配 攻/坦/迅捷/辅/宗/防 或踢人)+ 名字(★队长) + HP gauge + `affects[7]` 附加效果 chip;顶部 EXP 分配开关(`party_set_distribute`)+ 组队治疗(`party_use_skill(1,0)`)**;角色 / 治疗控件已按 40250 服务端 Leadership 规则本地门控(攻击≥10、坦克/迅捷≥20、辅助≥25、宗师≥35、防御≥40,治疗≥18);真服单会话 `CG_PARTY_USE_SKILL`(9B) 后仍在线;小地图 / Atlas 绿色队员点 + 队长环 | 仍需真版 `.sub` 图标 / 颜色、队伍技能冷却 / 权限、离线颜色语义和真实两账号组队验收 |
|
||||
| P1 | 🟡 | 好友 / 情侣 | 好友列表、上线状态和私聊入口已有;`GC_LOVER_INFO`(70B) / `GC_LOVE_POINT_UPDATE`(5B) 已有尺寸断言、`EntityStore::LoverInfo` 状态、`M2Client.get_lover()` / `lover_changed`,`love_ui` 常驻显示伴侣名和 0–100 爱意值;`net.entity_store` 与 `love_ui_test.gd` 覆盖 | 补好友分组和完整 messenger 行为;情侣仍需完整交互 / 状态图标与 affect 表现、断线 / 切图生命周期、原版文案和真服务器端到端验收 |
|
||||
| P1 | 🟡 | 公会 | 信息、成员、技能、公会战、会徽上 / 下载和部分操作已有首版;`GC_REQUEST_MAKE_GUILD`(0x0731) 已解析并以 `M2Client.guild_make_requested` 通知;`CG_SYMBOL_CRC` / `GC_SYMBOL_DATA` 已支持原始符号文件下载 | 补完整权限 / 等级页、公告与日志、成员管理、创建公会 UI / 应答流程、公会战应答、积分板、领地和公会建筑 |
|
||||
| P1 | 🟡 | 公会(暂缓) | 信息、成员、技能、公会战、会徽上 / 下载和部分操作已有首版;`GC_REQUEST_MAKE_GUILD`(0x0731) 已解析并以 `M2Client.guild_make_requested` 通知;公会窗已弹出创建名称输入并发送 `CG_ANSWER_MAKE_GUILD`;`CG_SYMBOL_CRC` / `GC_SYMBOL_DATA` 已支持原始符号文件下载 | 本阶段暂缓完整权限 / 等级页、公告与日志、成员管理、公会战应答、积分板、领地和公会建筑;恢复公会范围后再做完整真服验收 |
|
||||
| — | ❌ | 龙魂精炼 | 当前目标 40250 服务端不提供该玩法;本阶段不纳入支持或验收,已有兼容代码仅保留作协议参考 | 若未来服务端增加该玩法,再另立协议、UI 和验收需求 |
|
||||
| P1 | 🟡 | 世界玩法 | 有 `CG_WARP` 主动请求、`GC_WARP` 同服 / 跨服处理、`CG_FISHING` / `GC_FISHING` 钓鱼方向与状态事件、`NetWorld` / `NetPlay` 钓鱼动作分发、`ChatUI` 鱼获 / 失败日志、`CG_DUNGEON` / `GC_DUNGEON` 副本请求与状态事件、`GC_DIG_MOTION` 挖矿动作广播、`GC_LAND_LIST` 领地状态、`GC_OBSERVER_ADD/REMOVE/MOVE` 观战者状态、频道、时间、NPC marker、天气粒子和 mount_vnum 字段;真服登录洪流已收到并解析 `GC_LAND_LIST`(436B),单会话发送 `CG_FISHING`(5B) 后收到“Please choose a Fishing Pole.”业务拒绝且连接保持;同服 `GC_WARP` 直接挪玩家,跨服 `addr≠0` 由 `M2Client` 复用 login key 直连目标 game server,断点重连也走该快路径 | 补完整钓鱼 UI / 鱼获背包落地、副本计时 / 入口 UI、坐骑真模型 / 骑乘动作 / 移速、地形贴花、DungeonBlock 和地图天气配置;`CG_DUNGEON` / `CG_WARP` 本轮为避免副作用未发送,跨服换图仍需真服端到端验收与场景生命周期清理 |
|
||||
| P1 | 🟡 | 小地图 / Atlas | 可画玩家、实体、NPC、任务标记、观战者紫色菱形和 `GC_LAND_LIST` 领地边框;支持 `set_scale()` / 鼠标滚轮缩放;Atlas 支持底图、地图名称、玩家坐标、拖动和坐标查询 | 补原 minimap / Atlas 贴图细节、提示、队员 / NPC 分类、世界箭头、地图驱动天气配置和原版窗口视觉 |
|
||||
| P1 | 🟡 | EffectLib | `.mse` Particle 已映射到 `GPUParticles3D` | 粒子 `.dds` 目前被程序化径向渐变替代,`.mde` 用 box 占位;需补 EffectMesh、SimpleLight、TexAni、MovingType、骨骼挂点和完整时间轴 |
|
||||
@@ -384,7 +424,7 @@
|
||||
故当前总数从 24 降为 22 个 header;增量 7 再补任务选择 / 取消上行,增量 8 补队伍技能上行,
|
||||
增量 9 补飞行目标广播,增量 10 补技能组切换,增量 11 补角色改名,增量 12 补公会创建请求,
|
||||
增量 13 补主动传送,增量 14 补挖矿动作,增量 15 补会徽符号下载,增量 16 补钓鱼协议,
|
||||
增量 17 补副本协议,增量 18 补领地与观战者,当前为 **1 个 header**。
|
||||
增量 17 补副本协议,增量 18 补领地与观战者,增量 39 补 `CG_TEXT`,当前为 **0 个 header**。
|
||||
|
||||
排除仅命名不同、功能已覆盖的别名(`GC_CHAR_ADDITIONAL_INFO`=`GC_CHAR_ADD_INFO`、
|
||||
`GC_TARGET`=`GC_TARGET_INFO`、`GC_TARGET_CREATE_NEW`=`GC_TARGET_CREATE`、
|
||||
@@ -392,13 +432,13 @@
|
||||
`GC_SEPCIAL_EFFECT`=`GC_SPECIAL_EFFECT`、`GC_REFINE_INFORMATION_NEW`=`GC_REFINE_INFO_NEW`),
|
||||
以及 `CG_STATE_CHECKER` / `GC_RESPOND_CHANNELSTATUS`(`project/net/channel_status.gd` 单独实现)
|
||||
和 `CG_HACK`(反作弊,见「不做清单」),
|
||||
**当前主网络层仍缺 1 个 header**(脚本核对 `wire.h` vs `Packet.h`):
|
||||
**当前主网络层仍缺 0 个 header**(脚本核对 `wire.h` vs `Packet.h`):
|
||||
|
||||
### 账号 / 命令通道
|
||||
|
||||
| header | 值 | 说明 |
|
||||
|---|---|---|
|
||||
| `CG_TEXT` | 0x0011 | 简易命令通道(Cube 现借 `CG_CHAT`/`CHAT_TYPE_COMMAND` 实现,非原路径) |
|
||||
| `CG_TEXT` | 0x0011 | 已补 classic wire 尺寸表;这是握手阶段的管理命令,固定前缀为 1 字节,后续文本直到换行由服务端特殊解析。Cube 仍借 `CG_CHAT`/`CHAT_TYPE_COMMAND` 实现,不伪造管理命令入口 |
|
||||
|
||||
### 已声明但待核(不计入上面 1 个)
|
||||
|
||||
@@ -407,8 +447,9 @@
|
||||
自动触发语义、姿态动作链和服务端位置纠偏回包验收。
|
||||
- `CG_SCRIPT_SELECT_ITEM`(0x0903) / `CG_QUEST_CANCEL`(0x0906):wire、发送接口和
|
||||
loopback 字节测试已覆盖;真服单会话已分别发送 8B / 4B,取消触发 1 条 quest-change 且无
|
||||
unknown;基础 `[INPUT]` / Escape 取消已接入,仍缺选道具网格、原版输入校验和有脚本时的任务
|
||||
流程验收。
|
||||
unknown;基础 `[INPUT]` / `[SELECT_ITEM]` / Escape 取消已接入,选择窗的背包魔石网格、
|
||||
grade 过滤和选择回包已由 `select_item_ui_test.gd` 覆盖;仍缺原版输入校验、CJK IME 和有脚本时
|
||||
的真实任务流程验收。
|
||||
- `CG_PARTY_USE_SKILL`(0x0705):wire、发送接口和 loopback 字节测试已覆盖;真服单会话已发送
|
||||
9B 且保持在线 / 无 unknown,但无队伍技能业务回包;仍缺冷却 / 权限、UI 入口和有效队伍真服
|
||||
验收。
|
||||
@@ -420,10 +461,11 @@
|
||||
`M2Client.skill_group_changed` 已覆盖;本轮发现并修复 `GameClient` 未分派该 header 的 bug;
|
||||
仍缺技能组选择 UI、服务端权限和真服推送验收。
|
||||
- `CG_CHANGE_NAME`(0x010B) / `GC_CHANGE_NAME`(0x010C):wire、角色槽位更新、
|
||||
`M2Client.change_name()` 和 `char_name_changed` 已覆盖;仍缺改名 UI、改名卡消耗 / 重名错误
|
||||
文案和真服验收。
|
||||
- `GC_REQUEST_MAKE_GUILD`(0x0731):无负载 wire 解析和 `guild_make_requested` 信号已覆盖;仍缺
|
||||
创建公会窗口、名称校验 / 应答和真服验收。
|
||||
`M2Client.change_name()` 和 `char_name_changed` 已覆盖;选人页按 `change_name` 标志接入
|
||||
原版“点击开始先改名”流程,并对重名 / 非法名错误码给出状态文案;仍缺真服验收。
|
||||
- `GC_REQUEST_MAKE_GUILD`(0x0731):无负载 wire 解析和 `guild_make_requested` 信号已覆盖;公会窗已
|
||||
完成创建窗口、12 字上限、空名 / 控制字符校验和 `CG_ANSWER_MAKE_GUILD` 应答;仍缺服务端敏感词 /
|
||||
重名错误回包、实际建会状态和真服验收。
|
||||
- `CG_SYMBOL_CRC`(0x0723) / `GC_SYMBOL_DATA`(0x0732):16B / 8B wire、`MarkClient` CRC 请求、
|
||||
变长数据接收和 `M2Client.guild_symbol_ready` 已覆盖;仍缺本地符号缓存失效策略、UI 预览和
|
||||
真服验收。
|
||||
@@ -464,7 +506,7 @@
|
||||
|
||||
1. 任务完整标签 / 输入 / 选道具 / 指引;
|
||||
2. 商店 START_EX、仓库密码、商城、私人商店、Cube(拍卖行 m2dev-client 无,除非另起协议);
|
||||
3. 组队角色、公会完整页面、情侣完整交互、领地与公会建筑;
|
||||
3. 组队角色、情侣完整交互、领地与公会建筑;公会完整页面暂缓;
|
||||
4. 钓鱼、副本、坐骑、观战者和 Atlas。
|
||||
|
||||
### M3:UI 与表现 1:1
|
||||
@@ -483,7 +525,7 @@
|
||||
|
||||
## 1:1 完成判据
|
||||
|
||||
一个功能只有同时满足以下条件才标记为完成:
|
||||
一个功能只有同时满足以下条件才标记为完成。当前 40250 阶段对已明确暂缓的真服、公会和龙魂项不作完成承诺:
|
||||
|
||||
1. 原客户端涉及的 CG / GC 包和 sub-header 全部覆盖,并有尺寸断言;
|
||||
2. 数据状态能正确恢复、重连、切图和清理;
|
||||
|
||||
Reference in New Issue
Block a user