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

11 KiB
Raw Blame History

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,优先返回右侧,再返回左侧;钓鱼/持镐状态参与动作门控。
    • StartFishingStopFishingReactFishingCatchSuccessCatchFail 只切换角色动作/表情,不在客户端结算鱼或库存。
  • UserInterface/PythonNetworkStreamPhaseGame.cpp / Packet.h
    • SendFishingPacket 发送角度/5 的 byte 并追加 sequenceRecvFishing 对 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::fishingClassicSession::send_fishingGameClient::send_fishing 已能在游戏阶段发送角度/5;classic stream 会为已登记的 CG 包追加 sequence。
  • EntityStore/classic parser 已保存 GC_FISHINGGC_DIG_MOTIONM2Client::poll 发出 fishing_event/dig_motionNetWorld 会更新实体方向/动作,NetPlay 会更新本地主角钓鱼状态,ChatUI 展示 FISH/FAIL 文本。
  • Metin2World::get_fishing_rotation 已按 600cm、左右 10 度扫描 ATTRIBUTE_WATERfishing_water_test.gd 已在 A1 地图验证样本;water builder/animation 已存在。
  • project/fishing_mining_system.gdfishing_rod_reel_system.gdfishing_cooking_camp_system.gdmining_refinery_smelt_system.gd 直接实现概率、物品消耗、烤鱼 buff、矿石熔炼、宝石孔和库存写入。这些是本端 custom/server-like authority40250 Windows 客户端本身不做这些结算。

Branch matrix

场景 40250 当前端 结论
开始钓鱼 NEW_FishingCanFishingGetFishingRot→有效才发送;无水只提示 activate_fishing 有状态/死亡/技能门控并调用 get_fishing_rotation,再调用 native fishing PARTIAL:主路径接近,但真实装备动作模式、CanFishing 和服务端拒绝回滚未端到端证明
钓鱼角度 角色前方 600cm,左右 0..180、10 度,右侧优先,返回服务端角度 native world 用 6m、同样步长并做 MapCoord 转换 PARTIAL:算法接近;轴向、地图基准和 heading 转换需实机/固定样本对照,provider 缺失时当前端允许协议 fallback
取消钓鱼 只在 IsFishing 时发 0500ms 内不重复发送 cancel_fishing 使用 _fishing_active 和 500ms 节流 PARTIAL:状态来源是本地事件 flag,不是 actor IsFishing 的完整动作状态;断线/旧包/取消失败清理未覆盖
GC_FISHING START/STOP 按 fisher VID 查角色,调用 Start/Stop;找不到角色直接忽略 NetWorld 写 metadata、设置 fishing/waitNetPlay 对本地主角维护 _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.gdproject/water_reference_test.gd:通过;分别验证 A1 水属性/600cm heading 查询和当前 water geometry/material,不是 40250 像素级渲染证明。
  • project/netplay_test.gdproject/netbridge_test.gdproject/combat_fx_test.gdproject/chat_test.gdbuild/extension/net_entity_testbuild/extension/net_classic_session_testbuild/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.gdwater_reference_test.gdnetplay_test.gdcombat_fx_test.gdchat_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_MOTIONcount 目前只保存为 metadata/一次状态,未证明按参考实现重复排队 NAME_DIG 动作。
  • 本端钓鱼收益、烹饪、营火、采矿、熔炼、开孔和库存写入仍由本地脚本直接结算;40250 Windows 客户端只消费服务端结果,属于职责差异。
  • 水属性和水面几何有局部样本通过,但地图边界、单位、资源帧、动作/音效和断线/换图清理没有完整 live 证据。

Status update

本轮仍为 PARTIAL;完成钓鱼/采矿方向的合同审计并登记,未修改实现。

PARTIAL。当前端已经具备 40250 钓鱼/采矿协议骨架、角色动作入口、水属性扫描和水面构造;但持竿/持镐 live 门控、角色状态条件、采矿 count 动作队列和真实资源副作用证据不足,且钓鱼收益、烹饪、营火、熔炼、宝石与库存脚本承担了 40250 客户端没有承担的本地 authority。本轮完成审计并记录,未修改实现。