Files
mtgodot-poc/docs/FIRST-MAC-PLAYABLE-STATUS.md

11 KiB
Raw Permalink Blame History

首个 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.app2026-09-08),早于本轮全部 playable 代码,不能作为候选包。
  • 本轮修改了 GDScript(包内测试入口、流程、指标、窗口适配),必须重新导出 PCK;若最终修复涉及 C++,还需 ./build.sh Release 重建扩展、重新签名打包。重建后对最终包重新跑退出门禁。
  • 官方 Release 模板的粒子退出警告未修复;必须显式使用经过验证的自编译 arm64 引擎。不宣称已修复官方模板或 Intel 平台。
  • 数据盘剩余约 7.5 GiB(99% 已用)。2 小时 soak 的 events.jsonlrss.jsonl、截图与日志会持续写盘,实跑前需由用户腾出空间;脚本不会自行清理任何文件或系统缓存。

3. 已知问题与限制

3.1 树怪动作(MAP-01

  • ent_trent2301/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 条 fallback2 个 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.gdMetalsuite=offline_syntheticFakeClient + 真实资源)本轮结果:

  • 689 帧,>50ms 14 帧,全部已归因(unattributed=0);>100msloading 6、gameplay 2。
  • gameplay 的 2 帧(119.5ms、237.0ms)都带 viewport_resize 标记,发生在测试主动切换窗口尺寸时。它们不属于正常游玩的重复交互,但在实网 soak 中要继续按“同一交互 3 次中 2 次 >100ms 即阻断”规则判定。
  • loading 段:同步模型构建 447746ms,切图 1861ms 与 4489ms。首次加载预算尚未固定(计划要求基线采集后再定,不临时放宽)。
  • CPU 蒙皮 8/16 角色时 p99 分别为 70.1ms/50.5ms90 帧窗口,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=nullunavailable)。Godot RenderingDevice 计数 843,616 KiB 不是系统显存,不据此判断显存泄漏。探针开销:每次采样 CPU 约 1.26µs;开/关探针 p50 差 −0.018ms,处于帧节奏噪声内。

3.3 稳定性工具的边界(STB-01)

  • 切图soak.warp.status 默认 unconfirmedSTB-WARP-01 为 BLOCKED。只有环境负责人确认合法传送入口(portal_cmreturn_portal_cmdestination_map_keycross_server、偶数且 ≥20 的往返次数)后才会走传送门;不以直接改客户端节点位置代替。跨服切图须核实测试服支持。
  • 真实断网soak.faults.status 默认 unconfirmedSTB-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-Nsuite playableN ≥ 10)和 soak-1suite soak,墙钟时长 = soak.duration_seconds,超时 ≥ 时长 + 900s)。
  • 写出只列本批次运行的 release-manifest.jsonrequired_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. 需要环境负责人提供

  1. 自编译 arm64 引擎和重新导出的候选包(含本轮脚本),以及足够的磁盘空间。
  2. test/playable/scenario.local.json:由 scenario.example.json 复制,填写 serverinfo 中的地址、角色槽位、map_key、安全路线、怪物/掉落 vnumsoak 需 timeout_seconds ≥ duration_seconds + 900
  3. 专用测试账号(等级、装备、已学技能、掉落条件由负责人准备),以及 skill-cases.local.json 中各职业的确认记录。
  4. 如需 STB-WARP/STB-DISCONNECT:合法传送入口的确认;确认可在 127.0.0.1 代理后运行,并核实传送是否下发直连地址。
  5. 树怪机位(平地/坡地/密林/传送点)的确认,以及 Metal 截图人工签核人。