Files
mtgodot-poc/audit/contracts/world.fishing-mining.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
11 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.fishing_mining
## Scope
审计 40250 Windows 客户端的钓鱼输入门控、`GetFishingRot` 水面扫描、`CG_FISHING/GC_FISHING` 状态与角色动作、`GC_DIG_MOTION` 采矿动作、地图水面/水高和当前端扩展的钓鱼、开鱼、烹饪、营火、采矿、熔炼脚本。判断标准是当前端是否统一复现 40250 客户端的输入条件、坐标/单位、协议、角色动画、事件顺序和资源副作用;服务端概率、掉落、库存、熔炼与增益规则不能因被写入 Godot helper 就当成 Windows 客户端 parity。
## Reference call chain
- `UserInterface/PythonPlayerInput.cpp`
- `NEW_Fishing`:无主角色则返回;已在钓鱼时发送 `CG_FISHING(0)`;否则要求 `CanFishing()`,调用 `GetFishingRot`,水面无效时只触发 `OnFishingWrongPlace`,有效时发送角度。
- `NEW_CancelFishing` 只在 `IsFishing()` 时发送取消包,并有 500ms 节流。
- `UserInterface/InstanceBaseMotion.cpp` / `InstanceBase.cpp`
- `GetFishingRot` 以角色当前位置、朝向和 600cm 距离,按左右 0..180 度、每 10 度扫描 `ATTRIBUTE_WATER`,优先返回右侧,再返回左侧;钓鱼/持镐状态参与动作门控。
- `StartFishing``StopFishing``ReactFishing``CatchSuccess``CatchFail` 只切换角色动作/表情,不在客户端结算鱼或库存。
- `UserInterface/PythonNetworkStreamPhaseGame.cpp` / `Packet.h`
- `SendFishingPacket` 发送角度/5 的 byte 并追加 sequence`RecvFishing` 对 START/STOP/REACT/SUCCESS/FAIL 按 `info` 查角色并切换动作,FISH 按 item vnum 走 `OnFishingNotify/OnFishingSuccess`;未知角色包直接忽略,未知物品也不凭空入包。
- `RecvDigMotionPacket` 查主角色和目标,朝目标转身,再按 `count` 重复 `NAME_DIG` 动作。
- `GameLib/AreaTerrain.cpp` / `MapOutdoorWater.cpp`
- 地形通过水属性图和水高表提供 `ATTRIBUTE_WATER`/water height;水面渲染使用地图 water 数据和循环纹理,不负责钓鱼收益。
## Current call chain
- native `M2Client::fishing``ClassicSession::send_fishing``GameClient::send_fishing` 已能在游戏阶段发送角度/5;classic stream 会为已登记的 CG 包追加 sequence。
- `EntityStore`/classic parser 已保存 `GC_FISHING``GC_DIG_MOTION``M2Client::poll` 发出 `fishing_event`/`dig_motion``NetWorld` 会更新实体方向/动作,`NetPlay` 会更新本地主角钓鱼状态,`ChatUI` 展示 FISH/FAIL 文本。
- `Metin2World::get_fishing_rotation` 已按 600cm、左右 10 度扫描 `ATTRIBUTE_WATER``fishing_water_test.gd` 已在 A1 地图验证样本;water builder/animation 已存在。
- `project/fishing_mining_system.gd``fishing_rod_reel_system.gd``fishing_cooking_camp_system.gd``mining_refinery_smelt_system.gd` 直接实现概率、物品消耗、烤鱼 buff、矿石熔炼、宝石孔和库存写入。这些是本端 custom/server-like authority40250 Windows 客户端本身不做这些结算。
## Branch matrix
| 场景 | 40250 | 当前端 | 结论 |
|---|---|---|---|
| 开始钓鱼 | `NEW_Fishing``CanFishing``GetFishingRot`→有效才发送;无水只提示 | `activate_fishing` 有状态/死亡/技能门控并调用 `get_fishing_rotation`,再调用 native fishing | PARTIAL:主路径接近,但真实装备动作模式、CanFishing 和服务端拒绝回滚未端到端证明 |
| 钓鱼角度 | 角色前方 600cm,左右 0..180、10 度,右侧优先,返回服务端角度 | native world 用 6m、同样步长并做 MapCoord 转换 | PARTIAL:算法接近;轴向、地图基准和 heading 转换需实机/固定样本对照,provider 缺失时当前端允许协议 fallback |
| 取消钓鱼 | 只在 `IsFishing` 时发 0,500ms 内不重复发送 | `cancel_fishing` 使用 `_fishing_active` 和 500ms 节流 | PARTIAL:状态来源是本地事件 flag,不是 actor `IsFishing` 的完整动作状态;断线/旧包/取消失败清理未覆盖 |
| `GC_FISHING START/STOP` | 按 fisher VID 查角色,调用 Start/Stop;找不到角色直接忽略 | NetWorld 写 metadata、设置 `fishing`/`wait`NetPlay 对本地主角维护 `_fishing_active` | PARTIAL:状态/动作骨架存在;metadata/placeholder 与真实角色 motion 资源、重复/乱序包语义仍需验证 |
| `REACT` | 仅在角色仍钓鱼时加 fish emoticon 并 ReactFishing | 当前端显示 emoticon 并切 `fishing_react`,未严格以 actor 状态确认 | PARTIAL:缺少同等 `IsFishing` 条件和清理时序证据 |
| `SUCCESS/FAIL` | 切 catch/fail 动作;FAIL 对主角色触发失败 UI | 当前端切动作并在 ChatUI 展示失败文本 | PARTIAL:动作/文本入口有,资源、音效、重复结果和主角色判断未完整覆盖 |
| `FISH` 结果 | info=0 显示 unknown;有 item 且能查 item data 才通知;按角色仍钓鱼决定 notify/success | ChatUI 用 proto 查询并展示;NetWorld/NetPlay 将 FISH 作为 UI-only | PARTIAL:未知物品忽略接近参考,但 item type、主角色状态和 live inventory 回包未闭合 |
| 采矿动作 | `GC_DIG_MOTION` 查 VID/目标、朝目标转身、按 count 重复 dig motion | native parser→NetWorld 转身并只设置一次 `dig` 状态、保存 count | PARTIALcount 仅 metadata,未证明按 count 排队多个 NAME_DIG 动作;目标缺失/动作结束清理未覆盖 |
| 矿镐/攻击门控 | `IsHoldingPickAxe` 影响 CanAttack/CanUseSkill/动作模式 | 当前 `FishingMiningSystem` 能识别矿镐,但未作为 live NetPlay 的统一攻击/技能门控证据 | PARTIAL/GAP:识别 helper 存在,网络动作门控未闭合 |
| 水属性/水高/水面 | ATTRIBUTE_WATER、水高和 water.wtr 由地图资源读取与渲染 | native world 读取 attr、水高并构造 water mesh/动画 | PARTIAL:结构已存在,尚未证明所有 map chunk 边界、water height 单位和纹理帧与 40250 像素级一致 |
| 钓鱼/采矿收益 | 客户端只展示服务端 item/状态,不计算概率和库存 authority | 本地脚本直接 roll、扣 bait、写 inventory、发 fish/ore、烹饪 buff 和熔炼宝石 | GAPcustom authority):不能与 40250 Windows 客户端实现宣称统一 |
## Implementation-equivalence matrix
| 项目 | 状态 | 证据/限制 |
|---|---|---|
| Preconditions | PARTIAL | 游戏阶段、网络状态、水面扫描和部分本地动作门控存在;真实 `CanFishing`/装备形态、持镐对攻击/技能的统一门控、服务端拒绝未完整接入 |
| Branch structure | PARTIAL | START/STOP/REACT/SUCCESS/FAIL/FISH、DIG_MOTION、water attribute 主分支存在;REACT 的 actor 状态条件、DIG count 队列和未知/乱序清理不等价 |
| Algorithms/formulas | PARTIAL | 600cm/10度扫描、右优先和 5 度网络量化接近参考;收益概率、开鱼、采矿、熔炼和 buff 是自定义本地算法,不是 40250 client 算法 |
| State transition order | PARTIAL | 回包→parser→NetWorld/NetPlay/UI 大体存在;真实角色动作完成、FISH 与 IsFishing 判断、拒绝/重连和 inventory 回包顺序未闭合 |
| Constants/units | PARTIAL | 600cm、10度、180度、500ms、角度/5、ATTRIBUTE_WATER 和 packet layout 有证据;MapCoord 轴向/水高单位和本地 VNUM/概率表缺 reference client 证据 |
| Timing/event sources | PARTIAL | 取消节流和网络事件队列存在;服务端 fishing reaction 时序、动作结束、重复/延迟 GC 包、矿动作 count 时序未覆盖 |
| Resource/data sources | PARTIAL | A1 attr/water mesh、fish emoticon 和角色状态入口存在;全部地图 water.wtr、实际 fishing motion/effect/sound 和 item proto 对应关系未完整验证 |
| Protocol side effects | PARTIAL | CG/GC fishing、GC dig parser 和 sequence/frame 存在;缺 live wrong-place、CanFishing、server result、item inventory/音效端到端证据 |
| Interruption/failure/cleanup | GAP | 断线、换图、角色消失、错误 item、重复 FISH/FAIL、采矿 count 中断及本地 helper 的 optimistic inventory/buff 回滚没有完整证明 |
## Regression evidence
- `project/test_fishing_mining_parity.gd`:26/26 通过;验证本地装备识别、概率 helper、开鱼/蚌壳和矿脉表,不是 40250 live client 回包证据。
- `project/test_fishing_rod_reel_parity.gd`:33/33 通过;验证本端抛竿/拉杆/鱼竿精炼 helper40250 Windows client 不在本地执行这些收益和持久化规则。
- `project/test_fishing_cooking_camp_parity.gd`:23/23 通过;验证本地营火、烤鱼和 buff 写入,属于 custom authority。
- `project/test_mining_refinery_smelt_parity.gd`:21/21 通过;验证本地熔炼、开孔和镶嵌,不能证明 Windows client parity。
- `project/fishing_water_test.gd``project/water_reference_test.gd`:通过;分别验证 A1 水属性/600cm heading 查询和当前 water geometry/material,不是 40250 像素级渲染证明。
- `project/netplay_test.gd``project/netbridge_test.gd``project/combat_fx_test.gd``project/chat_test.gd``build/extension/net_entity_test``build/extension/net_classic_session_test``build/extension/net_classic_wire_test`:覆盖 fishing/dig event 的部分状态、动作和 wire;未覆盖 actor motion 资源、REACT `IsFishing`、DIG count 多动作、服务端拒绝、乱序、断线/切图和 live inventory。
## Status
## Deep audit round 2026-09-21
### Fresh regression results
- `test_fishing_mining_parity.gd` 26/26、`test_fishing_rod_reel_parity.gd` 33/33、`test_fishing_cooking_camp_parity.gd` 23/23、`test_mining_refinery_smelt_parity.gd` 21/21 均通过。
- `fishing_water_test.gd``water_reference_test.gd``netplay_test.gd``combat_fx_test.gd``chat_test.gd` 通过;native entity/session/wire 三项通过。
- `netbridge_test.gd` 仍失败 3 项(实体节点、mount 子节点和主实体可见性),并有 5 个 ObjectDB 泄漏;这说明 fishing/dig 事件与通用实体桥接尚未闭合。
### Static parity conclusion
- 600cm 水面扫描、10 度步长、右侧优先、500ms 取消节流和 fishing/dig 包骨架存在,但 `CanFishing`/持竿动作状态、REACT 的 `IsFishing` 条件和服务端拒绝回滚不等价。
- `GC_DIG_MOTION``count` 目前只保存为 metadata/一次状态,未证明按参考实现重复排队 `NAME_DIG` 动作。
- 本端钓鱼收益、烹饪、营火、采矿、熔炼、开孔和库存写入仍由本地脚本直接结算;40250 Windows 客户端只消费服务端结果,属于职责差异。
- 水属性和水面几何有局部样本通过,但地图边界、单位、资源帧、动作/音效和断线/换图清理没有完整 live 证据。
### Status update
本轮仍为 `PARTIAL`;完成钓鱼/采矿方向的合同审计并登记,未修改实现。
`PARTIAL`。当前端已经具备 40250 钓鱼/采矿协议骨架、角色动作入口、水属性扫描和水面构造;但持竿/持镐 live 门控、角色状态条件、采矿 count 动作队列和真实资源副作用证据不足,且钓鱼收益、烹饪、营火、熔炼、宝石与库存脚本承担了 40250 客户端没有承担的本地 authority。本轮完成审计并记录,未修改实现。