Files
mtgodot-poc/audit/contracts/world.dungeon-activity.md
T
shenandshen c93894313a fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧
- inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域
- 包含其他累积的功能开发和测试文件
2026-09-21 16:38:59 -07:00

89 lines
10 KiB
Markdown
Raw 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.
# world.dungeon_activity
## Scope
审计 `GC_DUNGEON` 目标点、地下城事件/计时、`DUNGEON_RESULT` 结果窗口、地图导航提示、镜头/屏幕效果,以及当前端额外提供的 Boss、排行和具体副本 helper。判断标准是当前端是否复现 40250 Windows 客户端的协议字段、目标点状态、到达/重复提示、结果展示和中断清理;服务端才拥有副本奖励、Boss 血量、排行和副本规则,当前端本地计算这些内容不能作为 40250 客户端 parity 证明。
## Reference call chain
- `UserInterface/PythonNetworkStreamPhaseGame.cpp`
- `RecvDungeon` 读取 `TPacketGCDungeon``TIME_ATTACK_START` 分支在 40250 中不启动本地计时,`DESTINATION_POSITION` 读取两个坐标并调用 `CPythonPlayer::SetDungeonDestinationPosition`
- `PythonEventManager.cpp``DUNGEON_RESULT` 分支把九个整数交给 `interface.ShowDungeonResult`;客户端展示结果,不在此处结算奖励。
- `UserInterface/PythonPlayer.cpp` / `PythonPlayer.h`
- `SetDungeonDestinationPosition` 保存全局像素/厘米目标,立即调用 `AlarmHaveToGo`;更新时用整数 Manhattan 距离判断 `< 10000` 到达,未到达且超过 20 秒再次提示,并在到达时清空目标。
- `AlarmHaveToGo` 创建 `effect/etc/compass/appear_middle.mse`,朝目标方向旋转罗盘提示。
- `UserInterface/PythonEventManager.cpp` / `GameLib/GameEventManager.cpp`
- 事件窗口负责结果 UI、等待和清理;`GameEventManager` 的相关路径是屏幕波动/运动效果,不是 Boss 或排行 authority。
- `GameLib/MapManager.cpp` / `Packet.h` / `PythonNetworkStreamPhaseGame.h`
- 提供地图/副本协议常量和包布局;副本目标与结果由服务端包驱动,客户端没有本地奖励、Boss HP 或排行榜结算。
## Current call chain
- native `EntityStore::apply` 已解析 `GC_DUNGEON` 的 subheader 和目标坐标;`M2Client::poll` 发出 `dungeon_event``M2Client::request_dungeon`/`ClassicSession::send_dungeon` 能发送请求。
- `project/dungeon_state.gd` 已实现 `TIME_ATTACK_START` 不启动本地计时、目标坐标转换、立即提示、10,000 cm Manhattan 到达阈值、20 秒重复 alarm、到达清理和 `world_reset` 清理。
- `project/ui/dungeon_result_ui.gd` 已接收九个字段并呈现击杀、隐藏目标、药水、复活、完成、时间和经验等结果;`game_scene.gd` 已连接 `dungeon_result_requested`
- `project/world_boss_system.gd``project/dungeon_ranking_system.gd``project/spider_dungeon_system.gd``project/flame_dungeon_razador_system.gd``project/endless_spire_dungeon_system.gd` 是当前端额外的本地规则/authority helper。40250 Windows 客户端没有对应的本地 Boss HP、掉落、排行或副本奖励实现,不能把这些 helper 的单元测试当成 parity PASS。
## Branch matrix
| 场景 | 40250 | 当前端 | 结论 |
|---|---|---|---|
| 地下城请求 | `__CanActMainInstance`/游戏阶段检查后发送对应请求;结果由服务端包驱动 | native 只做 `is_in_game` 和 session send;没有完整动作门控、请求去重和拒绝回滚证据 | PARTIAL |
| `TIME_ATTACK_START` | `RecvDungeon` 消费包但分支为空,不凭客户端包启动计时 | `DungeonState` 记录 subheader 但不启动本地计时 | PASS(已覆盖的分支) |
| 目标点回包 | 读取 x/y→`SetDungeonDestinationPosition`→立即 compass alarm | `GC_DUNGEON``dungeon_event`→坐标转换→`destination_changed``alarm_requested` | PARTIAL:协议/状态接近,但 alarm 没有在 `game_scene.gd` 接到实际 compass/effect 消费者 |
| 目标点重复提示 | 未到达时每 20 秒 `AlarmHaveToGo`,使用参考 `.mse` 资源并按目标方向旋转 | `DungeonState` 每 20 秒发 `alarm_requested`,但当前没有实际资源效果调用 | GAP:信号存在,视觉副作用缺失 |
| 目标到达 | Manhattan `< 10000` 后清除目标并停止提示 | 同阈值和清理信号已实现 | PASS(状态算法) |
| 地图切换/断线 | 玩家状态重置并清理目标提示 | `world_reset` 清理目标;实际断线、重连、旧包乱序未完整验证 | PARTIAL |
| 副本结果 | `DUNGEON_RESULT` 九个整数交给 `ShowDungeonResult`,仅展示服务端结果 | `QuestDialog``dungeon_result_requested``DungeonResultUI` 展示九字段 | PARTIAL:展示链存在,但真实 `DUNGEON_RESULT`→UI 回包和关闭/重复/中断未端到端覆盖 |
| 奖励、Boss、排行 | 客户端不计算副本奖励、Boss HP、掉落或排行榜权威 | 本地 helper 直接推进 Boss 阶段/掉落/库存奖励和排行统计 | GAPcustom authority):与 40250 客户端职责不一致 |
| 屏幕波动/地图事件 | `GameEventManager` 处理屏幕波动和运动事件 | 当前副本合同没有证明该引用链的实际资源/中断效果 | PARTIAL:不能用 Boss/排行 helper 代替原版事件效果 |
## Implementation-equivalence matrix
| 项目 | 状态 | 证据/限制 |
|---|---|---|
| Preconditions | PARTIAL | native 游戏阶段、包长度和目标字段检查存在;请求动作门控、重复请求、服务器拒绝和活动阶段限制未与 40250 等价证明 |
| Branch structure | PARTIAL | dungeon subheader、目标、到达、结果主分支存在;alarm 没有实际 compass 消费者,结果回包和中断分支证据不足 |
| Algorithms/formulas | PARTIAL | 目标坐标转换、10,000 cm Manhattan 阈值、20 秒间隔与参考一致;实际 `.mse` 方向/资源效果缺失,本地 Boss/排行公式属于额外 authority |
| State transition order | PARTIAL | 包→native event→目标状态→HUD 的顺序接近;alarm 只到 signalworld reset/重连/旧包清理和结果窗口生命周期未闭合 |
| Constants/units | PARTIAL | subheader 0/1、10,000 cm、20 秒和九字段结果存在;server cm→Godot world 的轴/地图基准需实机验证,Boss/排行常量不能视为 40250 客户端常量 |
| Timing/event sources | PARTIAL | 目标初次与 20 秒 alarm、到达检测存在;实际 compass effect、结果重复包、断线/切图/重连和计时事件未覆盖 |
| Resource/data sources | PARTIAL | 结果字段来自服务端包,目标坐标来自 `GC_DUNGEON`;参考 `appear_middle.mse` 没有实际接入,Boss/排行使用本地硬编码表 |
| Protocol side effects | PARTIAL | `GC_DUNGEON` parser、请求和结果 UI 入口存在;未证明请求被正确门控,alarm/结果的完整 UI/音效/资源副作用不完整 |
| Interruption/failure/cleanup | GAP | 目标 alarm、结果 UI、Boss/排行 helper 在拒绝、断线、乱序、地图切换、重复结果和重连时的恢复没有完整回归;本地 helper 可绕开服务器 authority |
## Regression evidence
- `project/dungeon_state_test.gd`:通过,覆盖目标状态、坐标、到达阈值和 alarm 计数;没有证明实际 compass `.mse` 消费者已连接。
- `project/dungeon_result_test.gd`:通过,覆盖九字段结果窗口的本地展示;没有真实 `DUNGEON_RESULT` native 回包、重复结果、断线和关闭时序。
- `project/test_dungeon_ranking_parity.gd``project/test_spider_dungeon_parity.gd``project/test_spider_dungeon_key_parity.gd``project/test_flame_dungeon_razador_parity.gd``project/test_endless_spire_dungeon_parity.gd`:通过,验证当前端自定义 helper;40250 客户端没有同等本地 authority,因此不能证明 Windows 客户端 parity。
- `build/extension/net_entity_test``build/extension/net_classic_session_test``build/extension/net_classic_wire_test`:通过基础 parser/session/wire 检查;未覆盖 alarm 视觉副作用、目标乱序/旧包、结果 live UI、断线重连和 server rejection。
### Active GameLib dungeon-block review
- `GameLib/DungeonBlock.cpp`/`.h` 以资源 `CGraphicThing` 建立多个 `CDungeonModelInstance`,维护 deformable vertex buffer、bounding sphere、model intersection、static collision data、height instance、Update/Render/Shadow 和 Destroy;它是地图对象碰撞/渲染生命周期的一部分。
- 当前副本 helper 与 dungeon HUD 主要实现目标、结果和本地状态,没有 40250 `DungeonBlock` 的多模型/碰撞/高度/阴影对象链;`DUNGEON_RESULT` 测试通过不能覆盖该地图对象资源语义。
- 本轮完成 `DungeonBlock` 活跃源码静态核对,地下城合同继续为 `PARTIAL`
## Status
## Deep audit round 2026-09-21
### Fresh regression results
- `dungeon_state_test.gd``dungeon_result_test.gd``test_dungeon_ranking_parity.gd``test_spider_dungeon_parity.gd``test_spider_dungeon_key_parity.gd``test_flame_dungeon_razador_parity.gd``test_endless_spire_dungeon_parity.gd` 均退出码 0;对应本地断言为 30/30、32/32、34/34、31/31、22/22。
- `net_entity_test``net_classic_session_test``net_classic_wire_test` 均退出码 0。
### Static parity conclusion
- `TIME_ATTACK_START`、目标坐标转换、10,000 cm Manhattan 到达阈值和 20 秒 alarm 状态算法已接近参考实现;但 `alarm_requested` 没有实际消费 `appear_middle.mse`、方向旋转和音效的生产链。
- `DUNGEON_RESULT` 九字段展示窗口只有本地 UI/假回包证据,尚未证明真实 native 回包到窗口的重复、关闭、断线和重连时序。
- Boss、排行、蜘蛛/火焰/无限塔 helper 在本端直接维护阶段、掉落、奖励或统计;这些不是 40250 Windows 客户端 authority,不能把其单元测试计为 parity 通过。
- 请求门控、拒绝回滚、旧包/乱序、地图切换和重连清理仍缺 live 证据。
### Status update
本轮仍为 `PARTIAL`;完成三个地下城/活动方向的合同审计并登记,未修改实现。
`PARTIAL`。当前端已经具备 `GC_DUNGEON` 目标点的主要 parser、坐标状态和与 40250 一致的 Manhattan/20 秒算法,也有结果窗口骨架;但 40250 的 compass `.mse` alarm 没有实际消费者,结果链缺少 live 回包时序证据,且 Boss、排行和具体副本 helper 是当前端本地 authority,不是 40250 Windows 客户端实现。本轮完成审计并记录,未修改实现。