- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
13 KiB
13 KiB
world.npc_drop_actor_spawn
Scope
审计 40250 Windows 客户端的 NPC、怪物、石头、建筑/墙体、玩家实体、地面掉落、所有权、私人商店招牌和实体清理链。判断标准是实体是否按相同的包字段、VID 生命周期、分类、可见性、模型/动作资源、名字尾标、掉落所有权和删除时序进入客户端;服务端掉落概率、散落规则或本地活动规则不能因为在当前端有脚本就当作 40250 客户端等价实现。
Reference call chain
UserInterface/PythonNetworkStreamPhaseGameActor.cppRecvCharacterAppendPacket/RecvCharacterAdditionalInfo/RecvCharacterUpdatePacket解包 race、character type、parts、affect、位置、速度、名字、公会、等级、mount 等字段;不可见 race 不创建实例;角色新增最终进入CNetworkActorManager/CInstanceBase,非零 mount vnum 由角色实例处理。RecvCharacterDeletePacket通过 actor manager 删除 VID,并同步通知私人商店消失。RecvOwnerShipPacket把 owner VID 与 victim VID 写入网络 actor manager。
UserInterface/NetworkActorManager.cpp/UserInterface/PythonCharacterManager.cpp/UserInterface/InstanceBase.cpp- actor manager 负责 add/update/move/delete、VID 查找和实例状态;character manager 负责碰撞、拾取、排序、距离可见性和渲染列表;
CInstanceBase按 race/type 选择模型、动作、名字和状态。 - 40250 的可见性由
CHAR_STAGE_VIEW_BOUND、AFFECT_SHOW_ALWAYS和 wall 判定共同决定;离开范围时走 delete/blend-out,数据与渲染实例不是同一层。
- actor manager 负责 add/update/move/delete、VID 查找和实例状态;character manager 负责碰撞、拾取、排序、距离可见性和渲染列表;
UserInterface/PythonNetworkStreamPhaseGameItem.cpp/UserInterface/PythonItem.cpp/UserInterface/PythonTextTail.cpp/Packet.hRecvItemGroundAddPacket将全局坐标转本地坐标后调用CPythonItem::CreateItem(vid, vnum, x, y, z);未知 item data 不创建地面物体。RecvItemOwnership调用SetOwnership(vid, name),更新独立 owner 尾标;RecvItemGroundDelPacket删除地面实例并删除对应 item text tail。CreateItem从CItemData::GetDropModelThing()建立掉落模型,注册 item text tail;GetCloseMoney/GetCloseItem、模型拾取和网络CG_ITEM_PICKUP负责交互,服务器回包才完成真正拾取。
UserInterface/PythonNetworkStreamPhaseGame.cppRecvShopSignPacket对空 sign 触发BINARY_PrivateShop_Disappear,非空 sign 触发BINARY_PrivateShop_Appear(vid, sign);该包不是普通实体 spawn,必须依赖已存在角色 VID。
Current call chain
extension/src/net/classic/classic_parser.cpp已将 character add/additional/update/delete、GC_OWNERSHIP、GC_ITEM_GROUND_ADD/DEL/OWNERSHIP和GC_SHOP_SIGN分别写入EntityStore/ground store;M2Client::poll将实体和地面变化转为 Godot signal。extension/src/net/entity_store.cpp/.h以 VID 保存实体,spawn 是整行替换;地面掉落独立保存vid/vnum/pos/owner,shop sign 是已存在实体的可变字段;未知 VID 的 shop sign/owner 不凭空创建实体。project/net_world.gd在数据层保存全部实体,在场景层按主角距离、AFFECT_SHOW_ALWAYS和 wall race 创建/淡出节点;_on_spawn写入分类、名字、parts、affect、速度、mount 和 shop sign,_on_info刷新可变字段;project/ui/mob_view.gd负责 NPC/怪物模型、动作、受击和名字补点。project/ui/ground_items.gd监听 ground add/del,按 item proto 解析名字/颜色,加载 item bag/money 模型或 fallback BoxMesh,创建名字与 owner 尾标、稀有掉落光柱,按距离和 500ms 节流发送拾取;服务端 ground del 负责最终消失。project/entity_rules.gd、project/metin_spawn_event_system.gd、project/mob_drop_scatter.gd等本地 helper 还承担木门/建筑分类、石头活动、掉落散落和所有权保护等自定义规则;这些不等于 40250 Windows 客户端本身的 authority。
Branch matrix
| 场景 | 40250 | 当前端 | 结论 |
|---|---|---|---|
| 角色/NPC/怪物新增 | add packet→actor manager→CInstanceBase→模型/尾标;不可见 race 跳过 |
parser/store→entity_spawned→NetWorld,可延迟 placeholder 后升级真模型 |
PARTIAL:字段链存在,但不可见 race、未知 race、真资源缺失时的失败分支未完整证明 |
| character additional/update | 按包刷新 parts、名字、公会、affect、速度、状态和 shop 相关数据 | _on_info/_apply_field_updates 按顺序刷新部分字段 |
PARTIAL:顺序入口有,角色类型、异常字段、重复/乱序包和实际 model attachment 缺 live 证据 |
| VID 重用 | 删除旧实例后重新 add;actor manager 查找不应残留旧状态 | EntityStore whole-row spawn,NetWorld 销毁并重建节点 | PARTIAL:设计上接近,但旧节点延迟释放与同 VID 新 spawn 的边界没有完整回归 |
| 远端删除/淡出 | actor manager 删除;尾标、商店和交互引用同步清理 | entity_despawned→_fade_and_free,数据层/场景层分离 |
PARTIAL:删除链存在,blend-out 期间重复 spawn、目标/尾标/交互引用的完整时序仍需验证 |
| 距离可见性 | CHAR_STAGE_VIEW_BOUND、always-show、wall 分支控制实例和渲染列表 |
_update_visibility 每帧以 20000cm/20010cm、affect bit、wall race 建/淡出 |
PARTIAL:基础分支已映射;距离常量、真实 actor manager 淡出和复杂 wall/always-show 组合仍未完全证明 |
| 建筑/墙体/门 | 由 race 与 InstanceBase/碰撞数据决定,墙体不因距离错误消失 | entity_rules/cursor shape 识别 door/building,wall race 强制可见 |
PARTIAL:分类与 cursor 入口有;模型、碰撞、阻挡和真实 wall 生命周期未统一证明 |
| 地面掉落新增 | 坐标转换→CItemData drop model→item text tail;未知 vnum 不创建 | ground store→ground_items,item bag/money 或 BoxMesh fallback→Label3D |
PARTIAL:协议、坐标、名字尾标和 fallback 有;真实 drop model/effect/sound/未知 vnum 失败语义不等价 |
| 地面掉落所有权 | RecvItemOwnership 更新独立 owner text tail;服务器仍是拾取 authority |
owner 写入 ground row/owner_tag,并在本地 pickup 前做名字判断 | PARTIAL:回包链存在;本地 owner precheck 是额外 optimistic gate,party/anti-flag/native action gate 未完整接入 |
| 地面掉落删除/拾取 | GC_ITEM_GROUND_DEL 同步删除模型和尾标;拾取成功依赖服务器包序 |
ground del signal 删除节点,pickup 只发送请求 | PARTIAL:删除基础链有;CG_ITEM_PICKUP→GC_DEL→ITEM_GET/ITEM_SET/UPDATE 的 live 成功、失败、乱序和回滚未证明 |
| 私人商店招牌 | GC_SHOP_SIGN 空/非空走 disappear/appear,依赖已有角色 VID |
shop_sign 进入实体 info,_refresh_shop_sign 创建/释放 Label3D |
PARTIAL:空/非空状态可映射;BINARY 私人商店 UI、重复/未知 VID、重连清理和视觉资源不等价 |
| 怪物死亡与掉落 | 死亡/删除/地面掉落由服务端包和 actor/item manager 驱动 | mob_view 死亡表现,活动 helper 可生成本地掉落 |
GAP(custom authority):本地散落/活动掉落不能作为 40250 client parity,live server death→drop 时序仍缺证据 |
Implementation-equivalence matrix
| 项目 | 状态 | 证据/限制 |
|---|---|---|
| Preconditions | PARTIAL | stage、VID、实体/ground store 和部分分类存在;未知 race/vnum、主 VID、模型工厂未就绪和 owner/anti-flag 门控未完整证明 |
| Branch structure | PARTIAL | actor add/info/update/delete、ground add/del/owner、shop sign 主要分支存在;visibility、不可见 race、未知数据和 server rejection 分支不等价 |
| Algorithms/formulas | PARTIAL | 坐标转换、20000cm 可见范围、owner 标签和拾取距离有实现;CItemData 模型选择、碰撞/拾取几何、drop effect 和参考资源算法未统一 |
| State transition order | PARTIAL | parser→store→signal→view 顺序明确;延迟模型升级、淡出、同 VID 重用、ground del 与 owner/sign 乱序的可观察顺序未闭合 |
| Constants/units | PARTIAL | CHAR_STAGE_VIEW_BOUND、+10 cull、ground height/pickup 距离、packet fields 有证据;Godot world unit 与 40250 pixel/cm、文本像素度量、模型锚点仍是近似 |
| Timing/event sources | PARTIAL | poll、ground signal、500ms pickup throttle、visibility interval 有;真实 frame cull、blend-out、drop animation/effect/sound、server packet delay 未覆盖 |
| Resource/data sources | PARTIAL | mob/NPC 资源扫描和部分真模型测试通过,但有 4 个 fallback;ground 使用通用 bag/BoxMesh,未证明所有 CItemData drop model、特效、音效和牌匾资源 |
| Protocol side effects | PARTIAL | classic parser/session 与 ground/ownership/shop sign 基础路径存在;完整拾取回包、商店 UI、不可见实体过滤和未知 packet 语义缺 live 证据 |
| Interruption/failure/cleanup | PARTIAL | net_world_vis_test.gd 的基本可见性/重显/删除回归已通过;地图切换基础清理已有,但实体淡出、地面掉落、尾标、商店、同 VID 重用、断线/重连和模型 fallback 的组合清理未完整证明 |
Regression evidence
project/net_world_vis_test.gd:通过;覆盖主角进入范围后的远端节点创建、单次创建、离开范围裁剪和删除信号去重。仍不证明真实 actor manager 的 wall/always-show/模型失败组合。project/entity_rules_test.gd:通过;验证实体分类/可攻击规则,但不证明 40250 的模型、碰撞和 visibility chain。project/forest_mob_render_test.gd:24 个结果、0 failures、4 fallback;有 Godot ObjectDB leak warning,且仍需人工资源 sign-off,因此不能标记 PASS。project/mob_view_test.gd、project/mob_winding_test.gd、project/net_world_push_test.gd:通过;覆盖单体模型/绕序/受击推开,不能证明完整 actor manager 生命周期。project/test_ground_pickup_parity.gd、project/mob_death_drop_test.gd、project/test_mob_drop_scatter_parity.gd、project/test_metin_spawn_event_parity.gd:通过;主要覆盖当前端 helper、掉落散落和活动石头规则,不等于 40250 live drop/model/pickup parity。build/extension/net_entity_test、build/extension/net_classic_session_test、build/extension/net_classic_wire_test:覆盖部分实体、地面包和协议边界;未覆盖上述 visibility 失败、真实资源失败、完整拾取回包、商店牌匾和重连组合清理。
Active GameLib spawn/property review
GameLib/MonsterAreaInfo.cpp保存刷怪区域 origin/size、左右上下边界、数量、随机初始位置、方向、group/leader/VID/name 和清理默认值;Property.cpp/PropertyLoader.cpp/PropertyManager.cpp为地图 object/property 注册提供 CRC 和 token 数据。- 当前实体生成主要来自服务端 spawn packet 和
NetWorld,地图静态刷怪区域/property 并没有一条等价的客户端本地MonsterAreaInfo消费链;因此本轮只确认参考数据模型和清理边界,不能把网络实体测试当作静态刷怪 parity。
Active UserInterface NPC data review
PythonNonPlayer.h/PythonNonPlayerModule.cpp以 MMPT mob table 为权威,提供LoadNonPlayerData、vnum/name/type/event/color、VID event lookup 和按等级区间匹配的 mob list;PythonCharacterModule.cpp再用 event type 决定角色 render/behavior。- 当前
Metin2Proto/EntityStore能解析 mob proto 并生成网络实体,但 event type、mob color/name、等级筛选和 unknown vnum/缺记录失败分支没有完整接入NetWorld/NPC view;本轮静态证据确认“能生成一个怪物”不等于 NPC data chain 一致。 - 本轮完成 UserInterface NPC 数据入口静态核对,合同保持
PARTIAL。
Deep audit round 2026-09-20
本轮复跑 project/net_world_vis_test.gd 时发现固定 100ms 可见性节流会让快速连续帧的结果不稳定;40250 CPythonCharacterManager::Update 每帧执行距离检查,因此已改为每帧调用 _update_visibility()。连续两次测试均 PASS。该结果只证明当前 Godot 可见性状态机的基础边沿,不足以把 40250 的 actor manager 淡出、wall 判定和真实资源失败分支标为等价。
Status
PARTIAL。当前端已经具备 40250 实体/掉落协议的主要 native parser、VID 数据层、NPC/怪物场景层、地面物体和 shop sign 状态入口;可见性基础回归和每帧更新边界已修复,但掉落模型/特效/音效、建筑碰撞、完整 actor/ground 生命周期和 live 拾取/商店回包证据仍不足。