Files
mtgodot-poc/audit/contracts/world.mount-pet-polymorph.md
T
shenleiandClaude Opus 5 a989b8f19b chore: delete 106 unreachable *_system.gd and their parity tests
These files were loaded only by their own test_*_parity.gd and never by
the runtime (transitively checked, incl. client_phase_integration_system).
Removes 76 manifest implementation/evidence references across 18
contracts; contract docs get a note that conclusions based on them are
void. Live systems kept: chest, consumable, item_attr, metin_socket,
whisper_chat.

Full headless suite: no new failures (7 failing + 5 headless-hanging
render tests are identical before the deletion).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 17:51:52 +09:00

11 KiB
Raw Blame History

world.mount_pet_polymorph

Scope

审计 40250 Windows 客户端的角色 mount_vnum 接收、GC_MOUNT 上下马状态、骑乘/步行 motion mode、旋转速度、骑乘攻击/技能限制、变身 affect/装备遮挡,以及当前端的马匹、宠物、变身和马上技能脚本。判断标准是客户端是否与 40250 的实体字段、动作模式、门控和回包顺序统一;服务端拥有马匹等级、宠物属性、变身持续和技能伤害 authority,当前端本地 helper 能独立推进规则不能作为 parity 证明。

Reference call chain

  • UserInterface/PythonNetworkStreamPhaseGameActor.cpp
    • Character add/additional/update packet 携带 dwMountVnum,交给 CInstanceBase;角色创建时非零 mount vnum 会进入 MountHorse
  • UserInterface/PythonNetworkStreamPhaseGame.cpp / Packet.h
    • RecvMountPacket 读取 vid/mount_vid/pos/x/y,按角色存在性处理上下马;该版本的 Ride/Unride/SetRidingVehicleIndex 调用被注释,不能凭空扩大为客户端结算。
  • UserInterface/InstanceBase.cpp / InstanceBaseMotion.cpp
    • MountHorse/DismountHorse 更新 horse actor、动作模式和 rotation speed;持镐、钓竿、变身、婚纱、坐骑会影响 motion mode、CanAttackCanUseSkill 和武器/发型遮挡。
    • CanAttackHorseLevel 通过 horse actor 等级限制普通攻击;新的坐骑/马术技能可由 PythonPlayer 的 can-use 门控决定。
  • UserInterface/PythonPlayer.cpp / PythonPlayerSkill.cpp / InstanceBase.h
    • 客户端消费 NEW_AFFECT_POLYMORPH/NEW_AFFECT_MOUNT 等状态和 skill level,阻止不允许的动作;不在客户端本地计算宠物战力、掉落、马匹成长或服务端技能伤害。
  • 40250 ClientVS22 全树搜索未找到独立宠物 follow/combat authority 实现;ITEM_TYPE_POLYMORPH 和 polymorph skill/affect 常量存在,但其客户端职责是展示/门控/动作。

Current call chain

  • native classic parser 已将角色 add/update、additional info 和 GC_MOUNTmount_vnum 写入 EntityStoreM2Client::poll 发出 mount_changed,实体 getter 能提供该字段。
  • project/net_world.gd 保存 mount_vnum metadata、根据 mount 选择旋转速度并更新实体字段;project/net_play.gd 根据 mount/poly/weapon 刷新 local motion mode、骑乘攻击等级门和技能上下文;EquipModel 只用 mount 状态处理武器双手规则。
  • project/horse_system.gdhorse_combat_system.gdhorse_level_growth_system.gdmounted_combat_skill_system.gdpet_companion_system.gdclassic_pet_system.gdpolymorph_system.gdpolymorph_marble_system.gd 在本地维护召唤、骑乘、耐力、宠物跟随/增益、变身时限和技能伤害。
  • 当前代码搜索未发现 mount_vnum 被用于创建/挂接实际坐骑模型或 saddle actor 的实现;大多数 live 网络路径只保留 metadata/motion mode,宠物和变身 helper 也没有对应的 native server affect/entity 回包闭环。

Branch matrix

场景 40250 当前端 结论
角色创建带 mount add packet 的 dwMountVnumMountHorse→动作/挂点;服务器字段权威 parser/store 保存 mountNetWorld 只写 metadata,未发现 mount actor/model attach GAP:状态字段有,视觉实体链缺失
GC_MOUNT 上马 读取包,角色存在时进入 Ride 分支(本版本 Ride 调用被注释),主角色 vehicle index 也被注释 parser 更新实体 mount_vnum,发 mount_changedNetPlay 刷 motion mode PARTIAL:字段/动作门有,需保持与该版本注释语义一致,不能自行增加本地 ride authority
GC_MOUNT 下马 mount_vid==0,服务端位置字段交给 Unride(本版本调用被注释) mount 字段置零并刷新 motion;没有验证 x/y 下马位置和模型清理 PARTIAL
骑乘旋转/移动 MountHorse 使用约 300°/s rotation,步行约 1200°/shorse motion mode 参与根运动 NetPlay/NetWorld 有 horse rotation speed 和 mounted modeNetWorld 对有 mount 的真模型不推送 motion speeds PARTIAL:常量入口接近,但实际 horse motion/模型不存在,远端骑乘 root motion 不完整
普通攻击 CanAttack 受 horse level、婚纱、持镐和 actor lock 限制;等级 1 坐骑不能攻击 NetPlay 有 _can_attack_horse_level 和部分新坐骑 skill gate PARTIAL:部分映射存在,真实 horse actor 等级、服务器拒绝、动作/包副作用未完整证明
技能/武器模式 CanUseSkillSetMotionMode 受变身、婚纱、持镐、坐骑、武器类型影响 local motion mode/skill context 有 mount/poly 字段,但 poly 字段未由 native entity 回包提供 PARTIAL/GAP
变身 NEW_AFFECT_POLYMORPH/shape/parts 影响模型、装备遮挡、技能/动作门;状态来自服务器 affect/character data polymorph_system.gd 直接启动、加攻防、计时、死亡取消;EquipModel 明确 _is_poly() 恒 false GAP:本地 helper 有规则,live 视觉和 native affect 闭环缺失
宠物 40250 ClientVS22 未发现独立宠物 follow/combat authority pet_companion_system.gd/classic_pet_system.gd 本地召唤、跟随和属性加成 GAPcustom feature/authority):不能标记为 40250 parity
马匹成长/耐力/喂养/马上技能 服务端/脚本权威;客户端只消费字段和动作 本地 helper 直接计算成长、耐力、技能 CD、伤害、库存消耗 GAPcustom authority

Implementation-equivalence matrix

项目 状态 证据/限制
Preconditions PARTIAL native stage/VID/mount 字段、部分死亡/技能/新坐骑门存在;角色存在、horse actor、变身 affect 和 server rejection 的完整门控未闭合
Branch structure PARTIAL add/update/mount parser、动作模式、攻击范围/等级入口存在;ride/unride 位置、实际 mount attach、poly entity field 和 pet 分支不等价
Algorithms/formulas PARTIAL motion mode/旋转速度和部分 mount level 表有映射;马匹成长、耐力、宠物加成、变身加攻防、马上技能伤害是本地 custom 算法
State transition order PARTIAL server actor data→EntityStore→mount_changed→motion mode 顺序大体存在;模型 attach/detach、poly affect→装备遮挡、断线/重连和死亡清理未闭合
Constants/units PARTIAL mount_vnum、马等级表、300/1200°/s、技能/affect 常量有证据;本地宠物/成长/耐力/伤害常量没有 40250 client authority 依据
Timing/event sources PARTIAL mount signal、motion refresh、死亡/技能上下文存在;实际 ride animation、poly affect duration、server updates、重复/乱序包未覆盖
Resource/data sources GAP 当前搜索未找到 mount_vnum→horse model/saddle actor 挂接;真实 horse/poly motion 资源存在与否、路径和绑定关系没有端到端证明
Protocol side effects PARTIAL actor/mount packet parser 和 getter 存在;没有客户端等价的宠物/马战本地结算,也缺 live 上下马/变身/拒绝/重连 packet sequence
Interruption/failure/cleanup GAP 下马、角色消失、地图切换、死亡、变身过期、宠物过期、断线重连和 mount/poly model 清理未完整回归;本地 helper 可绕开服务器 authority

Regression evidence

  • project/test_mount_horse_parity.gd:24/24 通过,覆盖本地马匹命令/范围 helper;不证明 GC_MOUNT live actor/model attach。
  • project/test_horse_combat_parity.gd32/32、test_horse_level_growth_parity.gd42/42、test_mounted_combat_skill_parity.gd:25/25 通过;这些测试验证本地骑乘战斗、成长、耐力和技能 helper,不能作为 40250 Windows client parity。
  • project/test_pet_companion_parity.gd40/40、test_classic_pet_parity.gd:31/31 通过;验证本地宠物状态/序列化,40250 ClientVS22 未发现同等宠物 authority。
  • project/test_polymorph_parity.gd25/25、test_polymorph_marble_parity.gd:32/32 通过;验证本地变身 helper,但未覆盖 native affect/entity、模型 shape、装备遮挡和 server lifetime。
  • project/netplay_test.gdproject/netbridge_test.gdbuild/extension/net_entity_testbuild/extension/net_classic_session_test:覆盖部分 mount 字段、motion mode 和 parser 信号;未覆盖模型挂接、GC_MOUNT 位置、poly/pet live chain、骑乘根运动、拒绝、乱序和重连清理。

Status

Deep audit round 2026-09-21

Fresh regression results

  • test_mount_horse_parity.gd 24/24、test_horse_combat_parity.gd 32/32、test_horse_level_growth_parity.gd 42/42、test_mounted_combat_skill_parity.gd 25/25、test_pet_companion_parity.gd 40/40、test_classic_pet_parity.gd 31/31、test_polymorph_parity.gd 25/25、test_polymorph_marble_parity.gd 32/32 均通过。
  • equip_rules_test.gdtest_battle_arena_duel_parity.gdplayer_move_test.gdnetplay_test.gd 和 native entity/session 测试退出码 0;通用 netbridge_test.gd 仍有 3 项实体桥接失败和 5 个 ObjectDB 泄漏。

Static parity conclusion

  • mount_vnum 的 parser/store/signal、部分动作模式、旋转速度和攻击等级门存在;但没有找到 mount_vnum 到实际 horse/saddle model attach/detach 的生产链。
  • GC_MOUNT 的位置、下马清理、重复/乱序、断线重连和角色死亡后的模型生命周期没有闭合;本版本参考代码中 Ride/Unride 调用被注释,不能用本地 helper 自行扩大 authority。
  • 变身字段没有形成 native affect→shape→装备遮挡/动作资源的完整链,EquipModel_is_poly() 仍是恒 false;宠物、马匹成长/耐力/马上技能/变身加攻防由本地脚本直接结算,而 40250 Windows 客户端没有对应本地 authority。
  • 所有 helper 测试通过只证明当前端自定义规则内部一致,不证明与参考客户端实现统一。

Status update

本轮仍为 PARTIAL;完成坐骑、宠物和变身方向的合同审计并登记,未修改实现。

PARTIAL。当前端已具备 mount_vnum 的网络存储、mount_changed 信号、部分动作模式/旋转速度/攻击门控,并有本地马匹、宠物和变身 helper;但没有发现实际坐骑模型挂接链,变身状态尚未进入 native entity,宠物与马战/成长/耐力/伤害脚本承担了 40250 客户端没有承担的本地 authority。基础测试全部通过仍不足以证明与 40250 Windows 客户端实现统一。本轮完成审计并记录,未修改实现。

2026-09-22 死代码删除

以下文件只被自身测试引用、运行时从不加载,已删除;本文中以它们为实现或证据的结论作废,相关行为需按 40250 源码单元重新移植:classic_pet_system.gd, horse_combat_system.gd, horse_level_growth_system.gd, horse_system.gd, mounted_combat_skill_system.gd, pet_companion_system.gd, polymorph_marble_system.gd, polymorph_system.gd, test_battle_arena_duel_parity.gd, test_classic_pet_parity.gd, test_horse_combat_parity.gd, test_horse_level_growth_parity.gd, test_mount_horse_parity.gd, test_mounted_combat_skill_parity.gd, test_pet_companion_parity.gd, test_polymorph_marble_parity.gd, test_polymorph_parity.gd