11 KiB
11 KiB
首个 Mac 联网内测版:实施状态与已知问题(REL-01)
日期:2026-09-11。对应计划:docs/FIRST-MAC-PLAYABLE-IMPLEMENTATION.md。
后续审查:提交 f39a55fd 的观察器缓存保留、运行取消清理、外部内存门禁与异常 JSON 处理问题,见 审查与修复记录。以下环境数据是原实施时的快照。
本文只记录已核对的事实。当前没有可放行的候选包,也没有任何实网证据;所有依赖服务器、测试账号、环境负责人确认或人工签核的条目均为 BLOCKED。离线/假进程测试 PASS 只证明门禁和状态机按契约工作,不能代替联网验收。
1. 结论
| 项 | 状态 | 说明 |
|---|---|---|
| INF-01 契约与配置校验 | 离线 PASS | playable_harness_test.gd 负向用例、validate_playable_report.mjs 静态夹具全部通过 |
| INF-02 运行器与退出门禁 | 离线 PASS | script/playable_gate_test.sh 用假签名 arm64 包覆盖 PASS/退出码/信号/超时 TERM→10s→KILL/残留 FIFO/RID 与泄漏警告/凭据脱敏/聚合 |
| NET-01 真实联网闭环 | BLOCKED | 包内入口已实现;缺 scenario.local.json、测试账号、环境负责人确认的路线/怪物/掉落,未联网运行 |
| CBT-01 四职业技能矩阵 | BLOCKED | test/playable/skill-cases.json 全部 unconfirmed;脚本不补技能 ID |
| MAP-01 树怪资源与离线 Metal 截图 | 离线 PASS,待人工签核 | 12 个候选树怪 × CPU/GPU × wait/run/attack/damage/dead 全部组装通过;截图需人工看过 |
| MAP-02 实际地图定位与落地 | BLOCKED | forest-viewpoints.example.json 机位均 unconfirmed;坡地脚/根接触需人工检查 |
| STB-01 2 小时稳定性 | 工具已实现,未实跑,BLOCKED | script/playable_soak.sh 可运行(见 §4);真实断网与切图需环境确认 |
| REL-01 放行 | BLOCKED | 无重建候选包;上述必测项均未产生实网证据 |
2. 候选包与环境
- 计划中的候选包
build/export-native-trees-20260911/mtgodot-poc.app和自编译引擎build/godot-particle-diagnostic/bin/godot.macos.template_release.arm64在当前工作树不存在。仅有build/export/mtgodot-poc.app(2026-09-08),早于本轮全部 playable 代码,不能作为候选包。 - 本轮修改了 GDScript(包内测试入口、流程、指标、窗口适配),必须重新导出 PCK;若最终修复涉及 C++,还需
./build.sh Release重建扩展、重新签名打包。重建后对最终包重新跑退出门禁。 - 官方 Release 模板的粒子退出警告未修复;必须显式使用经过验证的自编译 arm64 引擎。不宣称已修复官方模板或 Intel 平台。
- 数据盘剩余约 7.5 GiB(99% 已用)。2 小时 soak 的
events.jsonl、rss.jsonl、截图与日志会持续写盘,实跑前需由用户腾出空间;脚本不会自行清理任何文件或系统缓存。
3. 已知问题与限制
3.1 树怪动作(MAP-01)
ent_trent(2301/2311)的 motlist 只有 WAIT、WAIT1、NORMAL_ATTACK、NORMAL_ATTACK1、FRONT_DAMAGE、FRONT_DEAD,没有 RUN/WALK。按旧客户端CRaceData::GetMotionKey未命中→SetLoopMotion直接返回的规则,移动时继续播放当前循环(reference_keep_current_motion)。forest_mob_render_test报告记为 4 条 fallback(2 个 race × CPU/GPU),标注“需实网确认:服务器移动该种族时位置变化且保持原循环”。未经实网确认前不能宣称行走表现与原版一致。- 七种 ent 目录的 motlist 均只有 FRONT_DEAD,没有 BACK_DEAD。背后击杀时的死亡动作按旧客户端回退规则判定,需实网对照确认。死亡姿态、材质、轮廓已进入接触表截图,必须人工签核;AABB 底部不是脚部接触,离线测试不能证明坡地脚/根贴地。
mob_winding_test.gd仍固定覆盖 101/110/20001;树怪由forest_mob_render_test.gd单独覆盖。
3.2 帧时间(离线合成 suite,非实网)
rendering_scenario_test.gd(Metal,suite=offline_synthetic,FakeClient + 真实资源)本轮结果:
- 689 帧,>50ms 14 帧,全部已归因(unattributed=0);>100ms:loading 6、gameplay 2。
- gameplay 的 2 帧(119.5ms、237.0ms)都带
viewport_resize标记,发生在测试主动切换窗口尺寸时。它们不属于正常游玩的重复交互,但在实网 soak 中要继续按“同一交互 3 次中 2 次 >100ms 即阻断”规则判定。 - loading 段:同步模型构建 447–746ms,切图 1861ms 与 4489ms。首次加载预算尚未固定(计划要求基线采集后再定,不临时放宽)。
- CPU 蒙皮 8/16 角色时 p99 分别为 70.1ms/50.5ms(90 帧窗口,p99 即最大值);GPU 蒙皮 1/8/16 角色 p99 ≤ 26.1ms。
- 视口 1280×720、1920×1080、2560×1440 均按请求尺寸生效(screen_scale=1);Retina 缩放下的物理/逻辑换算由
testing/playable_window.gd记录,未在 Retina 屏实测。 - 冷启动:进程冷启动/系统缓存状态未知,测试不清空系统缓存。
- 显存:
gpu_memory_kib=null(unavailable)。Godot RenderingDevice 计数 843,616 KiB 不是系统显存,不据此判断显存泄漏。探针开销:每次采样 CPU 约 1.26µs;开/关探针 p50 差 −0.018ms,处于帧节奏噪声内。
3.3 稳定性工具的边界(STB-01)
- 切图:
soak.warp.status默认unconfirmed,STB-WARP-01 为 BLOCKED。只有环境负责人确认合法传送入口(portal_cm、return_portal_cm、destination_map_key、cross_server、偶数且 ≥20 的往返次数)后才会走传送门;不以直接改客户端节点位置代替。跨服切图须核实测试服支持。 - 真实断网:
soak.faults.status默认unconfirmed,STB-DISCONNECT-01 为 BLOCKED;主动reconnect()(STB-RECONNECT-01)与真实传输故障分开计数,不能互相替代。确认后由run_client_gate.sh在 127.0.0.1 上启动script/playable_fault_proxy.mjs,只代理本测试客户端的连接(server.*与 serverlist 必须指向代理端口,soak.faults.upstream为真实测试服)。不修改全局路由、防火墙,也不关闭任何服务。 - 已知限制:如果服务器传送时下发了直连的 game 地址,之后的连接会绕过代理,故障注入对切图后的连接无效。需要在确认故障条件时一并核实,或在同一地图服务器内完成故障用例。
- 窗口:headless、全屏、最大化窗口不可切换尺寸;请求尺寸(含标题栏)超出屏幕可用区域时如实记为 BLOCKED,不缩小目标冒充通过。
- 内存:父运行器每秒采样子进程 RSS(KiB),在每轮静置 30s 后取低水位;必须 ≥ warm-up + 10 轮才判定。连续 5 轮增长,且后 5 轮中位数比前 5 轮高出 max(50MiB, 5%) 时 FAIL。低于阈值也不能证明长期无泄漏。
- 10 次正常退出由 10 个独立进程完成,每次都经过完整退出门禁;任何一次失败,后续运行(包括 2 小时 soak)不会启动,记为 BLOCKED。
3.4 人工项(不能自动化替代)
- 真实鼠标/键盘闭环(点击移动、选怪、普攻、技能栏、拾取)需要单独的人工证据。
- MAP-01/MAP-02 Metal 截图人工签核(
forest_map_render_test报告里manual_signoff.status恒为PENDING,自动 PASS 不代表视觉签核)。 - CBT-01 技能特效截图需人工看过一次。
4. 已可运行的命令
以下命令在 metin2-client/ 下执行。账号只通过 MT_ACCOUNT/MT_PASSWORD 环境变量或隐藏输入提供,禁止写进配置、参数或命令历史。
离线(不连服务器,本轮均 PASS):
bash script/playable_gate_test.sh
node script/playable_soak_metrics_test.mjs
node script/playable_fault_proxy_test.mjs
node script/audit_playable_maps_test.mjs
(cd project && godot --headless --path . --script playable_harness_test.gd)
(cd project && godot --path . --script forest_mob_render_test.gd)
bash script/rendering_batch_test.sh
联网(需要重建候选包、test/playable/scenario.local.json 与测试账号;本轮未运行):
bash script/playable_test.sh --app "$PWD/build/export-playable-rc1/mtgodot-poc.app" --config test/playable/scenario.local.json --suite full --allow-gameplay --repeat 3
bash script/playable_soak.sh --app "$PWD/build/export-playable-rc1/mtgodot-poc.app" --config test/playable/scenario.local.json --allow-gameplay --duration-seconds 7200
node script/validate_playable_report.mjs --release-dir <本批次输出目录>
playable_soak.sh 行为:
- 先用 soak suite 校验配置和资源。缺少
--allow-gameplay时只做校验,返回 2,不启动客户端。 - 依次运行
exit-1..exit-N(suite playable,N ≥ 10)和soak-1(suite soak,墙钟时长 =soak.duration_seconds,超时 ≥ 时长 + 900s)。 - 写出只列本批次运行的
release-manifest.json(required_runs{playable:N, soak:1}),再聚合。 - 退出码:0 PASS / 1 FAIL / 2 BLOCKED / 124 超时。
5. 放行检查表对照(计划 §11)
| 检查项 | 当前 |
|---|---|
| INF-01/02 负向用例通过,必测项缺失不能 PASS | ✅ 离线通过 |
| 同一候选包 3 轮联网闭环 + 鼠标键盘证据 | ❌ BLOCKED(无候选包、无账号/夹具、无人工证据) |
| 四职业基础战斗、技能及异常路径 | ❌ BLOCKED(技能矩阵未确认) |
| 首测地图和树怪资源/动作/Metal 画面 | ⚠️ 离线组装通过;机位未确认、人工签核未做、实网未跑 |
| 2 小时、切图、故障恢复、窗口、退出次数 | ❌ BLOCKED(工具就绪,未实跑;切图/断网条件未确认) |
| P0/P1 清零 | ❌ 未知:没有实网运行,无法判定 |
| 所有 BLOCKED 明确处理 | ⚠️ 本文已列出;首测必测项不得以“已知问题”绕过 |
| 包哈希、签名、引擎来源、设备信息一致 | ❌ 需重建候选包后由运行器生成 |
| 已知 P2、未覆盖地图/装备/技能及未验收平台列出 | ⚠️ 本文 §3;未覆盖:首测三图以外的地图、Intel、官方模板 |
6. 需要环境负责人提供
- 自编译 arm64 引擎和重新导出的候选包(含本轮脚本),以及足够的磁盘空间。
test/playable/scenario.local.json:由scenario.example.json复制,填写 serverinfo 中的地址、角色槽位、map_key、安全路线、怪物/掉落 vnum;soak 需timeout_seconds ≥ duration_seconds + 900。- 专用测试账号(等级、装备、已学技能、掉落条件由负责人准备),以及
skill-cases.local.json中各职业的确认记录。 - 如需 STB-WARP/STB-DISCONNECT:合法传送入口的确认;确认可在 127.0.0.1 代理后运行,并核实传送是否下发直连地址。
- 树怪机位(平地/坡地/密林/传送点)的确认,以及 Metal 截图人工签核人。