- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
109 lines
11 KiB
Markdown
109 lines
11 KiB
Markdown
# lifecycle.platform_release —— Windows/桌面窗口、导出、资源自包含、崩溃和发布门禁
|
||
|
||
状态:`PARTIAL`
|
||
|
||
本合同检查 40250 的 Win32 应用/窗口消息循环、全屏与窗口状态、资源自包含、版本/CRC 检查、异常退出、前后台处理和发布产物。判断标准是目标平台上是否具备相同的启动、窗口、资源、错误处理和退出副作用;“某个平台能导出”不能代替 Windows 40250 等价实现。
|
||
|
||
## 40250 参考调用链
|
||
|
||
- `EterLib/MSApplication.cpp` / `MSWindow.cpp`
|
||
- `CMSApplication::Initialize` 保存 HINSTANCE,`MessageLoop` 通过 `GetMessage/TranslateMessage/DispatchMessage` 驱动窗口;`WM_CLOSE` 转为退出消息。
|
||
- `CMSWindow` 注册 Win32 窗口类,创建 HWND,处理 `WM_SIZE`、`WM_ACTIVATEAPP`、显示/隐藏、窗口/客户区尺寸、鼠标坐标、居中、位置和全屏窗口尺寸。
|
||
- `UserInterface/PythonApplication.cpp` / `PythonApplicationProcedure.cpp`
|
||
- 初始化 800×600、60 FPS、相机/渲染/网络/音频/Granny 共享资源,并在非 Debug 模式安装 Eter 异常处理器。
|
||
- `WM_ACTIVATEAPP` 负责音量 Save/Restore 和全屏显示模式切换;`WM_SIZE`/`WM_EXITSIZEMOVE` 重建 back buffer;`WM_CLOSE` 按构建配置退出或进入退出流程。
|
||
- 统一处理 IME 消息、鼠标 capture、输入和窗口激活状态,主循环按固定帧/网络/场景更新顺序执行。
|
||
- `UserInterface/CheckLatestFiles.cpp`
|
||
- 可选编译 `CHECK_LATEST_DATA_FILES` 时启动低优先级线程,对 `CRC32_inc.h` 中的文件逐个检查可读性和 CRC;错误通过 Application error string 触发退出。
|
||
- `EterPack/*` / `Locale*`
|
||
- 运行时从 EterPack/locale 读取资源,并通过版本/资源链保证客户端数据完整;坏资源和版本不匹配有明确失败路径。
|
||
|
||
## 当前端实现映射
|
||
|
||
- `project/client_main.gd` / `project/app_flow.gd`
|
||
- 已有 Godot 主场景、AppFlow 状态机、登录→选人→游戏切换、断线重连和测试模式;客户端启动时配置协议、AssetPack 和资源根。
|
||
- Godot MainLoop 取代 Win32 `CMSApplication`,没有 40250 的 HWND 类注册、Win32 消息分派、back buffer resize 和全屏显示模式切换等价代码。
|
||
- `project/app_lifecycle.gd`
|
||
- 已处理 Godot 的暂停/恢复、窗口焦点、内存警告、Android 返回和桌面关闭信号,后台降 FPS 并绑定客户端/音频。
|
||
- 窗口失焦/重新获得焦点现在复用后台入口,分别执行音量保存、BGM/SFX 静音和恢复;关闭请求目前主要发信号,仍未形成与 40250 `WM_CLOSE`/`PostQuitMessage`/退出清理一致的统一出口。
|
||
- `project/asset_root.gd` / `asset_pack.gd` / `build-macos-client.sh` / `build-android.sh` / `project/export_presets.cfg`
|
||
- macOS 脚本将 assets/bgm 复制到 app Resources,Android 使用 `assets.zip`/`asset_index.txt`,AssetRoot 支持环境变量、散文件、包内资源和可执行文件旁资源。
|
||
- 当前没有 Windows 导出预设或 Windows GDExtension 构建脚本;资源链也不是 EterPack 的原生 eix/epk/CRC/更新流程,移动端还依赖外部 zip。
|
||
- `oracle/*`
|
||
- 有 Windows/Wine Granny 对拍工具和文档,但它是测试 oracle,不是客户端发布/崩溃/版本链。
|
||
|
||
## 分支等价矩阵
|
||
|
||
| 40250 判据/副作用 | 当前实现 | 结论 |
|
||
|---|---|---|
|
||
| Win32 HINSTANCE/HWND、窗口类、消息循环和 WM_CLOSE | Godot MainLoop/Window | 平台适配;没有 Windows 40250 同链实现,Windows 发布未闭合 |
|
||
| WM_SIZE/EXITSIZEMOVE、back buffer resize、窗口/客户区尺寸 | Godot 窗口系统自动处理,脚本未提供等价回调证据 | 部分等价;缺 Windows 原生尺寸/渲染设备恢复测试 |
|
||
| 前后台激活、全屏显示模式切换和音量保存恢复 | AppLifecycle 对 focus/pause 统一进入/退出后台,保存并恢复 BGM/SFX;全屏切换由 Godot 配置承担 | 部分等价;焦点音量副作用已有回归,Win32 全屏显示模式分支仍缺失 |
|
||
| 初始化/固定帧/网络/渲染/退出顺序 | AppFlow/GameScene/Godot scene tree 已有状态机 | 部分等价;没有与 `CPythonApplication::Process` 更新顺序和异常中止路径的生产级证据 |
|
||
| Eter 异常处理、Abort/Exit 和错误退出 | Godot 日志/进程退出,未发现专用异常处理器和 crash report | GAP;崩溃收集、错误字符串和资源回收链未对齐 |
|
||
| CheckLatestFiles CRC/可读性/低优先级线程更新检查 | 没有对应版本/CRC 更新线程 | GAP |
|
||
| EterPack/locale 自包含和坏资源失败回退 | AssetRoot/AssetPack/外部 assets.zip/手工复制 | 部分等价;资源来源可用,但原生 pack、版本校验、坏包/缺包门禁和 Windows 路径未闭合 |
|
||
| Windows 导出、GDExtension、资源自包含和启动验证 | 只有 macOS/Android 导出预设;macOS 导出探针通过 | GAP(Windows);其它平台基础导出通过 |
|
||
| 应用关闭、场景释放、音频/网络/模型清理 | queue_free、AppFlow 状态切换和局部生命周期测试 | 部分等价;没有 Windows 关闭消息、崩溃中止和整包资源释放门禁 |
|
||
|
||
## 已执行测试
|
||
|
||
- `project/app_flow_lifecycle_test.gd`:通过;覆盖 AppFlow 单一生命周期属主、登录/游戏断线重连和场景状态摘要。
|
||
- `project/bgm_test.gd`:通过;覆盖窗口失焦/获得焦点时 BGM/SFX 保存、静音和恢复;修复前该回归有 2 项失败。
|
||
- `project/dds_lifecycle_test.gd`:通过;20 次 DDS 解码后图像仍有效且节点计数不变。
|
||
- `godot --headless --path project --editor --quit`:退出码 0,脚本/GDExtension/项目结构校验完成;过程自动补建若干缺失 `.uid` 缓存文件,未发现阻断错误。
|
||
- `godot --headless --path project --export-release macOS /tmp/mtgodot-platform-audit.app`:退出码 0,macOS 导出流程通过;该结果不代表 Windows 导出可用。
|
||
|
||
## Deep audit round 2026-09-21
|
||
|
||
### Fresh regression results
|
||
|
||
- `app_flow_lifecycle_test.gd`、`dds_lifecycle_test.gd` 均退出码 0;覆盖生命周期属主和 DDS 资源解码后对象稳定性。
|
||
- `godot --headless --path project --editor --quit` 退出码 0,但编辑器自动重建了缺失的 `view_equipment_ui_test.gd.uid`,且在无 Android daemon 时出现连接拒绝提示;这不是 Windows 发布验证。
|
||
- 当前没有 Windows export preset/GDExtension 构建脚本;本轮没有把 macOS/Android 结果替代 Windows 发布通过。
|
||
|
||
### Static parity conclusion
|
||
|
||
- Godot MainLoop/AppLifecycle 能覆盖跨平台基础生命周期,且焦点音量保存/恢复已对齐 `WM_ACTIVATEAPP` 的可观察副作用,但没有 40250 Win32 HWND/WM_SIZE/WM_CLOSE、Eter 异常处理、CRC 更新检查和统一崩溃/退出链。
|
||
- 资源合同确认的 PCK/zip/loose 入口和当前自定义 pack 不能直接证明 Windows 自包含资源、坏包/缺包阻断、版本校验和路径大小写行为。
|
||
- 未发现可执行的 Windows 导出、Windows GDExtension 和启动/连接/地图/音频/退出冒烟门禁,因此平台发布合同继续保持 PARTIAL。
|
||
|
||
本轮仍为 `PARTIAL`,完成焦点激活链的实现和第三轮平台生命周期证据登记。
|
||
|
||
### Implementation fix round 2026-09-22T09:10Z
|
||
|
||
- 修复前新增的 `bgm_test.gd` 失焦回归出现 2 项失败:`WM_WINDOW_FOCUS_OUT` 不会静音 BGM/SFX,重新获得焦点也没有恢复备份音量。
|
||
- 参考 `CPythonApplication::WindowProcedure` 的 `WM_ACTIVATEAPP` 分支,`AppLifecycle._notification` 现在在 `APPLICATION_FOCUS_OUT`/`WM_WINDOW_FOCUS_OUT` 调用 `_enter_background()`,在对应 `*_FOCUS_IN` 调用 `_exit_background()`;`_bg` 守卫避免同时收到 pause/focus 通知时重复保存或恢复。
|
||
- 修复后 `bgm_test.gd`、`app_flow_lifecycle_test.gd`、`mouse_controller_test.gd`、`audio_miles_test.gd` 通过。全屏显示模式、WM_SIZE/back-buffer、Windows 导出和 Win32 异常/CRC 链仍为平台级未闭合项。
|
||
|
||
### Active EterLib device-core review
|
||
|
||
- `EterLib/GrpDevice.cpp`、`GrpScreen.cpp`、`GrpShadowTexture.cpp` 负责 D3D 设备/交换链创建、back buffer、lost/reset、屏幕尺寸和阴影纹理资源;这些不是单纯由窗口系统自动替代的 UI 行为,而是和渲染资源、全屏切换、设备丢失恢复绑定的状态机。
|
||
- 当前 Godot renderer 由引擎托管,`AppLifecycle` 只收到焦点/暂停/窗口通知,没有对应的设备创建、lost-device、reset、back-buffer 和 shadow texture 重建回调,也没有 Windows 目标上的验证矩阵。
|
||
- 因此本轮完成上述活跃 EterLib 图形设备源码静态核对;Godot editor/macOS 导出通过不能证明 Windows D3D/窗口/设备恢复一致,平台合同继续为 `PARTIAL`。
|
||
|
||
### Active EterLib graphics/runtime utility review
|
||
|
||
- `EterLib/GrpDetector.cpp` 枚举 adapter/display mode/pixel format/capability;`GrpBase.cpp` 维护 back buffer、camera/projection/view、default index buffer、dynamic vertex stream 和 screen effects;`StateManager.cpp` 保存/恢复 D3D render/texture/shader/transform/stream/index/material 状态。
|
||
- `GrpVertexBuffer*`、`GrpIndexBuffer*`、`GrpD3DXBuffer`、`GrpPixelShader`/`GrpVertexShader`、`GrpLightManager`、`GrpObjectInstance` 和 `GrpColorInstance` 分别管理 GPU buffer/shader/light/object transform/color transition;当前 Godot renderer 将这些责任下沉给引擎,没有对应 Windows lost/reset 和状态恢复 oracle。
|
||
- `Pool.h`、`Dynamic.h`、`Ref.h`/`ReferenceObject.cpp`、`Thread.cpp`、`Event.h`、`Mutex.h` 形成参考端池化、引用计数、线程、事件排序和同步清理基础;当前端虽有 queue_free/RefCounted/SceneTree,但池容量、引用自毁、线程 shutdown 和按时间排序事件没有同一可观察契约。
|
||
- 本轮完成 EterLib 图形/runtime utility 活跃文件静态核对,合同仍为 `PARTIAL`。
|
||
|
||
### Active UserInterface platform-host review
|
||
|
||
- `PythonSystem.cpp` 的配置文件、分辨率/频率枚举、窗口状态、音量/阴影/光标和 D3D adapter 查询,与当前 Godot `project/system_options.gd`/`app_lifecycle.gd` 的配置来源和窗口能力不同。
|
||
- `PythonApplicationLogo.cpp`/`MovieMan.cpp` 通过 DirectShow/DirectDraw surface 驱动开场视频并恢复 D3D 状态;当前项目没有等价的 Windows media surface/skip/fade 生命周期。
|
||
- `ProcessCRC`、`ProcessScanner`、`PythonExceptionSender` 与 GameGuard/HackShield/XTrap 提供参考端完整性/异常/安全发布门禁;当前没有相应的 Windows 组件和可执行验证。静态核对完成,但这些平台能力仍明确为 `PARTIAL/GAP`。
|
||
|
||
## 已确认差异和未验证项
|
||
|
||
1. 增加 Windows 导出预设、Windows GDExtension 构建和资源自包含脚本,至少验证启动、连接、地图/模型/音频资源加载和退出。
|
||
2. 建立平台窗口合同:窗口大小/客户区、resize、全屏/窗口化、激活/失焦、关闭、鼠标坐标和输入法消息的运行时快照。
|
||
3. 建立发布资源门禁:资源清单、哈希/版本、缺包/坏包/权限失败、路径大小写和外部 zip/PCK 解包失败均必须可诊断并阻断启动。
|
||
4. 补充崩溃/异常/退出测试和诊断日志;区分正常关闭、网络断开、资源失败、GDExtension 加载失败和 native crash。
|
||
5. 将 Windows、macOS、Android 的导出产物、资源来源、版本号和回归测试结果写入发布报告,避免把单平台导出通过误记为完整发布通过。
|
||
|
||
## 下一轮验证入口
|
||
|
||
- `world.environment_weather` 是当前唯一尚未逐分支审计的映射域;完成后生成全清单覆盖报告,再进入按优先级修复阶段。
|