运行实例 GUID、UUID 输入记录与 proc 种子(v41)
2026-09-20。将原 NativeEditorGuid 计算接入表示范围内的玩家/怪物出生、存档和宿主回放,再把目标运行 GUID 接给已有 proc 的私有种子初始化。构造覆盖仍为 1099/1419;273 阻塞、47 缺定义/创建等级。没有提前开启 TYPE201/204,所有武器目标未完成。
RuntimeId 与 SourceId
原 CEditorBaseObject 构造 4D5660 调 EditorMakeGuid,初始 RuntimeId(+8) 与 SourceId(+24) 相同;随后布局装载把文件 ID 写到 SourceId,并建立 SourceId→RuntimeId 映射。运行 ID 不是布局文件 ID,也不是单位 DAT 的定义 GUID。
本批再次核查 Monster 描述符的构造入口 4C1580:创建实际 CMonster,继续沿其基类构造链生成运行身份。没有把 SourceId 直接塞进技能 seed。
EditorMakeGuid/6774D0 使用 UuidCreateSequential 返回的 16 字节,以及 synced MWC 的一次抽样,再经过既有 676330 哈希。本内核已有 2048 组原机器码对照;本批复用它,不另造 Guid.GetHashCode 或整数自增 ID 算法。
创建与回放接线
- 宿主 NativeUuidLedger 调 Windows RPC UuidCreateSequential,保存 Guid.ToByteArray 的原生 UUID 字节序;接受成功/本地唯一状态,其他失败显式报告。
- 每个输入流有独立日志标识。这个标识不用于游戏对象 GUID 或游戏随机数。
- CoreSim 的 SpawnNativePlayer/SpawnNativeMonster 接收已捕获输入,先暂存 GUID 生成,再执行表示范围内的角色数据/HP 创建,最后一起提交 synced 流与身份。
- RuntimeIdentity 保存十进制 GUID 字符串、UUID 输入索引、生成前 synced 种子字符串和来源标签。
- 保存 NativeUuids 的已消费输入数组。恢复时校验 GUID 是否等于对应 UUID 与 SeedBefore 计算的结果;数组不和原快照共享。
- 原实例恢复沿用保存身份,不重新生成。宿主保留同一输入流的回放缓冲;恢复到过去检查点后,重复出生请求复用已捕获的下一条 UUID,而不是再次调用 RPC。
- GUID 与已知单位身份冲突时,请求下一条外部输入;未得到完整输入前不发布单位或提交 RNG,成功时记录全部重试抽样。
真实原版的构造流程还包含其他编辑器对象、模型等的创建/随机操作。本批只接当前表示范围内的战斗单位及已知单位碰撞检查,不宣称整张地图所有对象的 GUID 抽样顺序已与原版一致。回放缓冲的 UUID 是显式外部输入,不是伪随机合成的替代 UUID。
旧存档
schema 41 增加 NativeUuids 与 UnitSnapshot.RuntimeIdentity。
纯核心读取 v40 及更早格式时仍保留未知身份,不谎称恢复丢失的运行 GUID。宿主给实际重新绑定的旧玩家/当前场景单位建立新的运行身份,并明确标为 legacy-rebind;不会批量给未加载关卡的历史单位制造身份。这个升级会产生对应的 GUID 随机抽样,不承诺保留旧版本未记录的历史 ID/未来外部 UUID 序列。
新生单位标为 birth。生成后的 GUID 与对应输入/种子一并保存,随后正常恢复/回放无须再次生成。非 Windows 宿主仍需另接录制输入提供者,当前没有偷偷换用另一种对象 ID 算法。
64 位跨语言精度与 proc
运行 GUID、生成前种子使用字符串保存。SnapshotCodec 对 NativeProcSkillSnapshot 的 EffectRng/InitialSeed、NativeProcManagerSnapshot 的 ManagerSeed 使用 JSON 数字字符串,并兼容读取旧数字表示,避免 Godot JSON 的 double 精度损失。
这项转换针对上述身份/私有种子字段,不宣称任意 GDScript 对整份快照做数值改写都会自动保真。正式存档仍由 C# codec 直接编码/解码。
已有 effect-only proc 在目标运行身份已知时,现在实际提供:
requested_seed = manager_seed + target_runtime_guid + signed_salt (mod 2^64)
不会再把目标 DAT GUID 或 core 整数句柄代入。旧的纯数值核心夹具/尚未绑定身份仍保留未知;非 effect-only 程序继续要求完整种子输入。零和种子的 GetTickCount 外部输入接口保留显式要求,不从纯核心读取墙钟。
验证
- 1709 条核心断言通过。新增 GUID 在 HP 抽样前生成、记录输入的出生重放、非法输入无部分提交、碰撞重试、身份校验、旧格式未知/重绑标记及 64 位 JSON 测试。
- 353 项相关 Python 回归通过;C# 构建 0 warning / 0 error,coresimlint 通过。
- 实际 ECHO PASS headless 探针使用真实 Windows UUID 捕获:额外出生捕获一次;恢复已有单位没有新捕获;回放相同出生得到相同 ID/HP/RNG/快照,RPC 捕获数未再增加。
- 同一真实 GREATHAMMER_U03 击杀回血 proc 检查目标已绑定身份,并由 C# 按完整 64 位计算核对私有种子。active=1、seed_matches=true;HP 与恢复/到期/重放检查通过。
- 原流血武器主场景回归也通过,包括叠层、NOBLEED、死亡/到期、骨骼挂接状态与清理。
新增探针 tl2_runtime_identity_world_probe.gd 与 RuntimeIdentityProbe.cs 均为测试文件;没有新增特效或修改视觉资源。headless 结果只证明运行接线,不当作视觉一致性验收。
初次场景测试发现 Godot 未识别主场景 UID;完成编辑器资源导入后重跑通过,没有用更改主场景配置绕过。
日志/产物:build/runtime_identity_core.log、runtime_identity_regression.log、runtime_identity_world.log、runtime_identity_bleeding_world.log、runtime_identity_audit.log。代码:core_sim/NativeRuntimeIdentity.cs、CoreSimBridge.RuntimeIdentity.cs,以及出生/恢复/codec/proc 调用处。
后续与安全
下一段继续实际世界目标查询、CSkill 事件实例及其 begin/tick/end/abort、双随机流的递归命中事务,再使 Stormclaw 从原武器命中自动触发。整个场景工厂的 UUID 调用序列、所有者/目标死亡策略、零种子外部时钟完整命令记录等仍需最终合流验证。
按 godot-master 保持宿主输入、核心状态和显示层分离。在 main 工作,未提交,未 attach/修改原版游戏。默认 warp_autosave.json SHA256 仍为 9840fe858b6e311c73f8c2d4ed49912d59d71365f6278392811730e012d32a7f;探针只写隔离测试槽。