实时 Room Piece 碰撞:实际资源槽到世界射线
2026-09-20。接通实际碰撞模型持有槽、原生节点姿态 / 可见状态与世界射线,并为地图烘焙增加读取实时实例的入口。不是按当前 GUID / VISUAL 再选一次资源,也不是 Godot Physics 的替代射线。
本批完成的是实时实例适配链,不是整张地图的原版创建与注册。武器构造覆盖仍为 1099 / 1419(273 阻塞、47 缺基础定义 / 创建等级),TYPE201 / 204 未放宽,全武器目标未完成。
为什么不能重新选择网格
F2NativeRoomResourceHost / NativeRoomCollisionSlot 已有原资源生命周期:
- 修改 GUID / VISUAL 首先刷新元数据,不一定立即替换已经加载的碰撞模型。
- 清空碰撞请求会释放模型,却有意保留旧 CachedRequest。
- 再请求同一旧字符串时,原 622360 的相等判断可提前返回,模型仍为空。
- 模型由共享缓存按引用持有,资源字符串不是模型存活证明。
因此,上批显式值绑定只适合已经确定的选定资源回放。正式实时入口必须读取资源槽当前的 NativeCollisionModelHandle,而非目录重选。即使新定义没有 COLLISIONFILE,旧模型仍可在实际替换前继续参与查询。
实现
核心实时视图
core_sim/NativeLiveRoomCollision.cs:
- INativeRoomCollisionRuntime 要求实际模型、碰撞开关、对象 / 节点传播可见位、烘焙状态、当前定义 ALWAYSBAKECOLLISION、条件分类、NOPATH、旋转、自身缩放和碰撞位置。
- NativeLiveRoomCollision 不持有新模型副本、不负责资源释放;它每次读取实例当前的模型槽。
- CaptureBakeInput 复制当前模型的面数组,不能由调用方修改共享模型;隐藏对象不会因显示状态而丢失其静态烘焙候选。
- Bounds 的生产方必须显式绑定;提供 ComputeBounds 供实际更新阶段使用,不假定原包围盒缓存随每帧移动自动刷新。
NativeGeometryWorldRayHost 遇到 INativeWorldRayRoom 时进入实时路径;既有冻结几何输入路径继续保留。
原 622950 顺序
LiveRoomRay 保留以下顺序(世界射线路径不启用 ignoreVisibility):
- 先查实际模型槽;没有模型立即返回。
- 碰撞开关、对象可见、节点传播可见按短路顺序读取。
- 视觉烘焙、ALWAYSBAKECOLLISION、碰撞烘焙门。
- 读取原碰撞位置;终点 X/Z 各轴超过 50 时退出,不要求旋转 / 缩放可用。
- 读取派生旋转和物件 stored scale,执行已验证的原 Ogre 逆变换。
- 求交前再次读取模型槽,不保留第一次门检查时的旧模型。
- 命中后先写线性变换后的点,再次读取派生旋转来转换法线,最后加回位置并应用 NOPATH。
最后一段依据原 622B67–622BAB 指令;二次 getter 不能被无条件缓存合并。法线仍只旋转,不套逆转置或额外归一化。关闭门、清空模型和普通 miss 均不伪造新的调用方命中输出。
Godot 生产方
torchlight-2-poc/NativeGodotRoomCollisionState.cs 从已有真实对象读取:
- F2NativeRoomResourceHost.CollisionModel;
- NativeRoomResourceState.CollisionEnabled / NoPath;
- NativeSceneAttachmentState.Visible;
- NativeGodotSceneBackend 的 Propagated 位和派生旋转;
- 明确提供的 positionable stored pose,而不是 Godot 渲染全局 Transform。
61DCE0 的位置分支要求 object+80(TransformParent)和实际节点存在。只有源 PARENTID、有 Godot mount、或节点恰好挂在树里,都不能替代这个条件;没有原 transform parent 时取 stored position。
BAKE 和 ConditionalDetail 仍由其生命周期所有者提供。本批没有从节点名字、材质、是否显示或网格文件存在性推断这些状态。
core_sim.io/F2MapCollisionInputs.cs 新增 BindLiveBakeInputs,完整核对实例集合后按调用方给出的实际顺序抓取实时状态。缺失、重复和外来实例仍拒绝;不以一份不完整的集合发布地图烘焙输入。
验证
核心:
- 新实时路径对照已有原 622950 机器码的 4908 组几何参考,PC24 / 53 / 64 命中、世界点、法线、surface 均一致;miss 保持调用方输出。
- 补充 getter 顺序、各级短路门、第二次模型返回不同资源、命中后二次旋转变化、回调观察到的中间点、共享面数组隔离和模型清除测试。
- 包围盒测试遵循原先已验证的 X/Z 0.2、Y 0.1 扩张,发生在自身缩放之前;未降低几何误差门限。
独立真实 Godot 探针:
- NativeLiveRoomCollisionProbe 加载原岩石碰撞资源,通过真实 native-backed Godot 节点进入完整世界射线控制器。
- 22 项检查覆盖自身 / 父级缩放分离、原 transform-parent 位置规则、原生传播可见、移动后的碰撞更新、碰撞开关、BAKE 事件、隐藏对象烘焙、NOPATH、元数据先改而模型未换、sticky request 和释放后的查询。
- 无正式地图 / 玩家存档实例化;世界静态候选、成员列表与 BAKE 事件为明确的受控上下文。实际使用的模型槽、原几何和 Godot 节点不是虚构的命中结果。
- 不新增画面资源,不以 headless 检查宣称视觉一致或全地图遮挡验收。
运行探针:
dotnet build torchlight-2-poc/TL2Poc.csproj --nologo
& 'E:/Godot/Godot_v4.7-stable_mono_win64_console.exe' --headless --path 'E:/Torchlight2-Remaster-Project/torchlight-2-poc' --script res://tl2_native_live_room_collision_probe.gd --audio-driver Dummy --quit-after 3600产物:build/native_live_room_result.json(含源文件哈希、22 项检查和存档前后哈希)。完整日志:native_live_room_core.log、native_live_room_godot.log、native_live_room_regression.log、native_live_room_build.log、native_live_room_lint.log、native_live_room_audit.log。
1776 条核心断言、374 项相关 Python 回归通过;Godot C# 构建零警告 / 零错误;coresimlint 通过。
剩余与安全
接下来仍需把完整地图原版属性 / 初始化顺序产生的 BAKE、条件分类、随机变体和实际注册列表接进来,再组成静态分区与单位 / 装备阻挡上下文。技能事件与攻击型 proc 的完整执行继续在后面,不能因为一件真实 Room 能正确求交就把全世界查询标记完整。
按 godot-master 分离实例状态所有权、数据来源与几何计算。main 原地工作、未提交;快照仍为 v41,未引入新持久化状态。默认 warp_autosave.json 的 SHA256 保持 9840fe858b6e311c73f8c2d4ed49912d59d71365f6278392811730e012d32a7f。