- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
89 lines
11 KiB
Markdown
89 lines
11 KiB
Markdown
# 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 authority,40250 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 | PARTIAL:count 仅 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 和熔炼宝石 | GAP(custom 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 通过;验证本端抛竿/拉杆/鱼竿精炼 helper,40250 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。本轮完成审计并记录,未修改实现。
|