Initial import of IC.Rebuild

This commit is contained in:
2026-10-13 22:55:05 +08:00
commit 16d61f7a5e
87 changed files with 17054 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
# 首轮实测与 0.1.1 修复
客户端:国际服 `2026.09.15.0000.0000`。ffxiv_dx11.exe SHA256:`5BBC501DD5C7F22FD61A11D08C25356041D878DB7CD83203ADAE393E4DFACC44`。
## 用户反馈
- 测试 1 通过;保持原反馈,不扩展成所有参数和场景均通过。
- 最大加速度开启后无法行走。
- 目标圈大小开启后客户端崩溃。
- Opcode 记录在插件窗口可见,但没有导出文件。
配置文件中编号 1 与 14 的参数均为 0,所以不能据此认定非零移速增量或非零目标圈增量已通过验证。日志确认插件成功加载。
## 目标圈崩溃
证据来自 `dalamud_appcrash_20261010_231418_146_9584.log`:异常码 E0434352,HRESULT 80131509。调用链为游戏 JobPool 工作线程 → 目标圈回调 → GameContext.Ready → ObjectTable.LocalPlayer。
Dalamud ObjectTable 的索引访问调用 ThreadSafety.AssertMainThread。旧版 Ready 在原生工作线程直接访问该服务,导致托管异常越过原生回调边界。
0.1.1 将角色有效性、本地地址、PVP 状态、减速状态和迷宫信息放入不可变帧快照,仅在 Framework.Update 读取游戏服务。原生回调读取快照;超过 500 ms 未刷新时停用修改。配置参数和 Timeline 名单也发布为不可变快照。技能距离的 Excel 数据在启用时准备,不在原生回调读取。
目标圈回调使用 SDK GetRadius 委托,并在托管计算失败时保留原始返回值。修复通过离线回归,游戏内复测待完成。
## 最大加速度
在用户当前客户端磁盘文件中,历史签名唯一匹配 RVA `0x182BB20`。只读反汇编确认:
- `0x14182BB26` 检查 `[rcx+0x3C]` 活动状态。
- `0x14182BB38` 读取 `[rcx+0x20]` 控制器。
- `0x14182BB6A` 读取 `[rbx+0x44]` 运动状态。
- `0x14182BC5F` 和 `0x14182BD41` 将计算结果写回 `[rbx+0x44]`。
- 该函数通过控制器 `+0x3E0` 访问所属对象。
旧版 finally 写回调用前值,会覆盖原生计算结果;初始值为 0 时会把更新结果反复清零。0.1.1 删除这一恢复行为,仅对当前活动的本地角色控制器预置值,保留原函数最终结果。角色受减速状态影响时不预置。字段适配限定为本次审计版本,其他版本拒绝启用。
回归测试模拟初始 0、预置 100、原函数输出 6,确认返回后仍为 6;另覆盖其他对象、不活动、减速和 NaN 情况。实际行走、停止与加速效果仍待复测。
只读审计工具:`Tools/NativeAudit`;不访问进程内存或修改游戏文件。
## Opcode 检查
已读取插件配置目录中的 opcodes.json。当前版本包含 28 个上行名称、73 个下行名称,对应 28 个上行数值及 90 个下行数值。同方向内没有 Opcode 冲突,值均在 ushort 范围。
部分映射:
| 名称 | 十进制 Opcode |
| --- | --- |
| UP_UpdatePositionHandler | 920 |
| UP_UpdatePositionInstance | 411 |
| UP_PingReq | 838 |
| UP_EventStart | 181 |
| DOWN_ActorCast | 354 |
| DOWN_Effect | 787 |
| DOWN_EventStart | 737 |
当前版本没有 DOWN_PingRsp 映射,因此不能期待现有映射直接完成 Ping 响应关联。
这份文件是名称映射,不是用户本轮交互的抓包记录。用户确认没有导出,崩溃后旧版内存记录不可恢复;未对实际上下行序列作无依据判断。
## 记录保存
0.1.1 默认开启每 5 秒保存一次最近 2048 条记录的选项,可在网络面板关闭。文件位于插件配置目录,名称为 capture 加会话时间和随机标识,避免新会话覆盖旧会话。后台写临时文件后原子替换,不在原生回调写盘。
`/icr export` 可手动导出为 packets.jsonl;也可指定文件名。定时保存仍是滚动快照,不是无限完整日志,崩溃前最后一个保存周期可能丢失。实时数据仍仅有元数据,PayloadComplete=false。
+46
View File
@@ -0,0 +1,46 @@
# 猛攻与全职业位移名单修复
版本:0.1.2。目标客户端:国际服 2026.09.15.0000.0000。
用户反馈:16 开启后位移仍存在,14 增加后突进停在目标圈外。两种现象均使用战士猛攻测试。用户随后要求把所有带位移的技能加入 16 的名单。
## 名单与位移拦截
原配置的 BlockedTimelines 为空、BlockListed=true,因此旧实现开启 16 时不屏蔽任何技能。新版从动作表选择 IsPlayerAction=true 且 AffectsPosition=true 的所有条目,通过 AnimationEnd 建立名单。
本机动作表结果:79 个技能条目,58 个不同 Timeline,均有有效的 16 位映射。包含 PvE、PvP 及仍保留在动作表中的历史条目;不宣称每个条目都仍可从技能栏使用。数据明细见 `movement-skills-2026.09.15.json`。
| 技能 | 动作 ID | Timeline | 位移标记 |
| --- | --- | --- | --- |
| 猛攻 PvE | 7386 | 5189 | true |
| 猛攻 PvP | 29079 | 12244 | true |
首次加载当前客户端版本时自动补全名单,模式切为仅屏蔽名单内,所有模块仍默认关闭。相同版本后续加载保留用户编辑;可点击“加入全部位移技能”重新补全。相同 Timeline 对应的多个技能会联动。
保留三种明确模式:全部本地技能位移、仅屏蔽名单内、仅放行名单内。名单模式下空名单不屏蔽;另提供技能 ID 转换、技能名展示与最近位移命中统计。
## 原生路径核对
旧 NoActionMove 签名唯一匹配 RVA 0x1821FC0,是一个转发函数。它调用共用位移初始化函数 RVA 0x1822510。新版对共用入口建立经唯一性检查的签名,覆盖从其他转发路径进入的同类请求。
共用入口的参数对应控制器、位移类型、目标、起点、朝向及元数据;控制器 +0x3E0 为所属对象。拦截限定本地角色,未就绪或无效元数据时放行。
下层 RVA 0x180A370 的 0x14180A5A9、0x14180A5B0 分别读取元数据字节 2、3,0x14180A5B7 读取 word [data]。旧代码把前四字节全部作为 Timeline,会把标志位混入编号。新版按低 16 位读取编号,单独显示两个标志字节。
函数参数、偏移和签名限于本次审计版本。运行中的猛攻是否进入该入口、是否被成功屏蔽,仍需用界面的本地调用及拦截计数确认。
## 目标半径与落点
旧实现全局增加 GetRadius 的返回值,既影响目标,也影响自身和其他调用方。GetActionInRangeOrLoS 在本机 RVA 0x8DD220,明确读取目标与自身半径并参与距离计算;这种全局修改也会影响其他使用半径的移动或碰撞流程。
新版仅在本地角色的普通技能距离检查中,对正在检查的目标增加半径。使用线程局部作用域;自身、其他对象、未知技能和 AffectsPosition=true 的技能不加值。离开距离检查后立即恢复作用域,其他工作线程不继承。
因此 14 不再修改显示目标圈、碰撞半径或突进落点,也不给猛攻本身增加目标半径。13 的技能距离设置独立保留。热栏颜色等其他缓存显示是否同步仍待游戏内观察。
## 测试与记录
Release 构建通过,0 警告、0 错误;32 项离线测试通过。新增覆盖位移编号与标志分离、三种名单模式、本地对象限制、半径作用域、线程隔离、异常恢复和玩家技能目录筛选。
游戏内复测未完成,不把名单完整性等同于所有位移路径均已拦截。
已读取新生成的自动保存 JSONL,实际包含 2048 条上下行元数据,客户端版本匹配且 PayloadComplete 均为 false。聚合结果见 `capture-summary-second-test.json`;名称来自映射表,不能仅凭元数据验证具体包体含义或动作结果。
@@ -0,0 +1,312 @@
{
"Source": "capture-018.jsonl",
"SHA256": "224AE627F6F6E613662745300C01493E411BDBE02CBA72366CCBD373DD28ECFF",
"MapSHA256": "2764186EA528587F15D07569816D413E77E8C38C572E4157787B3092BD6D1DB6",
"MapSource": "local cache \u002B \u672C\u673A\u6838\u5B9E PingRsp",
"Version": "2026.09.15.0000.0000",
"Records": 891,
"Up": 534,
"Down": 357,
"FirstTime": "2026-10-11T10:12:32.1453158+00:00",
"LastTime": "2026-10-11T10:13:52.6616441+00:00",
"FirstSequence": 1,
"LastSequence": 891,
"SequenceContinuous": true,
"MonotonicOrder": true,
"Complete": 891,
"Incomplete": 0,
"CaptureIssues": 0,
"PayloadBytes": 56360,
"MinPayload": 8,
"MaxPayload": 656,
"EmptyPayloads": 0,
"Known": 724,
"Unknown": 167,
"Parsed": 512,
"SupportedButRejected": 0,
"Groups": [
{
"Key": {
"Direction": 0,
"Opcode": 920,
"Name": "UP_UpdatePositionHandler",
"Length": 24,
"PayloadComplete": true,
"Parsed": true
},
"Count": 494,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 787,
"Name": "DOWN_Effect",
"Length": 124,
"PayloadComplete": true,
"Parsed": false
},
"Count": 52,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 671,
"Name": null,
"Length": 72,
"PayloadComplete": true,
"Parsed": false
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 697,
"Name": null,
"Length": 24,
"PayloadComplete": true,
"Parsed": false
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 558,
"Name": null,
"Length": 264,
"PayloadComplete": true,
"Parsed": false
},
"Count": 50,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 516,
"Name": "DOWN_ActorControlSelf",
"Length": 40,
"PayloadComplete": true,
"Parsed": false
},
"Count": 48,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 238,
"Name": "DOWN_ObjectSpawn",
"Length": 64,
"PayloadComplete": true,
"Parsed": false
},
"Count": 38,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 913,
"Name": "UP_ActionSend",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 27,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 524,
"Name": "DOWN_NpcSpawn",
"Length": 656,
"PayloadComplete": true,
"Parsed": false
},
"Count": 18,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 974,
"Name": "DOWN_ActorDelete",
"Length": 8,
"PayloadComplete": true,
"Parsed": false
},
"Count": 12,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 614,
"Name": null,
"Length": 16,
"PayloadComplete": true,
"Parsed": false
},
"Count": 10,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 838,
"Name": "UP_PingReq",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 8,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 338,
"Name": "DOWN_PingRsp",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 8,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 607,
"Name": "DOWN_ActorControl",
"Length": 24,
"PayloadComplete": true,
"Parsed": false
},
"Count": 7,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 391,
"Name": "UP_ClientTrigger",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 5,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 131,
"Name": "DOWN_StatusEffectList",
"Length": 384,
"PayloadComplete": true,
"Parsed": false
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 788,
"Name": null,
"Length": 16,
"PayloadComplete": true,
"Parsed": false
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 305,
"Name": "DOWN_EffectResult",
"Length": 96,
"PayloadComplete": true,
"Parsed": true
},
"Count": 2,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 214,
"Name": null,
"Length": 16,
"PayloadComplete": true,
"Parsed": false
},
"Count": 1,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 856,
"Name": "DOWN_ActorControlTarget",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 1,
"Rejection": null
}
],
"PingPairs": [
{
"Request": 3,
"Response": 4,
"Milliseconds": 83.2735
},
{
"Request": 54,
"Response": 56,
"Milliseconds": 99.9771
},
{
"Request": 222,
"Response": 224,
"Milliseconds": 116.8623
},
{
"Request": 372,
"Response": 374,
"Milliseconds": 83.4204
},
{
"Request": 530,
"Response": 532,
"Milliseconds": 83.4215
},
{
"Request": 683,
"Response": 684,
"Milliseconds": 83.2034
},
{
"Request": 807,
"Response": 808,
"Milliseconds": 100
},
{
"Request": 870,
"Response": 871,
"Milliseconds": 83.2435
}
],
"Limitations": "No raw payload, coordinates or actor IDs included. Successful parsing does not verify all fields. Header-read failures absent from export require UI counters."
}
@@ -0,0 +1,271 @@
{
"Source": "capture-018.jsonl",
"SHA256": "224AE627F6F6E613662745300C01493E411BDBE02CBA72366CCBD373DD28ECFF",
"MapSHA256": "2764186EA528587F15D07569816D413E77E8C38C572E4157787B3092BD6D1DB6",
"MapSource": "local cache",
"Version": "2026.09.15.0000.0000",
"Records": 891,
"Up": 534,
"Down": 357,
"FirstTime": "2026-10-11T10:12:32.1453158+00:00",
"LastTime": "2026-10-11T10:13:52.6616441+00:00",
"FirstSequence": 1,
"LastSequence": 891,
"SequenceContinuous": true,
"MonotonicOrder": true,
"Complete": 891,
"Incomplete": 0,
"CaptureIssues": 0,
"PayloadBytes": 56360,
"MinPayload": 8,
"MaxPayload": 656,
"EmptyPayloads": 0,
"Known": 716,
"Unknown": 175,
"Parsed": 2,
"SupportedButRejected": 502,
"Groups": [
{
"Key": {
"Direction": 0,
"Opcode": 920,
"Name": "UP_UpdatePositionHandler",
"Length": 24,
"PayloadComplete": true,
"Parsed": false
},
"Count": 494,
"Rejection": "UP_UpdatePositionHandler \u957F\u5EA6\u4E0D\u5339\u914D\uFF1A24\uFF0C\u9884\u671F 40"
},
{
"Key": {
"Direction": 1,
"Opcode": 787,
"Name": "DOWN_Effect",
"Length": 124,
"PayloadComplete": true,
"Parsed": false
},
"Count": 52,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 671,
"Name": null,
"Length": 72,
"PayloadComplete": true,
"Parsed": false
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 697,
"Name": null,
"Length": 24,
"PayloadComplete": true,
"Parsed": false
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 558,
"Name": null,
"Length": 264,
"PayloadComplete": true,
"Parsed": false
},
"Count": 50,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 516,
"Name": "DOWN_ActorControlSelf",
"Length": 40,
"PayloadComplete": true,
"Parsed": false
},
"Count": 48,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 238,
"Name": "DOWN_ObjectSpawn",
"Length": 64,
"PayloadComplete": true,
"Parsed": false
},
"Count": 38,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 913,
"Name": "UP_ActionSend",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 27,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 524,
"Name": "DOWN_NpcSpawn",
"Length": 656,
"PayloadComplete": true,
"Parsed": false
},
"Count": 18,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 974,
"Name": "DOWN_ActorDelete",
"Length": 8,
"PayloadComplete": true,
"Parsed": false
},
"Count": 12,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 614,
"Name": null,
"Length": 16,
"PayloadComplete": true,
"Parsed": false
},
"Count": 10,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 838,
"Name": "UP_PingReq",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 8,
"Rejection": "UP_PingReq \u957F\u5EA6\u4E0D\u5339\u914D\uFF1A32\uFF0C\u9884\u671F 28"
},
{
"Key": {
"Direction": 1,
"Opcode": 338,
"Name": null,
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 8,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 607,
"Name": "DOWN_ActorControl",
"Length": 24,
"PayloadComplete": true,
"Parsed": false
},
"Count": 7,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 391,
"Name": "UP_ClientTrigger",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 5,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 131,
"Name": "DOWN_StatusEffectList",
"Length": 384,
"PayloadComplete": true,
"Parsed": false
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 788,
"Name": null,
"Length": 16,
"PayloadComplete": true,
"Parsed": false
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 305,
"Name": "DOWN_EffectResult",
"Length": 96,
"PayloadComplete": true,
"Parsed": true
},
"Count": 2,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 214,
"Name": null,
"Length": 16,
"PayloadComplete": true,
"Parsed": false
},
"Count": 1,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 856,
"Name": "DOWN_ActorControlTarget",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 1,
"Rejection": null
}
],
"PingPairs": [],
"Limitations": "No raw payload, coordinates or actor IDs included. Successful parsing does not verify all fields. Header-read failures absent from export require UI counters."
}
@@ -0,0 +1,319 @@
{
"Source": "capture-018.jsonl",
"SHA256": "224AE627F6F6E613662745300C01493E411BDBE02CBA72366CCBD373DD28ECFF",
"MapSHA256": "2764186EA528587F15D07569816D413E77E8C38C572E4157787B3092BD6D1DB6",
"MapSource": "local cache \u002B \u672C\u673A\u6838\u5B9E 7 \u9879",
"Version": "2026.09.15.0000.0000",
"Records": 891,
"Up": 534,
"Down": 357,
"ManagerReplay": {
"Matches": true,
"Records": 891,
"SendReturns": 534,
"ObserverErrors": 0,
"ReadErrors": 0
},
"FirstTime": "2026-10-11T10:12:32.1453158+00:00",
"LastTime": "2026-10-11T10:13:52.6616441+00:00",
"FirstSequence": 1,
"LastSequence": 891,
"SequenceContinuous": true,
"MonotonicOrder": true,
"Complete": 891,
"Incomplete": 0,
"CaptureIssues": 0,
"PayloadBytes": 56360,
"MinPayload": 8,
"MaxPayload": 656,
"EmptyPayloads": 0,
"Known": 891,
"Unknown": 0,
"Parsed": 679,
"SupportedButRejected": 0,
"Groups": [
{
"Key": {
"Direction": 0,
"Opcode": 920,
"Name": "UP_UpdatePositionHandler",
"Length": 24,
"PayloadComplete": true,
"Parsed": true
},
"Count": 494,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 787,
"Name": "DOWN_Effect",
"Length": 124,
"PayloadComplete": true,
"Parsed": false
},
"Count": 52,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 671,
"Name": "DOWN_UpdateHate",
"Length": 72,
"PayloadComplete": true,
"Parsed": true
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 697,
"Name": "DOWN_EffectResultBasic",
"Length": 24,
"PayloadComplete": true,
"Parsed": true
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 558,
"Name": "DOWN_UpdateHater",
"Length": 264,
"PayloadComplete": true,
"Parsed": true
},
"Count": 50,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 516,
"Name": "DOWN_ActorControlSelf",
"Length": 40,
"PayloadComplete": true,
"Parsed": false
},
"Count": 48,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 238,
"Name": "DOWN_ObjectSpawn",
"Length": 64,
"PayloadComplete": true,
"Parsed": false
},
"Count": 38,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 913,
"Name": "UP_ActionSend",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 27,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 524,
"Name": "DOWN_NpcSpawn",
"Length": 656,
"PayloadComplete": true,
"Parsed": false
},
"Count": 18,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 974,
"Name": "DOWN_ActorDelete",
"Length": 8,
"PayloadComplete": true,
"Parsed": false
},
"Count": 12,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 614,
"Name": "DOWN_JobGauge",
"Length": 16,
"PayloadComplete": true,
"Parsed": true
},
"Count": 10,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 838,
"Name": "UP_PingReq",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 8,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 338,
"Name": "DOWN_PingRsp",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 8,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 607,
"Name": "DOWN_ActorControl",
"Length": 24,
"PayloadComplete": true,
"Parsed": false
},
"Count": 7,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 391,
"Name": "UP_ClientTrigger",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 5,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 131,
"Name": "DOWN_StatusEffectList",
"Length": 384,
"PayloadComplete": true,
"Parsed": false
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 788,
"Name": "DOWN_UpdateClassInfo",
"Length": 16,
"PayloadComplete": true,
"Parsed": true
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 305,
"Name": "DOWN_EffectResult",
"Length": 96,
"PayloadComplete": true,
"Parsed": true
},
"Count": 2,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 214,
"Name": "DOWN_FirstAttack",
"Length": 16,
"PayloadComplete": true,
"Parsed": true
},
"Count": 1,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 856,
"Name": "DOWN_ActorControlTarget",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 1,
"Rejection": null
}
],
"PingPairs": [
{
"Request": 3,
"Response": 4,
"Milliseconds": 83.2735
},
{
"Request": 54,
"Response": 56,
"Milliseconds": 99.9771
},
{
"Request": 222,
"Response": 224,
"Milliseconds": 116.8623
},
{
"Request": 372,
"Response": 374,
"Milliseconds": 83.4204
},
{
"Request": 530,
"Response": 532,
"Milliseconds": 83.4215
},
{
"Request": 683,
"Response": 684,
"Milliseconds": 83.2034
},
{
"Request": 807,
"Response": 808,
"Milliseconds": 100
},
{
"Request": 870,
"Response": 871,
"Milliseconds": 83.2435
}
],
"Limitations": "No raw payload, coordinates or actor IDs included. Successful parsing does not verify all fields. Header-read failures absent from export require UI counters."
}
@@ -0,0 +1,76 @@
# capture-018 首轮完整采样核验与 0.1.9 解析修正
日期:2026-10-11。用户在国际服 2026.09.15.0000.0000 完成 0.1.8 网络采集并导出 `capture-018.jsonl`。时间范围为上海时间 18:12:32—18:13:52,约 80.5 秒。
文件 SHA256:`224AE627F6F6E613662745300C01493E411BDBE02CBA72366CCBD373DD28ECFF`。
本地 Opcode 缓存 SHA256:`2764186EA528587F15D07569816D413E77E8C38C572E4157787B3092BD6D1DB6`。未修改用户导出文件或映射缓存。报告与测试不保存原始坐标、对象 ID 或完整载荷。
## 采集结果
| 检查 | 结果 |
| --- | --- |
| 记录数 | 891:上行 534,下行 357 |
| 完整标记 | 891 完整,0 仅元数据,0 CaptureIssue |
| 序号 | 1—891 连续;单调时间顺序正常 |
| 载荷 | 合计 56,360 字节,单条 8—656 字节,无空载荷 |
| 客户端版本 | 全部匹配当前目标版本 |
36 的首轮完整采样通过文件核验。完整标记还通过已知包长度、当前原生发送构造及回显关系交叉核对。导出不含未形成记录的头部读取失败计数,不能据 CaptureIssue=0 宣称所有未记录调用都无异常;长期性能、反复启停、切图和卸载仍需独立验收。
## 暴露出的旧解析问题
0.1.8 解析器回放仅 2 条返回 Parsed=true(效果结果计数),502 条已有解析器的记录因长度不符被拒绝;其余为尚未接入或名称未知。两类不匹配为:
- 494 个普通移动包,Opcode 920,实际载荷 24 字节,旧 .cs 声明 40 字节。
- 8 个 Ping 请求,Opcode 838,实际载荷 32 字节,旧 .cs 声明 28 字节。
这是旧解析结构的问题,不是新采集随意截断或补齐载荷。原生依据:
- 普通移动入口 RVA 0x62B680。0x62B6CD 写 Opcode 0x398(920);0x62B6D7 写消息长度 0x28。按已核实的发送长度契约减去 0x10,业务载荷确为 0x18。位置字段仍从业务载荷 +8 开始。
- Ping 构造 RVA 0x1D02776 写 Opcode 0x346(838),0x1D0279C 写消息长度 0x30;业务载荷为 0x20。业务偏移 0 是本机毫秒计时值,偏移 4 来自网络模块的上一轮往返计时字段。
0.1.9 仅对完整客户端版本 2026.09.15.0000.0000 使用这些新长度。其他版本/无版本的旧离线调用保持旧行为,不将本次结论跨版本套用。
## Ping 响应映射与语义
原缓存缺少 DOWN_PingRsp。下行 338(0x152)共 8 条、均 32 字节,业务偏移 0 与 8 条 Ping 请求逐一回显匹配。
原生 NetworkModule 在 0x1D0223A 以 0x152 选择分支;0x1D022E1 从 IPC 缓冲区 +0x10(业务偏移 0)读回显计时,0x1D022E7 与当前毫秒计时相减,0x1D022F2 存回网络往返字段。此证据支持本版本 DOWN_PingRsp=338。
响应业务偏移 4 在本次样本中均为 333;原生在 0x1D02307 起将其作为另一路参数使用,不能将它标作 RTT。界面改为未解释的 field04,RTT 仍按请求/响应回显匹配和采集时间差计算。
0.1.9 在有效非空映射加载后,仅当版本匹配、未已有 DOWN_PingRsp 名称且 338 未被占用时补充本地映射,来源注明“本机核实 PingRsp”。不覆盖显式映射,也不改写缓存 JSON。
8 组记录配对的往返时间范围 83.2034—116.8623 ms,平均 91.6752 ms。这是采集点观察值,包含接收调度时间,不宣称是纯网络传输延迟。
## 修正后的同文件回放
| 项目 | 0.1.8 | 0.1.9 |
| --- | --- | --- |
| 有名称 | 716 | 724 |
| 无名称 | 175 | 167 |
| Parsed=true | 2 | 512 |
| 已有解析器但拒绝 | 502 | 0 |
| Ping 配对 | 0 | 8 |
512 条包括普通移动 494、Ping 请求 8、Ping 响应 8、历史效果结果计数 2;后者仍只是有限计数检查,不能将 Parsed=true 理解为所有字段均被完整解释。724 条有名称记录中,另 212 条尚无已接入解析器。
剩余未知下行如下,先保留原始数据,不凭相近数值或长度猜名称:
| Opcode | 长度 | 数量 |
| --- | --- | --- |
| 671 | 72 | 51 |
| 697 | 24 | 51 |
| 558 | 264 | 50 |
| 614 | 16 | 10 |
| 788 | 16 | 4 |
| 214 | 16 | 1 |
下一步优先核对高频未知 Opcode 与状态/动作结果的当前原生分派路径;8 的状态屏蔽仍不因取得样本就直接启用。
## 可复现验证
`Tools/CaptureAudit` 使用工程实际 PacketFiles、OpcodeMap、PacketParser 和 PacketCorrelator 生成只含汇总信息的报告。修正前后结果分别保存在 `2026-10-11-capture-018-before.json`、`2026-10-11-capture-018-after.json`。
Release 构建通过,0 警告、0 错误;60 项离线测试通过,新增版本长度隔离、映射冲突不覆盖、回显与完整性约束。实际文件回放另验证 891 条记录,不把离线测试条数作为现场功能数。
@@ -0,0 +1,312 @@
{
"Source": "capture-018.jsonl",
"SHA256": "224AE627F6F6E613662745300C01493E411BDBE02CBA72366CCBD373DD28ECFF",
"MapSHA256": "2764186EA528587F15D07569816D413E77E8C38C572E4157787B3092BD6D1DB6",
"MapSource": "local cache \u002B \u672C\u673A\u6838\u5B9E 4 \u9879",
"Version": "2026.09.15.0000.0000",
"Records": 891,
"Up": 534,
"Down": 357,
"FirstTime": "2026-10-11T10:12:32.1453158+00:00",
"LastTime": "2026-10-11T10:13:52.6616441+00:00",
"FirstSequence": 1,
"LastSequence": 891,
"SequenceContinuous": true,
"MonotonicOrder": true,
"Complete": 891,
"Incomplete": 0,
"CaptureIssues": 0,
"PayloadBytes": 56360,
"MinPayload": 8,
"MaxPayload": 656,
"EmptyPayloads": 0,
"Known": 876,
"Unknown": 15,
"Parsed": 664,
"SupportedButRejected": 0,
"Groups": [
{
"Key": {
"Direction": 0,
"Opcode": 920,
"Name": "UP_UpdatePositionHandler",
"Length": 24,
"PayloadComplete": true,
"Parsed": true
},
"Count": 494,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 787,
"Name": "DOWN_Effect",
"Length": 124,
"PayloadComplete": true,
"Parsed": false
},
"Count": 52,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 671,
"Name": "DOWN_UpdateHate",
"Length": 72,
"PayloadComplete": true,
"Parsed": true
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 697,
"Name": "DOWN_EffectResultBasic",
"Length": 24,
"PayloadComplete": true,
"Parsed": true
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 558,
"Name": "DOWN_UpdateHater",
"Length": 264,
"PayloadComplete": true,
"Parsed": true
},
"Count": 50,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 516,
"Name": "DOWN_ActorControlSelf",
"Length": 40,
"PayloadComplete": true,
"Parsed": false
},
"Count": 48,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 238,
"Name": "DOWN_ObjectSpawn",
"Length": 64,
"PayloadComplete": true,
"Parsed": false
},
"Count": 38,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 913,
"Name": "UP_ActionSend",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 27,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 524,
"Name": "DOWN_NpcSpawn",
"Length": 656,
"PayloadComplete": true,
"Parsed": false
},
"Count": 18,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 974,
"Name": "DOWN_ActorDelete",
"Length": 8,
"PayloadComplete": true,
"Parsed": false
},
"Count": 12,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 614,
"Name": null,
"Length": 16,
"PayloadComplete": true,
"Parsed": false
},
"Count": 10,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 838,
"Name": "UP_PingReq",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 8,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 338,
"Name": "DOWN_PingRsp",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 8,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 607,
"Name": "DOWN_ActorControl",
"Length": 24,
"PayloadComplete": true,
"Parsed": false
},
"Count": 7,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 391,
"Name": "UP_ClientTrigger",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 5,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 131,
"Name": "DOWN_StatusEffectList",
"Length": 384,
"PayloadComplete": true,
"Parsed": false
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 788,
"Name": null,
"Length": 16,
"PayloadComplete": true,
"Parsed": false
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 305,
"Name": "DOWN_EffectResult",
"Length": 96,
"PayloadComplete": true,
"Parsed": true
},
"Count": 2,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 214,
"Name": null,
"Length": 16,
"PayloadComplete": true,
"Parsed": false
},
"Count": 1,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 856,
"Name": "DOWN_ActorControlTarget",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 1,
"Rejection": null
}
],
"PingPairs": [
{
"Request": 3,
"Response": 4,
"Milliseconds": 83.2735
},
{
"Request": 54,
"Response": 56,
"Milliseconds": 99.9771
},
{
"Request": 222,
"Response": 224,
"Milliseconds": 116.8623
},
{
"Request": 372,
"Response": 374,
"Milliseconds": 83.4204
},
{
"Request": 530,
"Response": 532,
"Milliseconds": 83.4215
},
{
"Request": 683,
"Response": 684,
"Milliseconds": 83.2034
},
{
"Request": 807,
"Response": 808,
"Milliseconds": 100
},
{
"Request": 870,
"Response": 871,
"Milliseconds": 83.2435
}
],
"Limitations": "No raw payload, coordinates or actor IDs included. Successful parsing does not verify all fields. Header-read failures absent from export require UI counters."
}
@@ -0,0 +1,312 @@
{
"Source": "capture-018.jsonl",
"SHA256": "224AE627F6F6E613662745300C01493E411BDBE02CBA72366CCBD373DD28ECFF",
"MapSHA256": "2764186EA528587F15D07569816D413E77E8C38C572E4157787B3092BD6D1DB6",
"MapSource": "local cache \u002B \u672C\u673A\u6838\u5B9E 7 \u9879",
"Version": "2026.09.15.0000.0000",
"Records": 891,
"Up": 534,
"Down": 357,
"FirstTime": "2026-10-11T10:12:32.1453158+00:00",
"LastTime": "2026-10-11T10:13:52.6616441+00:00",
"FirstSequence": 1,
"LastSequence": 891,
"SequenceContinuous": true,
"MonotonicOrder": true,
"Complete": 891,
"Incomplete": 0,
"CaptureIssues": 0,
"PayloadBytes": 56360,
"MinPayload": 8,
"MaxPayload": 656,
"EmptyPayloads": 0,
"Known": 891,
"Unknown": 0,
"Parsed": 679,
"SupportedButRejected": 0,
"Groups": [
{
"Key": {
"Direction": 0,
"Opcode": 920,
"Name": "UP_UpdatePositionHandler",
"Length": 24,
"PayloadComplete": true,
"Parsed": true
},
"Count": 494,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 787,
"Name": "DOWN_Effect",
"Length": 124,
"PayloadComplete": true,
"Parsed": false
},
"Count": 52,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 671,
"Name": "DOWN_UpdateHate",
"Length": 72,
"PayloadComplete": true,
"Parsed": true
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 697,
"Name": "DOWN_EffectResultBasic",
"Length": 24,
"PayloadComplete": true,
"Parsed": true
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 558,
"Name": "DOWN_UpdateHater",
"Length": 264,
"PayloadComplete": true,
"Parsed": true
},
"Count": 50,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 516,
"Name": "DOWN_ActorControlSelf",
"Length": 40,
"PayloadComplete": true,
"Parsed": false
},
"Count": 48,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 238,
"Name": "DOWN_ObjectSpawn",
"Length": 64,
"PayloadComplete": true,
"Parsed": false
},
"Count": 38,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 913,
"Name": "UP_ActionSend",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 27,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 524,
"Name": "DOWN_NpcSpawn",
"Length": 656,
"PayloadComplete": true,
"Parsed": false
},
"Count": 18,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 974,
"Name": "DOWN_ActorDelete",
"Length": 8,
"PayloadComplete": true,
"Parsed": false
},
"Count": 12,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 614,
"Name": "DOWN_JobGauge",
"Length": 16,
"PayloadComplete": true,
"Parsed": true
},
"Count": 10,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 838,
"Name": "UP_PingReq",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 8,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 338,
"Name": "DOWN_PingRsp",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 8,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 607,
"Name": "DOWN_ActorControl",
"Length": 24,
"PayloadComplete": true,
"Parsed": false
},
"Count": 7,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 391,
"Name": "UP_ClientTrigger",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 5,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 131,
"Name": "DOWN_StatusEffectList",
"Length": 384,
"PayloadComplete": true,
"Parsed": false
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 788,
"Name": "DOWN_UpdateClassInfo",
"Length": 16,
"PayloadComplete": true,
"Parsed": true
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 305,
"Name": "DOWN_EffectResult",
"Length": 96,
"PayloadComplete": true,
"Parsed": true
},
"Count": 2,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 214,
"Name": "DOWN_FirstAttack",
"Length": 16,
"PayloadComplete": true,
"Parsed": true
},
"Count": 1,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 856,
"Name": "DOWN_ActorControlTarget",
"Length": 32,
"PayloadComplete": true,
"Parsed": false
},
"Count": 1,
"Rejection": null
}
],
"PingPairs": [
{
"Request": 3,
"Response": 4,
"Milliseconds": 83.2735
},
{
"Request": 54,
"Response": 56,
"Milliseconds": 99.9771
},
{
"Request": 222,
"Response": 224,
"Milliseconds": 116.8623
},
{
"Request": 372,
"Response": 374,
"Milliseconds": 83.4204
},
{
"Request": 530,
"Response": 532,
"Milliseconds": 83.4215
},
{
"Request": 683,
"Response": 684,
"Milliseconds": 83.2034
},
{
"Request": 807,
"Response": 808,
"Milliseconds": 100
},
{
"Request": 870,
"Response": 871,
"Milliseconds": 83.2435
}
],
"Limitations": "No raw payload, coordinates or actor IDs included. Successful parsing does not verify all fields. Header-read failures absent from export require UI counters."
}
+74
View File
@@ -0,0 +1,74 @@
# 状态与原生标识核对
日期:2026 年 10 月 11 日。客户端:国际服 2026.09.15.0000.0000。修订版本:0.1.3。
## 各功能的判断依据
| 编号 | 标识或判断来源 | 本轮结果 |
| --- | --- | --- |
| 1 和 2 | 本地玩家 StatusId,用于减速保护 | 旧 37 项存在;补入当前数据中三个新的玩家 Heavy 状态,现为 40 项 |
| 3 | 原生 Permission 检查编号 | 96—99 属于 Permission 行号;1001 等为该函数特殊分支编号,不是 StatusId |
| 4 | 本地对象地址及击退参数 | 不依赖状态名单;本轮未进行实际击退验收 |
| 5 | 掉落标志位掩码 | 不属于技能或状态 ID |
| 6 | 原生掉落检查返回值 | 不依赖状态名单;实际效果仍待验证 |
| 7 | 本地角色的指定强制坐标移动入口 | 不按状态 ID 筛选,不删除状态;不能据此宣称解除所有眩晕、禁锢或控制 |
| 8 | 旧版 StatusId 名单 | 发现 6 项与原注释分组不符;新版仍没有启用状态屏蔽 |
| 10 和 11 | 深层迷宫类型、层数和 TerritoryType 行号 | 1108 为 Eureka Orthos、1290 为 Pilgrim's Traverse,均为用途 31 |
| 13 | Action 行号、位移属性和例外技能 | 已核对四个例外 ID 及 Guardian 29066,均为技能 ID |
| 14 | 距离检查中的目标对象地址和 Action 位移属性 | 不通过状态 ID 改圈;保留 0.1.2 的作用域限制 |
| 16 | Action.AnimationEnd 映射的 16 位 Timeline,加独立标志字节 | 保留 0.1.2 的全职业位移名单与共用入口修复 |
| 17 和 18 | ActionType、ActionId、冷却组索引 | 天地人 6 个 ActionId 均匹配;同步函数的 57 是零起始冷却组索引 |
| 19 | ActionId 与咏唱时长 | 技能编号与浮点时长分别处理,不属于状态名单 |
| 20 | PVP 场景及动画锁浮点值 | 不按技能或状态 ID 筛选 |
| 36 和 37 | 方向、版本、ushort Opcode | 网络消息类型标识,与上述 ID 空间分开 |
## 旧状态名单的问题
核对本机 Status 表的 Name、Description、LockMovement、LockControl 和 LockActions 后发现:
| ID | 原分组 | 当前名称与含义 | 处理 |
| --- | --- | --- | --- |
| 142 | 滑冰 | Stun,眩晕 | 从已审候选排除 |
| 149 | 滑冰 | Stun,眩晕 | 从已审候选排除 |
| 2538 | 方向命令 | Strong of Shield,减伤及反射相关 | 从已审候选排除 |
| 2539 | 方向命令 | Stronger Together,减伤及反射相关 | 从已审候选排除 |
| 2540 | 方向命令 | Freezing Up,持续移动以避免冻结的机制状态 | 从已审候选排除 |
| 2541 | 方向命令 | 不浄の侵食,倒计时后转为强制远离的前置状态 | 从已审候选排除 |
这是当前数据与原注释分组不符,不代表这些 ID 曾在某个历史版本一定对应另一种状态。旧候选仍单独保留用于审计,已审候选保留 38 项;没有因此启用编号 8。
当前 SDK 中 StatusManager 含 60 个状态条目,每个客户端 Status 为 16 字节,StatusId 字段为 ushort。Owner 字段可能为空。不能把原资料中网络包的 30 条、12 字节条目直接用作客户端状态结构,也不能只修改总容量后就认为完成适配。
## 减速保护
旧 37 个条目在本机数据中都存在。按当前 Status 名称与说明发现三项新的玩家加重状态:5044、5175、5356,说明均为移动速度降低,已加入保护集合。
630 的说明是 Chocobo speed is reduced,归属陆行鸟,不自动纳入这份玩家状态补充。此检查不宣称覆盖全部未来状态。
重度减速并不一定设置 LockMovement。当前的 Heavy、Leaden 等条目该标志为 false,因此无法只依赖一个通用锁定标志实现完整减速识别。
名称模糊匹配也不适合自动建立屏蔽名单:例如 Fearless 和 Honeyed Charms 不等于恐惧或魅惑控制。StatusAudit 的名称检索仅用于产生审核候选,不会用于运行时自动删除状态。
## 强制移动入口
原签名在本机唯一命中 RVA 0x194AEC3 的调用,目标为 RVA 0x90BA80。调用方在栈参数位置写入 float,目标函数也以 movss 读取第五参数,因此将旧 int 声明修正为 float。返回寄存器透传行为保持,未凭这一调用方忽略返回值就假定所有调用都没有返回值。
该入口接受角色、坐标、浮点运动参数和选项结构;没有直接查 StatusId。运行时仅比较本地角色地址并拦截这条路径。它可能承载不止魅惑或恐惧一种强制移动,不应宣称为所有控制状态的通用解除器。已增加当前审计版本限制及界面说明。
## Permission 与冷却组
移动权限签名匹配 RVA 0xE16130,调用 RVA 0x835B50 取得数据。后者传入表号 0x14A;本机 root.exl 将该表号映射为 Permission。
复唱同步签名匹配 RVA 0x8EF260。第二参数传给 RVA 0x8E8300,在该函数中作为 int 组索引计算 RecastDetail 地址;第三参数与结构中的动作编号比较。已将参数明确命名为 manager、recastGroup、actionId、maximum,保留原返回值。
本机 Action 表确认:2259、18805 为 Ten,2261、18806 为 Chi,2263、18807 为 Jin。它们的 Timeline 分别为 233、234、235,不能将 Timeline 当作 ActionId 使用。
## 文件和验证
- `status-id-audit-2026.09.15.json`:状态名称、说明和标志核对数据。
- `action-id-audit-2026.09.15.json`:结印及距离例外技能核对数据。
- `Core/StatusCatalog.cs`:旧候选、已审候选及减速保护分开保存。
- `Core/NativeIds.cs`:Permission 编号、技能 ID、冷却组索引分开命名。
- `Tools/StatusAudit`、`Tools/NativeAudit`:本机游戏数据和磁盘可执行文件只读审计。
0.1.3 的原生参数声明调整及新增减速保护仍待游戏内复测。编号 8 缺少原生签名和网络布局依据,继续保持不可用。
@@ -0,0 +1,55 @@
# 0.1.8 完整游戏载荷采集
基线:国际服 2026.09.15.0000.0000,本机 ffxiv_dx11.exe;实现限定此完整版本。前期线索见 network-length-research.md。本次原生检查只读磁盘文件,不调用原生函数;现场验收尚未完成。
## 上行证据
上行签名唯一匹配 RVA 0x1D718C0,ABI 为 byte(connection, data, arg, byte flag)。data 是发送对象,Opcode 在 +0,消息长度为 +8 的 uint64,业务载荷在 +0x20。
- 0x1D7198C:从 [rsi+8] 取长度,源指针 rsi+0x20,长度减 0x10,调用 0x1DA6CB0。
- 0x1D71A84:另一分支执行相同的复制区间。
- 0x1DA6CB0:按 r8 长度分派复制;0x1DA6DD0 的 16—32 字节分支从 rdx、rdx+r8-0x10 读取并写入 rcx、rcx+r8-0x10,确认其复制含义。
- 0x1CFD1D0 的发送对象创建例:Opcode 在对象 +0,uint64 长度 0x18 在 +8,经 ZoneClient.SendPacket(0x1D03040)进入上述函数。复制的业务长度为 8。
采集发生在发送原函数之前,只表示进入发送路径,不代表发送成功或服务端接收。
## 下行证据与有效期
调用链:NetworkModule 0x1D02040 → ZoneClient.ReceivePacket 0x1D03020 → ZoneReceive 0x1D71440。后者 ABI 为 byte(connection, holder),返回值非零表示接收成功。
- 0x1D71464—0x1D71468:将消息对象写入 holder+0x10。
- 0x1D714D7—0x1D714E0:从 holder+0x10 取对象,再从对象+0x38 取 IPC 缓冲区。
- 对象+0x30 为 uint64 消息长度。接收构造路径 0x1D68875—0x1D6889E 从外层消息长度减去 0x10,按此大小复制到对象+0x38,并将相同大小写入对象+0x30。它包含 0x10 字节 IPC 头。
- 0x20EF800 读取缓冲区+2 的 Opcode,其各分支从缓冲区+0x10 取得业务载荷。
- NetworkModule 0x1D021AD 从对象+0x20 取得目标标识;保留位范围按原函数标准化,不能把对象+0x24 的其他值擅自标为 Source。
- 0x1D02203—0x1D02220 将 IPC 缓冲区交给 Application 接收回调;0x482440 转发到 PacketDispatcher 0x18D9500。
- 0x1D02366—0x1D02370 在分派后释放消息,下一次接收前清空 holder+0x10。Hook 在接收原函数成功返回后立即复制,尚未返回给上述调用者,不保存原生指针供后台使用。
下行签名的栈保存偏移 0x18 必须保留。将其通配后同时匹配 0x1D20BF0(另一接收入口)和 0x1D71440。最终完整签名在当前文件仅匹配一次:
```text
48 89 5C 24 18 57 48 83 EC 20 48 83 B9 88 00 00 00 00 48 8B FA 48 8B D9
```
下行不再挂接 PacketDispatcher,不重复记录同一包,也不从 IPC 指针之前猜读外层头部。
## 读取与失败行为
- 使用 Dalamud.SafeMemory.ReadBytes(当前进程 ReadProcessMemory)复制;没有使用旧结构大小推断原始指针长度。
- 先验证指针、头部读取和 uint64 长度,长度减 0x10 前检查下限及上限,单载荷最多 65536 字节。
- 完整读取才标记 PayloadComplete=true;确实零字节的合法载荷可以完整,不等于失败。
- 已有 Opcode 的异常长度、截断或复制失败保留仅元数据及 CaptureIssue;头部/对象失败不能可靠获得 Opcode,记录异常计数及最近原因,不伪造包。
- 暂停或方向过滤可避免读取对象,Opcode 过滤在读取载荷之前执行。
- 两个原函数都保持一次调用及原参数/返回值;发送在采集后调用,接收先调用再读取成功结果。采集托管异常不会替代游戏原函数结果。
- 记录通过复制成为托管数组;缓冲区按 2048 条和 8 MiB 载荷双重限制,淘汰最旧记录。后台保存只使用这些副本。
- 只覆盖当前版本 Zone 通道。聊天、登录和录像回放通道未挂接。上行 Source/Target、下行 Source 没有足够依据,保持 null。
## 结果与测试
Release 构建通过,0 警告、0 错误;57 项离线测试通过。新增模拟有界内存场景覆盖精确复制区间、对象引用链、目标标准化、恶意 uint64 长度、截断/部分读取、空载荷、64 KiB 上限、无效指针、过滤、错误原因导入导出和缓冲字节预算。
一次新增导出测试使用系统临时目录时受到沙箱文件移动限制;已改为与既有测试一致的测试输出目录,完整构建和测试重跑通过。此修正没有放宽插件文件路径或权限策略。
现场验证:重新加载 0.1.8,开启 36、37,方向全部、Opcode -1;正常移动、使用技能 20—30 秒。观察完整上下行计数是否增长、异常是否出现,再 `/icr export capture-018.jsonl` 并关闭 36。以导出样本核验真实载荷和已有解析,之后再扩展 37。
本版完成采集代码接入与离线边界验证,不把 36 标为游戏内已验证,也不据此宣称 37 的历史解析全部正确。
@@ -0,0 +1,37 @@
# 当前客户端网络长度来源:第一轮核对
客户端:2026.09.15.0000.0000。2026-10-11 继续开发时,只读检查本机 ffxiv_dx11.exe;没有访问游戏进程,也未改动 0.1.7 的采集 Hook。
## 上行已发现长度来源
现有 ZoneUp 签名唯一匹配 RVA 0x1D718C0。参数:rcx 为连接,rdx 为发送对象(保存到 rsi),r8 为附加参数指针,r9b 为标志。
正常状态分支在 RVA 0x1D7198C 附近:
```text
mov r8,[rsi+8]
lea rdx,[rsi+20h]
sub r8,10h
add rcx,10h
call 0x141DA6CB0
```
另一发送分支 0x1D71A84 使用相同的源指针及长度运算。这支持当前版本发送对象的实际复制范围为 `[data+0x20, data+0x20+(u64[data+8]-0x10))`,与旧事件给出的载荷起点 data+0x20 一致;长度不是按 Opcode 历史结构大小推算。
此前 0x1D71942 也把 `[rsi+8]` 传给 0x20F6200 的消息构造流程。唯一直接调用者位于 0x1D03040(ZoneClient.SendPacket 包装),0x1D03065 调用该发送函数。
下一步仍需核实复制辅助函数 0x1DA6CB0 的语义、发送对象创建时的长度契约,并为下限 0x10、最大采集量、版本门控、异常长度回退设计有界读取。此处记录原生证据,不等同于完整采集功能已完成或实测。
## 下行仍缺边界契约
PacketDispatcher 构造签名唯一匹配 0x18D9466,第一虚表为 RVA 0x23129E8,slot 1 指向 OnReceivePacket RVA 0x18D9500。函数开头读取 r8+2 的 ushort Opcode,r8 为现有下行 data,edx 为目标 ID。
ECommons 兼容代码使用载荷起点 data+0x10,并曾取 data-0x10 作为外层头部。这里尚未核实外层对象长度的来源和可读边界,不能仅凭历史包头布局在 data 前反向读取并复制。
下一步从 Application PacketReceiver 回调向下行分派调用追踪外层消息对象的长度,优先寻找明确携带长度的入口。
## 8 状态处理线索
本地 FFXIVClientStructs 的 IDA 标识表提供 HandleStatusEffectListPlayerPacket、HandleStatusEffectListPlayerDoublePacket、HandleStatusEffectListPacket、Eureka、Bozja、Double 等分类入口。这些源码地址不是本机已验证地址,不能直接挂接。现有 StatusManager 则是 60 个 16 字节的客户端状态项,与旧网络列表不是同一结构。
8 仍未启用;后续结合当前 dispatcher 分支、完整下行长度和动作表核对各状态列表入口,不能把某一类 30 项布局套到所有列表。
+51
View File
@@ -0,0 +1,51 @@
# 0.1.13:统一收发观察与独立日志订阅
日期:2026 年 10 月 11 日。用户将本轮工作切到收发包管理器。交付 M1 的只读管理器与日志接入;M4 主动发送、编码器、排队和请求响应事务仍未实现。
## 已接入的能力
- `Runtime/NetworkManager.cs` 管理原有两个 Zone Hook,复用 SharedModuleResource。第一个模块订阅启动 Hook,最后一个模块订阅释放 Hook;关闭 36 只释放记录器自己的订阅,其他模块可以独立持有管理器。
- `Core/NativePacketCapture.cs` 继续负责原有原生长度契约和有界复制,本轮未修改签名、ABI、载荷边界、读取时点、版本限制和原函数参数。
- `Core/NetworkPipeline.cs` 提供 Received、BeforeSend、AfterSend 三种只读观察。每个订阅可独立限定 Opcode,并通过 IDisposable 取消;一个订阅抛异常不会阻断后续订阅或改变原函数调用次数与返回值。
- `Core/PacketRecorder.cs` 将消息写入现有 PacketBuffer。36 保留收包和发送入口两类记录,不额外把发送后事件写成第二条上行记录;暂停、方向过滤和 Opcode 过滤仅作用于记录器。
- 网络面板显示订阅数、收包/发送入口/发送返回的观察计数、订阅异常及最近原生发送返回码。日志暂停时观察仍继续,因此暂停不再等于停止网络内存复制;关闭 36 且无其他消费者时才释放 Hook。
## 接口契约
模块在自己的生命周期入口调用,例如:
```csharp
network.Observe(scope, NetworkPhase.Received, observation =>
{
var message = observation.Message;
// message.Payload is ReadOnlySpan<byte>; only copy/process owned data here.
}, opcode: 338);
```
订阅的建立和释放与现有模块启停一样在框架生命周期代码中执行,不能从原生回调中释放 Hook。回调在原生调用线程同步执行,同一消息同一阶段按注册顺序回调,多个原生线程之间不承诺全局顺序。回调不得操作线程绑定游戏/UI 服务、等待 Framework、主动发送或阻塞;耗时任务由消费者基于自持有数据安排。
上行流程:在发送入口复制一次 → BeforeSend → 原函数恰好一次 → AfterSend。后者包含同一个 NetworkMessage 和原生 byte 返回码;发送前捕获的订阅集合用于两个阶段,发送中途新增的订阅从下次调用开始。原函数抛出时不重试、不伪造 AfterSend。原生返回码未解释为服务端确认。
下行流程:原函数先执行一次,返回非零后才读取 holder → Received;返回零时不读消息。原生读取失败仍保留既有元数据降级或错误计数。捕获和订阅异常处理不包裹原函数,避免异常路径重复调用。
每条 NetworkMessage 自持有不可变载荷副本,外部只有只读 Span,不能取得原生指针或底层可写数组;发送前后共享相同观察 ID 和消息实例。消费者可保留消息,不依赖原生发送对象或接收 holder 的生命周期。无对应观察订阅时跳过复制;有 Opcode 限定时在读头后筛选。
取消后不再进入该订阅的后续分发;已经通过活动检查、开始执行的回调可能结束在取消之后,取消不会强行中止它。释放过程中不持有订阅锁调用消费者;一个回调取消其他尚未执行的订阅时,后者会跳过。插件先释放所有模块作用域再关闭分发器。
## 记录兼容与来源
PacketRecord 新增可选 Context,包含观察 ID、NativeZone 来源、RawIpcPayload 阶段、观察阶段与可用的原生返回码。日志时间使用捕获快照的时间,仍保留独立的缓冲区记录序号。旧 JSONL 缺少 Context 时为 null,界面明确显示阶段未知,不把旧数据伪标为转换后状态。
NativeZone 表示采集入口,不保证实际发送者是游戏本体:其他插件经同一原生入口发送的数据也可能出现。当前管理器不主动发送,也未加入来源归因。RawIpcPayload 是排除 IPC 头的原始游戏载荷,不代表状态 ID 等字段已经转换。编号 8 继续使用自己的转换后 SetStatus 入口。
普通日志仍记录 BeforeSend,因此上行记录里的原生返回码为空;发送后的原始返回码通过 AfterSend 订阅和面板提供。下行记录可以附带接收返回码。观察 ID 只在本次插件实例内关联,不是服务器请求 ID,也不能跨重载用于业务匹配。
## 验证
Release 构建通过,0 警告、0 错误;77 项离线测试通过。新增七组检查针对调用顺序/次数、复制寿命、原生返回码、捕获与订阅异常、接收失败时不读取、日志过滤与独立订阅、取消/重复订阅/卸载、共享 Hook 持有者和新记录字段往返。
复用原 capture-018.jsonl:891 条(534 上行、357 下行)经新分发器与记录器回放后,载荷字节、方向、Opcode、版本、目标、完整性和读取问题逐条一致;发送后观察 534 次,订阅错误与读取错误均为 0。回放使用托管原函数代理返回 1,不代表真实原生发送已实测,更没有重发这些样本。报告见 `2026-10-11-capture-018-manager.json`。
原文件解析仍为全部具名、679 条有限字段解析、0 条已支持格式拒绝、8 组 Ping 配对。原文件及 Opcode 缓存未修改。回放按新观察时间生成临时内存记录;原文件的时间和序号只读保留,Ping/RTT 分析仍用原文件。
现场只需一次聚焦检查:重新加载后开启 36,正常移动,确认管理器计数与日志增加;暂停记录时日志停止增加而管理器继续;解除暂停后恢复;关闭 36 后在当前没有其他消费者的情况下订阅数为 0。性能、切区及卸载仍需现场验收,不要求重新提供泛化抓包。
@@ -0,0 +1,64 @@
# 0.1.10:高频未知 Opcode 核对
基线:国际服 2026.09.15.0000.0000;样本为原 capture-018.jsonl(SHA256 224AE627F6F6E613662745300C01493E411BDBE02CBA72366CCBD373DD28ECFF)。本次只读取原样本及游戏磁盘文件,没有新增 Hook、调用游戏函数或写入原始样本/映射缓存。
## 分派入口定位
PacketDispatcher RVA 0x18D9500 的主分派在 0x18DA549 附近:Opcode 减 101 后,以 0x18DD980 为 uint32 RVA 跳转表,读取对应分支。目标三项如下:
| Opcode | 样本数/长度 | 分派分支 RVA | 游戏处理函数 RVA | 本地补充名称 |
| --- | --- | --- | --- | --- |
| 671 | 51 / 72 字节 | 0x18DAD1E | 0xB4AC90 | DOWN_UpdateHate |
| 558 | 50 / 264 字节 | 0x18DAD4F | 0xB4ACF0 | DOWN_UpdateHater |
| 697 | 51 / 24 字节 | 0x18DAF7E | 0xB39090 | DOWN_EffectResultBasic |
分支均先调用录像记录入口,再将 IPC 缓冲区+0x10 作为业务载荷交给处理函数。主分派前的字段变换路径(0x18DA02C 起)处理的是 607、637、658、778 等值,这三种不会经过其字段变换。
本地 IDA 源码表的旧函数名作为交叉参考;实际地址由当前跳转表及当前机器代码取得,没有直接复用旧地址。
## 671:目标仇恨列表
0xB4AC90 读取业务偏移 0 的 byte 数量;从偏移 4 开始、步长 8 读取 uint32 对象标识及偏移 +4 的 byte 仇恨值。它将结果写入 UIState.Hate 的每项 EntityId/Enmity 和 HateArrayLength:实际数组起点 0x142ACBF28,计数 0x142ACC028,符合 Hate 的 0x100 计数字段。
样本固定 72 字节,数量为 0 或 1。当前解析限定 72 字节,以 4 字节前缀、8 字节步长限制最多 8 项;其余保留字节不解释。客户端 Hate 可容纳 32 项不代表本次这个固定大小包也容纳 32 项。仇恨值按原函数的 byte 读取,不把后面的填充字节拼成 uint32,也不额外推断百分比约束。
## 558:自身敌对列表
0xB4ACF0 采用相同网络条目布局:数量 byte,条目从 +4 开始,每项 8 字节,对象 uint32、仇恨 byte。处理后保存到 UIState.Hater 的 0x48 字节条目:其中前 0x40 字节的名称是客户端另行查找,并非包中的文本。HaterCount 写入 0x142ACC930。
样本固定 264 字节、数量均为 1。解析限定 264 字节、最多 32 项;不把它用于雷达、自动选敌或名单操作,仅展示网络记录中的已核实字段。
## 697:精简效果结果
0xB39090 按业务偏移 0 的 byte 数量循环,条目步长 0x10。相对于第一个条目:
- 业务 +4 的 uint32 用于匹配 ActionEffectHandler 中的动作全局序列;
- 业务 +0x10 的 byte 用于匹配目标序号;
- 业务 +0x0C 的 uint32 写入角色 +0x1AC,对应当前 CharacterData.Health;
- 其余字段继续保留,不凭偏移猜命名。
0x901EC0 根据匹配结果更新效果来源/目标确认标记,进一步支持“效果结果确认”的语义。样本均为 24 字节、数量 1;当前解析限定此固定包、最多 1 项,不据此支持其他数量变体。固定包中的 4 字节尾部不解释。
## 实现边界
三个映射与之前的 PingRsp 一起集中到 CurrentProtocolEvidence。仅当完整客户端版本匹配、Opcode 未被占用且名称尚不存在时补充,来源显示本机核实的新增项数。尊重用户或远程文件中已有的显式映射,缓存 JSON 不改写。
解析同样限定当前完整版本,检查固定长度与数量上限。显示已核实字段不代表所有字节都已解释。8 的状态屏蔽保持不可用;本轮没有把仇恨或动作确认包误当状态列表。
## 验证与进度
Release 构建通过,0 警告、0 错误;64 项离线测试通过,新增容量、步长、byte 字段、版本隔离、映射冲突和 1500 个任意长度/计数输入检查。
原 891 条记录回放:
| 项目 | 0.1.9 | 0.1.10 |
| --- | --- | --- |
| 有名称 | 724 | 876 |
| 未知记录 | 167 | 15 |
| Parsed=true | 512 | 664 |
| 已支持格式拒绝 | 0 | 0 |
| Ping 配对 | 8 | 8 |
新识别的 152 条全部通过当前有限字段解析;完整汇总保存为 2026-10-11-capture-018-v0110.json,不含真实载荷、坐标或对象标识。仍有 212 条已命名包未实现解析;Parsed=true 也不表示全字段解释完成。
剩余未知:614(16 字节,10 条)、788(16 字节,4 条)、214(16 字节,1 条)。对应当前分派线索分别为 0x18DD1FE → 0x8FE360、0x18DAF0E → 0xB38BB0、0x18DAFCC → 0xB39480;名称及完整语义下一轮核对,当前不补猜测映射。
@@ -0,0 +1,43 @@
# 0.1.11:剩余三种 Opcode 与状态处理边界
基线:国际服 2026.09.15.0000.0000。使用原 capture-018.jsonl 及本机游戏磁盘文件;原始样本、Opcode 缓存和运行 Hook 不改动。
## 614:职业量表更新
分派 0x18DD1FE 将业务载荷交给 0x8FE360,管理对象地址为 0x142A95710。函数比较包偏移 0 与管理器+0x58;一致时调用当前量表的虚函数,否则转到 0x8FE590 按 ClassJob 切换量表。当前 FFXIVClientStructs.dll 元数据确认 JobGaugeManager.ClassJobId 在 +0x58。
10 条样本均 16 字节、职业字节 31。仅解释职业 ID,其余职业专属数据保留,不凭其他职业的量表布局套用。
现有用户映射已含 `DOWN_ActorGauge=[8]`,而 614 未命名。本次使用独立的证据标签 `DOWN_JobGauge=614`,不覆盖原 8,也不宣称原 8 的语义经过本轮验证。仍遵守已有同名/同 Opcode 显式映射不覆盖规则。
## 788:职业信息更新
分派 0x18DAF0E → 0xB38BB0 → 0xB38AB0。后者将业务偏移 0 的职业字节交给 PlayerState 的职业更新路径,偏移 2 的 ushort 交给 0xBE7B90,后者写 PlayerState+0x88(CurrentLevel);偏移 8 的 uint32 交给 0xBE8000,后者经职业索引写 +0xD0 的职业经验数组。
当前 DLL 元数据确认 PlayerState.CurrentClassJobId=0x7E、CurrentLevel=0x88、classJobExperience=0xD0。四条 16 字节样本的职业 ID 为 31、当前等级为 100。
补充 `DOWN_UpdateClassInfo=788`,只解释职业、当前等级和经验;偏移 4、6、12 等其他值本轮不命名。
## 214:战斗归属
分派 0x18DAFCC → 0xB39480。函数按收到的目标 ID 找到角色,将业务偏移 0 的 byte 写角色+0x1D5,并将偏移 8 的 uint64 写角色+0x1D8。
当前 DLL 中 CharacterData 在角色+0x1A0,CombatTagType 在 CharacterData+0x35,CombatTaggerId 在 +0x38,正好对应这两次写入。补充 `DOWN_FirstAttack=214`,界面解释为战斗归属类型和 64 位标记者 ID,不解释为一次伤害或技能 ID。样本一条、16 字节。
## 状态列表为 8 提供的新依据
已命名的 DOWN_StatusEffectList(Opcode 131)在本次样本有四条、每条 384 字节。当前分派链是 0x18DAE4B → 0xB385F0 → 0xB37F90。消费函数将业务载荷+0x14 交给状态管理器批量处理函数 0x8A78F0。
0x8A78F0 明确循环 30 次、步长 12:从条目+0 读 ushort 状态 ID、+2 读 ushort 参数、+4 读 float 持续时间、+8 读 uint32 来源,再调用 0x8A6BF0 设置状态。网络块为 360 字节,前缀 20 字节,共到 380;本次 384 字节消息的末尾 4 字节不解释。旧 240 字节固定缓冲和 Size=8 声明不能直接恢复使用。客户端的 60 个 16 字节状态项仍是另一种内存结构。
另一个关键限制:PacketDispatcher 在 Opcode 131 的 0x18D97FC 分支先复制 IPC 消息,再对 30 个状态 ID 执行减去会话相关值的转换,随后才交给最终消费函数。转换由前置条件控制,不等于每次抓到的状态 ID 都已经是可直接与 Status 表比较的值。当前 36 在分派前记录原始业务载荷,不带完整会话转换上下文,因此不能仅凭旧捕获文件直接实现状态 ID 屏蔽。
下一步为 8 核对转换后的入口、正常与双列表/回放差异、本地 StatusManager 的身份门控及标志更新过程。尚未完成这些前提,8 继续不可用。本轮没有修改或删除任何角色状态。
## 验证与范围
Release 构建通过,0 警告、0 错误;66 项离线测试通过。新增三种固定包长度/版本隔离、64 位标识保真、原 ActorGauge 映射保留检查。
同一份 891 条文件回放:有名称 891、未知 0、有限字段解析通过 679、已支持格式拒绝 0,Ping 仍 8 组。报告为 2026-10-11-capture-018-v0111.json,不含真实载荷或对象标识。
这只说明本份样本中的 Opcode 均有名称,不代表未来采样不会再出现未知 Opcode,更不代表所有协议已还原。212 条已命名记录仍无解析器;职业量表也仅解析了职业 ID,其他字节继续保留。
@@ -0,0 +1,552 @@
{
"Source": "E:\\SapphireServer\\Dalamud Dev\\IC\\I-Ching-GL (2).dll",
"SHA256": "CE269139FDFDB136BE382E10BE78E6E0BC346DEB335E9D99DF2E80097BD76CBF",
"Assembly": "I-Ching-GL, Version=0.1.6.6, Culture=neutral, PublicKeyToken=null",
"Runtime": "v4.0.30319",
"References": [
{
"Name": "System.Runtime",
"Version": "10.0.0.0"
},
{
"Name": "System.Collections",
"Version": "10.0.0.0"
},
{
"Name": "Dalamud",
"Version": "15.0.3.6"
},
{
"Name": "System.Numerics.Vectors",
"Version": "10.0.0.0"
},
{
"Name": "System.Net.Http",
"Version": "10.0.0.0"
},
{
"Name": "System.Security.Cryptography",
"Version": "10.0.0.0"
},
{
"Name": "System.Diagnostics.Process",
"Version": "10.0.0.0"
},
{
"Name": "System.Text.RegularExpressions",
"Version": "10.0.0.0"
},
{
"Name": "System.Management",
"Version": "9.0.0.2"
},
{
"Name": "System.Threading.Tasks.Parallel",
"Version": "10.0.0.0"
},
{
"Name": "TerraFX.Interop.Windows",
"Version": "10.0.26100.5"
},
{
"Name": "Dalamud.Bindings.ImGui",
"Version": "1.0.0.0"
},
{
"Name": "FFXIVClientStructs",
"Version": "7.56.2.9418"
},
{
"Name": "System.Runtime.Numerics",
"Version": "10.0.0.0"
},
{
"Name": "System.Linq.Expressions",
"Version": "10.0.0.0"
},
{
"Name": "Lumina",
"Version": "0.0.0.0"
},
{
"Name": "Lumina.Excel",
"Version": "7.0.0.0"
},
{
"Name": "Newtonsoft.Json",
"Version": "13.0.0.0"
},
{
"Name": "System.Threading.Thread",
"Version": "10.0.0.0"
},
{
"Name": "System.Linq",
"Version": "10.0.0.0"
},
{
"Name": "System.Memory",
"Version": "10.0.0.0"
},
{
"Name": "System.Threading",
"Version": "10.0.0.0"
},
{
"Name": "System.Text.Encoding.Extensions",
"Version": "10.0.0.0"
},
{
"Name": "Microsoft.Win32.Registry",
"Version": "10.0.0.0"
},
{
"Name": "System.Runtime.InteropServices",
"Version": "10.0.0.0"
},
{
"Name": "ECommons",
"Version": "3.2.1.17"
},
{
"Name": "System.Console",
"Version": "10.0.0.0"
},
{
"Name": "mscorlib",
"Version": "4.0.0.0"
},
{
"Name": "D6804B14",
"Version": "0.0.0.0"
}
],
"Types": [
{
"Name": "StatusEffectList",
"Attributes": "Public, ExplicitLayout, Sealed, BeforeFieldInit",
"DeclaredSize": -1,
"PackingSize": -1,
"Fields": [
{
"Name": "EntryData",
"Type": "StatusEffectList/<EntryData>e__FixedBuffer",
"Offset": 20
}
],
"NestedTypes": [
{
"Name": "StatusEffectList/<EntryData>e__FixedBuffer",
"DeclaredSize": 240,
"DelegateInvoke": []
}
],
"Methods": [
{
"Signature": "System.Span`1<StatusEffectListEntry> StatusEffectList::get_Entries()",
"Token": 100663317,
"RVA": "0x2AE44",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
}
]
},
{
"Name": "StatusEffectListEntry",
"Attributes": "Public, ExplicitLayout, Sealed, BeforeFieldInit",
"DeclaredSize": 8,
"PackingSize": 1,
"Fields": [
{
"Name": "StatusID",
"Type": "System.UInt16",
"Offset": 0
},
{
"Name": "StackCount",
"Type": "System.UInt16",
"Offset": 2
},
{
"Name": "RemainingTime",
"Type": "System.Single",
"Offset": 4
},
{
"Name": "SourceID",
"Type": "System.UInt32",
"Offset": 8
}
],
"NestedTypes": [],
"Methods": []
},
{
"Name": "SamplePlugin.Hook.ActorRadiusHook",
"Attributes": "Public, BeforeFieldInit",
"DeclaredSize": -1,
"PackingSize": -1,
"Fields": [
{
"Name": "_configuration",
"Type": "SamplePlugin.Configuration",
"Offset": -1
},
{
"Name": "_ActorRadiusHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.ActorRadiusHook/ActorRadiusDelegate>",
"Offset": -1
}
],
"NestedTypes": [
{
"Name": "SamplePlugin.Hook.ActorRadiusHook/ActorRadiusDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.Single SamplePlugin.Hook.ActorRadiusHook/ActorRadiusDelegate::Invoke(System.UInt64,System.Byte)"
]
}
],
"Methods": [
{
"Signature": "System.Void SamplePlugin.Hook.ActorRadiusHook::.ctor(SamplePlugin.Configuration)",
"Token": 100664138,
"RVA": "0x2CA9D4",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.ActorRadiusHook::Dispose()",
"Token": 100664139,
"RVA": "0x2CB41C",
"BodyState": "SuspiciousBody",
"DeclaredCodeSize": -1812037104,
"Error": null,
"UnvalidatedIL": null
},
{
"Signature": "System.Single SamplePlugin.Hook.ActorRadiusHook::ActorRadiusDetour(System.UInt64,System.Byte)",
"Token": 100664140,
"RVA": "0x2CB9F4",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
}
]
},
{
"Name": "SamplePlugin.Hook.NoActionMoveHook",
"Attributes": "Public, BeforeFieldInit",
"DeclaredSize": -1,
"PackingSize": -1,
"Fields": [
{
"Name": "_configuration",
"Type": "SamplePlugin.Configuration",
"Offset": -1
},
{
"Name": "_NoActionMoveHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.NoActionMoveHook/NoActionMoveDelegate>",
"Offset": -1
}
],
"NestedTypes": [
{
"Name": "SamplePlugin.Hook.NoActionMoveHook/NoActionMoveDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.UInt64 SamplePlugin.Hook.NoActionMoveHook/NoActionMoveDelegate::Invoke(System.UInt64,System.Byte,System.UInt64,System.Single,System.IntPtr)"
]
},
{
"Name": "SamplePlugin.Hook.NoActionMoveHook/<>c",
"DeclaredSize": -1,
"DelegateInvoke": []
}
],
"Methods": [
{
"Signature": "System.Void SamplePlugin.Hook.NoActionMoveHook::.ctor(SamplePlugin.Configuration)",
"Token": 100664144,
"RVA": "0x2CD19C",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.NoActionMoveHook::Dispose()",
"Token": 100664145,
"RVA": "0x2CDA34",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Collections.Generic.List`1<System.UInt32> SamplePlugin.Hook.NoActionMoveHook::GetAllTimelineIds()",
"Token": 100664146,
"RVA": "0x2CDFA0",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.UInt64 SamplePlugin.Hook.NoActionMoveHook::NoActionMoveDetour(System.UInt64,System.Byte,System.UInt64,System.Single,System.IntPtr)",
"Token": 100664147,
"RVA": "0x2CE2EC",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
}
]
},
{
"Name": "SamplePlugin.Hook.YMove",
"Attributes": "Public, BeforeFieldInit",
"DeclaredSize": -1,
"PackingSize": -1,
"Fields": [
{
"Name": "_configuration",
"Type": "SamplePlugin.Configuration",
"Offset": -1
},
{
"Name": "_SendNormalMoveHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.YMove/SendNormalMoveDelegate>",
"Offset": -1
},
{
"Name": "_SendCombatMoveHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.YMove/SendCombatMoveDelegate>",
"Offset": -1
},
{
"Name": "_TryToGetDeepDStage",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.YMove/TryToGetDeepDStageDelegate>",
"Offset": -1
},
{
"Name": "offset",
"Type": "System.Int32",
"Offset": -1
},
{
"Name": "decryptor",
"Type": "SamplePlugin.Hook.BaguaDecryptor",
"Offset": -1
}
],
"NestedTypes": [
{
"Name": "SamplePlugin.Hook.YMove/SendNormalMoveDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.IntPtr SamplePlugin.Hook.YMove/SendNormalMoveDelegate::Invoke(System.UIntPtr,System.IntPtr,System.UInt32)"
]
},
{
"Name": "SamplePlugin.Hook.YMove/SendCombatMoveDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.IntPtr SamplePlugin.Hook.YMove/SendCombatMoveDelegate::Invoke(System.UIntPtr,System.IntPtr,System.UInt32)"
]
},
{
"Name": "SamplePlugin.Hook.YMove/TryToGetDeepDStageDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.Void SamplePlugin.Hook.YMove/TryToGetDeepDStageDelegate::Invoke(System.Int64,System.Int64)"
]
}
],
"Methods": [
{
"Signature": "System.Void SamplePlugin.Hook.YMove::.ctor(SamplePlugin.Configuration)",
"Token": 100664221,
"RVA": "0x3112D0",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.String SamplePlugin.Hook.YMove::CombineOffsets(System.Byte,System.Byte)",
"Token": 100664222,
"RVA": "0x312214",
"BodyState": "SuspiciousBody",
"DeclaredCodeSize": 19,
"Error": null,
"UnvalidatedIL": null
},
{
"Signature": "System.Int32 SamplePlugin.Hook.YMove::ConvertHexStringToInt(System.String)",
"Token": 100664223,
"RVA": "0x312670",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Object reference not set to an instance of an object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.YMove::SafeAreaCheckPlus(Dalamud.Plugin.Services.IFramework)",
"Token": 100664224,
"RVA": "0x312994",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.YMove::Dispose()",
"Token": 100664225,
"RVA": "0x313228",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
},
{
"Signature": "System.IntPtr SamplePlugin.Hook.YMove::SendNormalMoveDetour(System.UIntPtr,System.IntPtr,System.UInt32)",
"Token": 100664226,
"RVA": "0x313B34",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.IntPtr SamplePlugin.Hook.YMove::SendCombatMoveDetour(System.UIntPtr,System.IntPtr,System.UInt32)",
"Token": 100664227,
"RVA": "0x3166B4",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.YMove::TryToGetDeepDStageDetour(System.Int64,System.Int64)",
"Token": 100664228,
"RVA": "0x3195F0",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
}
]
},
{
"Name": "SamplePlugin.Hook.StatusCheck",
"Attributes": "Public, BeforeFieldInit",
"DeclaredSize": -1,
"PackingSize": -1,
"Fields": [
{
"Name": "_configuration",
"Type": "SamplePlugin.Configuration",
"Offset": -1
},
{
"Name": "_StatusCheckHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.StatusCheck/StatusCheckDelegate>",
"Offset": -1
},
{
"Name": "_ProcessPacketStatusEffectHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegate>",
"Offset": -1
},
{
"Name": "_ProcessPacketStatusEffectHookGL",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegateGL>",
"Offset": -1
},
{
"Name": "decryptor",
"Type": "SamplePlugin.Hook.BaguaDecryptor",
"Offset": -1
}
],
"NestedTypes": [
{
"Name": "SamplePlugin.Hook.StatusCheck/StatusCheckDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.Void SamplePlugin.Hook.StatusCheck/StatusCheckDelegate::Invoke(FFXIVClientStructs.FFXIV.Client.Game.StatusManager*)"
]
},
{
"Name": "SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.Void SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegate::Invoke(System.UInt32,StatusEffectList*,System.Boolean)"
]
},
{
"Name": "SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegateGL",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.Void SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegateGL::Invoke(System.UInt32,StatusEffectList*,System.Boolean,System.Boolean)"
]
}
],
"Methods": [
{
"Signature": "System.Void SamplePlugin.Hook.StatusCheck::.ctor(SamplePlugin.Configuration)",
"Token": 100664232,
"RVA": "0x31BE1C",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.StatusCheck::Dispose()",
"Token": 100664233,
"RVA": "0x31CB68",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.StatusCheck::StatusCheckDetour(FFXIVClientStructs.FFXIV.Client.Game.StatusManager*)",
"Token": 100664234,
"RVA": "0x31D2B0",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.StatusCheck::ProcessPacketStatusEffectDetourGL(System.UInt32,StatusEffectList*,System.Boolean,System.Boolean)",
"Token": 100664235,
"RVA": "0x31EF04",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.StatusCheck::ProcessPacketStatusEffectDetour(System.UInt32,StatusEffectList*,System.Boolean)",
"Token": 100664236,
"RVA": "0x320A44",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
}
]
}
],
"Limitation": "Metadata only. Method-body parsing is not proof of executable logic. Target assembly was not executed."
}
@@ -0,0 +1,528 @@
{
"Source": "E:\\SapphireServer\\Dalamud Dev\\IC\\I-Ching-GL.dll",
"SHA256": "DA648072A2CE0856B4884A332EFAC063FC8F0E03236D7D4DBC9334BF0B2A2AA8",
"Assembly": "I-Ching-GL, Version=0.1.6.6, Culture=neutral, PublicKeyToken=null",
"Runtime": "v4.0.30319",
"References": [
{
"Name": "System.Runtime",
"Version": "10.0.0.0"
},
{
"Name": "System.Collections",
"Version": "10.0.0.0"
},
{
"Name": "Dalamud",
"Version": "15.0.3.6"
},
{
"Name": "System.Numerics.Vectors",
"Version": "10.0.0.0"
},
{
"Name": "System.Diagnostics.Process",
"Version": "10.0.0.0"
},
{
"Name": "System.Text.RegularExpressions",
"Version": "10.0.0.0"
},
{
"Name": "System.Management",
"Version": "9.0.0.2"
},
{
"Name": "System.Threading.Tasks.Parallel",
"Version": "10.0.0.0"
},
{
"Name": "TerraFX.Interop.Windows",
"Version": "10.0.26100.5"
},
{
"Name": "Dalamud.Bindings.ImGui",
"Version": "1.0.0.0"
},
{
"Name": "FFXIVClientStructs",
"Version": "7.56.2.9458"
},
{
"Name": "Lumina",
"Version": "0.0.0.0"
},
{
"Name": "System.Threading.Thread",
"Version": "10.0.0.0"
},
{
"Name": "Lumina.Excel",
"Version": "7.0.0.0"
},
{
"Name": "Newtonsoft.Json",
"Version": "13.0.0.0"
},
{
"Name": "System.Linq",
"Version": "10.0.0.0"
},
{
"Name": "ECommons",
"Version": "3.2.1.17"
},
{
"Name": "System.Runtime.InteropServices",
"Version": "10.0.0.0"
},
{
"Name": "System.Console",
"Version": "10.0.0.0"
},
{
"Name": "System.Memory",
"Version": "10.0.0.0"
},
{
"Name": "System.Threading",
"Version": "10.0.0.0"
},
{
"Name": "mscorlib",
"Version": "4.0.0.0"
},
{
"Name": "DEC473AF",
"Version": "0.0.0.0"
}
],
"Types": [
{
"Name": "StatusEffectList",
"Attributes": "Public, ExplicitLayout, Sealed, BeforeFieldInit",
"DeclaredSize": -1,
"PackingSize": -1,
"Fields": [
{
"Name": "EntryData",
"Type": "StatusEffectList/<EntryData>e__FixedBuffer",
"Offset": 20
}
],
"NestedTypes": [
{
"Name": "StatusEffectList/<EntryData>e__FixedBuffer",
"DeclaredSize": 240,
"DelegateInvoke": []
}
],
"Methods": [
{
"Signature": "System.Span`1<StatusEffectListEntry> StatusEffectList::get_Entries()",
"Token": 100663303,
"RVA": "0x1D5BC",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
}
]
},
{
"Name": "StatusEffectListEntry",
"Attributes": "Public, ExplicitLayout, Sealed, BeforeFieldInit",
"DeclaredSize": 8,
"PackingSize": 1,
"Fields": [
{
"Name": "StatusID",
"Type": "System.UInt16",
"Offset": 0
},
{
"Name": "StackCount",
"Type": "System.UInt16",
"Offset": 2
},
{
"Name": "RemainingTime",
"Type": "System.Single",
"Offset": 4
},
{
"Name": "SourceID",
"Type": "System.UInt32",
"Offset": 8
}
],
"NestedTypes": [],
"Methods": []
},
{
"Name": "SamplePlugin.Hook.ActorRadiusHook",
"Attributes": "Public, BeforeFieldInit",
"DeclaredSize": -1,
"PackingSize": -1,
"Fields": [
{
"Name": "_configuration",
"Type": "SamplePlugin.Configuration",
"Offset": -1
},
{
"Name": "_ActorRadiusHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.ActorRadiusHook/ActorRadiusDelegate>",
"Offset": -1
}
],
"NestedTypes": [
{
"Name": "SamplePlugin.Hook.ActorRadiusHook/ActorRadiusDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.Single SamplePlugin.Hook.ActorRadiusHook/ActorRadiusDelegate::Invoke(System.UInt64,System.Byte)"
]
}
],
"Methods": [
{
"Signature": "System.Void SamplePlugin.Hook.ActorRadiusHook::.ctor(SamplePlugin.Configuration)",
"Token": 100663839,
"RVA": "0x1F1EB0",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.ActorRadiusHook::Dispose()",
"Token": 100663840,
"RVA": "0x1F2A78",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
},
{
"Signature": "System.Single SamplePlugin.Hook.ActorRadiusHook::ActorRadiusDetour(System.UInt64,System.Byte)",
"Token": 100663841,
"RVA": "0x1F2F94",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
}
]
},
{
"Name": "SamplePlugin.Hook.NoActionMoveHook",
"Attributes": "Public, BeforeFieldInit",
"DeclaredSize": -1,
"PackingSize": -1,
"Fields": [
{
"Name": "_configuration",
"Type": "SamplePlugin.Configuration",
"Offset": -1
},
{
"Name": "_NoActionMoveHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.NoActionMoveHook/NoActionMoveDelegate>",
"Offset": -1
}
],
"NestedTypes": [
{
"Name": "SamplePlugin.Hook.NoActionMoveHook/NoActionMoveDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.UInt64 SamplePlugin.Hook.NoActionMoveHook/NoActionMoveDelegate::Invoke(System.UInt64,System.Byte,System.UInt64,System.Single,System.IntPtr)"
]
},
{
"Name": "SamplePlugin.Hook.NoActionMoveHook/<>c",
"DeclaredSize": -1,
"DelegateInvoke": []
}
],
"Methods": [
{
"Signature": "System.Void SamplePlugin.Hook.NoActionMoveHook::.ctor(SamplePlugin.Configuration)",
"Token": 100663845,
"RVA": "0x1F4794",
"BodyState": "SuspiciousBody",
"DeclaredCodeSize": -1346900411,
"Error": null,
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.NoActionMoveHook::Dispose()",
"Token": 100663846,
"RVA": "0x1F511C",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
},
{
"Signature": "System.Collections.Generic.List`1<System.UInt32> SamplePlugin.Hook.NoActionMoveHook::GetAllTimelineIds()",
"Token": 100663847,
"RVA": "0x1F577C",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.UInt64 SamplePlugin.Hook.NoActionMoveHook::NoActionMoveDetour(System.UInt64,System.Byte,System.UInt64,System.Single,System.IntPtr)",
"Token": 100663848,
"RVA": "0x1F5AF8",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
}
]
},
{
"Name": "SamplePlugin.Hook.YMove",
"Attributes": "Public, BeforeFieldInit",
"DeclaredSize": -1,
"PackingSize": -1,
"Fields": [
{
"Name": "_configuration",
"Type": "SamplePlugin.Configuration",
"Offset": -1
},
{
"Name": "_SendNormalMoveHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.YMove/SendNormalMoveDelegate>",
"Offset": -1
},
{
"Name": "_SendCombatMoveHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.YMove/SendCombatMoveDelegate>",
"Offset": -1
},
{
"Name": "_TryToGetDeepDStage",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.YMove/TryToGetDeepDStageDelegate>",
"Offset": -1
},
{
"Name": "offset",
"Type": "System.Int32",
"Offset": -1
},
{
"Name": "decryptor",
"Type": "SamplePlugin.Hook.BaguaDecryptor",
"Offset": -1
}
],
"NestedTypes": [
{
"Name": "SamplePlugin.Hook.YMove/SendNormalMoveDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.IntPtr SamplePlugin.Hook.YMove/SendNormalMoveDelegate::Invoke(System.UIntPtr,System.IntPtr,System.UInt32)"
]
},
{
"Name": "SamplePlugin.Hook.YMove/SendCombatMoveDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.IntPtr SamplePlugin.Hook.YMove/SendCombatMoveDelegate::Invoke(System.UIntPtr,System.IntPtr,System.UInt32)"
]
},
{
"Name": "SamplePlugin.Hook.YMove/TryToGetDeepDStageDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.Void SamplePlugin.Hook.YMove/TryToGetDeepDStageDelegate::Invoke(System.Int64,System.Int64)"
]
}
],
"Methods": [
{
"Signature": "System.Void SamplePlugin.Hook.YMove::.ctor(SamplePlugin.Configuration)",
"Token": 100663922,
"RVA": "0x2388B8",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Object reference not set to an instance of an object.",
"UnvalidatedIL": null
},
{
"Signature": "System.String SamplePlugin.Hook.YMove::CombineOffsets(System.Byte,System.Byte)",
"Token": 100663923,
"RVA": "0x23996C",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
},
{
"Signature": "System.Int32 SamplePlugin.Hook.YMove::ConvertHexStringToInt(System.String)",
"Token": 100663924,
"RVA": "0x239DD4",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Object reference not set to an instance of an object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.YMove::SafeAreaCheckPlus(Dalamud.Plugin.Services.IFramework)",
"Token": 100663925,
"RVA": "0x23A0C8",
"BodyState": "SuspiciousBody",
"DeclaredCodeSize": 3,
"Error": null,
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.YMove::Dispose()",
"Token": 100663926,
"RVA": "0x23A9C4",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Object reference not set to an instance of an object.",
"UnvalidatedIL": null
},
{
"Signature": "System.IntPtr SamplePlugin.Hook.YMove::SendNormalMoveDetour(System.UIntPtr,System.IntPtr,System.UInt32)",
"Token": 100663927,
"RVA": "0x23B30C",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.IntPtr SamplePlugin.Hook.YMove::SendCombatMoveDetour(System.UIntPtr,System.IntPtr,System.UInt32)",
"Token": 100663928,
"RVA": "0x23CDCC",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.YMove::TryToGetDeepDStageDetour(System.Int64,System.Int64)",
"Token": 100663929,
"RVA": "0x23EE1C",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
}
]
},
{
"Name": "SamplePlugin.Hook.StatusCheck",
"Attributes": "Public, BeforeFieldInit",
"DeclaredSize": -1,
"PackingSize": -1,
"Fields": [
{
"Name": "_configuration",
"Type": "SamplePlugin.Configuration",
"Offset": -1
},
{
"Name": "_StatusCheckHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.StatusCheck/StatusCheckDelegate>",
"Offset": -1
},
{
"Name": "_ProcessPacketStatusEffectHook",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegate>",
"Offset": -1
},
{
"Name": "_ProcessPacketStatusEffectHookGL",
"Type": "Dalamud.Hooking.Hook`1<SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegateGL>",
"Offset": -1
},
{
"Name": "decryptor",
"Type": "SamplePlugin.Hook.BaguaDecryptor",
"Offset": -1
}
],
"NestedTypes": [
{
"Name": "SamplePlugin.Hook.StatusCheck/StatusCheckDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.Void SamplePlugin.Hook.StatusCheck/StatusCheckDelegate::Invoke(FFXIVClientStructs.FFXIV.Client.Game.StatusManager*)"
]
},
{
"Name": "SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegate",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.Void SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegate::Invoke(System.UInt32,StatusEffectList*,System.Boolean)"
]
},
{
"Name": "SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegateGL",
"DeclaredSize": -1,
"DelegateInvoke": [
"System.Void SamplePlugin.Hook.StatusCheck/ProcessPacketStatusEffectHookDelegateGL::Invoke(System.UInt32,StatusEffectList*,System.Boolean,System.Boolean)"
]
}
],
"Methods": [
{
"Signature": "System.Void SamplePlugin.Hook.StatusCheck::.ctor(SamplePlugin.Configuration)",
"Token": 100663933,
"RVA": "0x241E48",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.StatusCheck::Dispose()",
"Token": 100663934,
"RVA": "0x242A88",
"BodyState": "SuspiciousBody",
"DeclaredCodeSize": 1038335658,
"Error": null,
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.StatusCheck::StatusCheckDetour(FFXIVClientStructs.FFXIV.Client.Game.StatusManager*)",
"Token": 100663935,
"RVA": "0x24325C",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.StatusCheck::ProcessPacketStatusEffectDetourGL(System.UInt32,StatusEffectList*,System.Boolean,System.Boolean)",
"Token": 100663936,
"RVA": "0x245510",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Index was outside the bounds of the array.",
"UnvalidatedIL": null
},
{
"Signature": "System.Void SamplePlugin.Hook.StatusCheck::ProcessPacketStatusEffectDetour(System.UInt32,StatusEffectList*,System.Boolean)",
"Token": 100663937,
"RVA": "0x246F9C",
"BodyState": "ReadError",
"DeclaredCodeSize": null,
"Error": "Operation is not valid due to the current state of the object.",
"UnvalidatedIL": null
}
]
}
],
"Limitation": "Metadata only. Method-body parsing is not proof of executable logic. Target assembly was not executed."
}
+44
View File
@@ -0,0 +1,44 @@
# 原版 DLL 参考核对
日期:2026-10-11。用户提供 `IC/I-Ching-GL.dll`,原件保留未修改。
## 文件与依赖
- 大小:5,811,712 字节。
- 程序集:`I-Ching-GL, Version=0.1.6.6`。
- SHA256:`DA648072A2CE0856B4884A332EFAC063FC8F0E03236D7D4DBC9334BF0B2A2AA8`。
- 引用:System.Runtime 10.0.0.0、Dalamud 15.0.3.6、FFXIVClientStructs 7.56.2.9458、ECommons 3.2.1.17。
- 本机重建工程所用 FFXIVClientStructs 程序集为 7.56.2.9136。两者构建版本不同,不能直接将 DLL 的结构假设视为当前运行库已验证布局。
使用本机 Mono.Cecil 静态读取文件,没有通过 Assembly.Load 加载原版,没有执行模块初始化器或原版插件逻辑。
## 可核实的接口
| 对应功能 | DLL 元数据 | 与现有资料的关系 |
| --- | --- | --- |
| 14 目标半径 | ActorRadiusDetour / 委托:float(ulong, byte) | 与 IC/CombatHook.cs 的签名一致;不能据签名确定过滤对象或加值方式 |
| 9 高度偏移 | YMove 的普通、战斗路径均为 IntPtr(UIntPtr, IntPtr, uint) | 与现有两条移动路径的参数形状一致;不能据此确认字节偏移或是否恢复原值 |
| 16 突进无位移 | 旧入口委托:ulong(ulong, byte, ulong, float, IntPtr) | 与旧 .cs 一致;重建工程已基于当前原生入口及用户测试改用共用六参数入口,不退回旧入口 |
| 8 状态处理 | StatusCheckDetour(StatusManager*);GL 包处理为 void(uint, StatusEffectList*, bool, bool) | GL 委托比非 GL 多一个布尔参数;与旧 .cs 一致,仍未提供可读取的原生签名值或可靠方法体 |
## 方法体读取限制
本次选择目标半径、YMove、位移屏蔽、状态处理及状态结构中的 21 个方法:18 个读取方法体抛错,3 个得到明显可疑的 IL/长度。例:YMove.SafeAreaCheckPlus 被读为仅 3 字节,起始为缺少入栈操作的 ldelem.i1;StatusCheck.Dispose 的声明代码长度被读为 1,038,335,658 字节。模块初始化器含混淆标识调用。
这些现象与方法体保护或混淆相符,但尚未确定具体保护方案,亦不能仅由此排除文件损坏。不能将这些结果当作已成功反编译出的逻辑。尤其不能声称该 DLL 已证明 14 的真实半径公式、16461 的落点计算,或 9 的 UI 应用方式。
## 状态结构仍存在的矛盾
元数据再次确认旧 .cs 的声明:StatusEffectList.EntryData 在偏移 20,固定缓冲区为 240 字节;StatusEffectListEntry 声明 Size=8、Pack=1,但 SourceID 为偏移 8 的 uint,字段末端达到 12。这属于声明大小和字段范围不一致的证据,不能当作游戏网络布局。
旧 .cs 另外创建 30 项 Span;这个数量来自源码,DLL 的 get_Entries 方法体未成功读取,不能宣称本次已从 DLL 核实。仍须取得当前原生包长度和布局依据后才启用 8。
## 对重建工程的处理
将此文件登记为额外参考,用于后续接口与依赖交叉核对。本次没有基于不可读取的方法体修改运行逻辑,没有替换已部署 0.1.5。14 的当前修正继续等待 16461 游戏内复测;9 保持用户明确要求的“生效/回到 0”交互。
结构化证据保存在 `2026-10-11-original-dll-metadata.json`。可复现命令(工作区根目录):
```powershell
./IC.Rebuild/Tools/ManagedAudit/Audit.ps1 -AssemblyPath './IC/I-Ching-GL.dll' -OutputPath './IC.Rebuild/diagnostics/2026-10-11-original-dll-metadata.json'
```
@@ -0,0 +1,27 @@
# 0.1.5 落点与界面调整
日期:2026-10-11。客户端:国际服 2026.09.15.0000.0000。
## 14 目标半径
用户确认原生圈已扩大,但技能 16461 仍落在原来小圈边缘;期望落在扩大圈外侧。0.1.4 刻意保留突进原始半径的处理不符合该要求。
0.1.5 在帧快照记录选中目标地址和 EntityId,仅当两者一致且对象不是自身时,对原生半径增加一次偏移。圈显示、距离判断和突进路径读取同一目标半径;14 不再叠加技能射程。原生回调继续只读快照,不访问线程限定服务。界面显示原始和有效半径,以及相关调用计数。
离线检查覆盖自身、其他对象、身份不符和无效帧不扩大,以及不同查询上下文的一致性。实际原生调用和最终落点仍需游戏内复测:关闭 13 和 16,单独开启 14,使用 16461 对比原始与扩大后的落点。
## 已确认文案
用户明确确认 1、2、13、15、16、17、19、27、28、29 有效。仅在上述客户端版本将这些功能显示为“已实测有效”;14 为“待复测”,未确认项为“待实测”,没有实现的 8 为“暂不可用”。运行开关和错误状态独立显示。用户反馈不代表所有组合、切图和卸载场景已验收。
## 9 手动生效
勾选 9 后,预设值不会自动应用。设置参数再点“生效”才保存本次应用值;再点“回到 0”取消偏移,随后位置同步时反映。修改预设不改变当前应用值;关闭或重载清零应用值但保留预设。应用值只存在于会话内,使用线程安全读取,不写配置。依赖 10 的迷宫条件仍可将当前实际偏移限制为 0。
## Timeline 折叠
16 的整个名单管理默认折叠;其中技能名称名单和手动编号各有独立折叠,避免展开战斗页时出现全部编号。
## 验证
Release 构建通过,0 警告、0 错误;45 项离线测试通过。新增文案和高度应用状态测试通过;不在离线测试中执行原生游戏 Hook。14 修正与 9 新交互仍待用户热重载后实测。
@@ -0,0 +1,38 @@
# 14 原生目标圈与距离修复
版本:0.1.4。客户端:国际服 2026.09.15.0000.0000。
用户确认两个问题:画面目标圈没有变大,技能距离也没有增加;并明确要求修改游戏原生圈,不接受额外叠加圈。
## 距离路径
0.1.2—0.1.3 只在 GetActionInRangeOrLoS 中临时增加目标半径,漏掉 IsActionTargetInRange 的前置路径。
本机原生 IsActionTargetInRange 位于 RVA 0x8EE490,在 0x8EE51E 调用 GetActionRange,然后将结果与 ActionManager 内的缓存距离比较。因此仅影响最终半径读取,不能覆盖前置距离判断。
0.1.4 在 IsActionTargetInRange 与 GetActionInRangeOrLoS 两个检查范围内,对普通技能的有效距离补上编号 14 的增量,数学上相当于增加目标判定半径。作用域按线程隔离;未知技能、位移技能、负数及零范围不补偿。不直接改写缓存距离或物理半径。
13 和 14 共用一个 GetActionRange Hook,分别计算自己的增量,避免两个独立 Hook 互相覆盖。共享资源按引用计数释放;关闭任意一个模块不停止另一个,释放失败时禁止再次挂接。
## 原生圈路径
从本机可执行文件中的 gl_target 资源路径向使用方追踪:
- vfx/common/eff/gl_target1.avfx 和 gl_target2.avfx 是目标圈资源。
- 资源路径表起点 RVA 0x28A3640,gl_target1 位于第 105 项。
- 对应资源句柄表起点 RVA 0x2A8F5B0。
- 资源选择函数 RVA 0x3938A0,被原生圈更新函数调用。
- 原生圈更新函数通过 unwind 链确认完整入口为 RVA 0x7B5430;签名在本机唯一匹配。
- 0x7B5829 通过对象虚表的 GetRadius 槽读取半径,并且 adjustByTransformation=false,用于后续圈尺寸计算。
0.1.4 仅在此原生圈更新函数的同步调用范围内增加显示半径,并排除本地角色。其他线程、突进、碰撞及范围外读取仍返回原值。没有绘制 ImGui 叠加圈,没有修改游戏资源文件或永久写入对象半径。
原生圈更新 Hook 按本次审计版本限制启用。关闭模块后停止半径补偿,下一次游戏原生更新读取原始半径。
## 诊断与验证
面板显示前置检查、最终检查、距离补偿、原生圈更新、绘制半径补偿五项计数,以区分入口未触发与已触发但实际效果不符。
Release 构建通过,0 警告、0 错误;40 项离线测试通过。覆盖两条距离作用域、位移排除、原生圈作用域、跨线程隔离、异常退出恢复、13 和 14 的共享生命周期及清理失败处理。
静态反汇编和离线测试不代替游戏内验收。待复测:关闭 13 和 16,单开 14,增量设为 1;观察原生目标圈与普通近战技能距离,再确认关闭后恢复以及猛攻落点不受影响。不要只用猛攻验证普通技能的距离增量,14 明确排除位移技能的距离补偿。
@@ -0,0 +1,43 @@
# 0.1.12:编号 8 的转换后状态更新过滤
国际服客户端 2026.09.15.0000.0000;只读检查本机游戏文件,SHA256 为 `5BBC501DD5C7F22FD61A11D08C25356041D878DB7CD83203ADAE393E4DFACC44`。沿用当前 API 15 SDK。未调用运行中游戏的原生函数,效果仍待实测。
## 本次交付
编号 8 现在有可测试实现:在 StatusManager.SetStatus 入口,将本地角色后续收到的已选状态替换为空条目,原函数恰好调用一次,并保留其返回值和 refreshFlags。默认仅选 1257(Forced March),名单可逐项选取已审计的 38 个候选;空名单完全放行。界面提供本次启用的拦截次数与最近状态 ID。
不解析或改写原始网络载荷,不依赖 36、37,不直接清空客户端状态数组。首次启用前已有状态须等待下一次 SetStatus 更新。关闭后正常接收后续更新,不把旧状态写回已经变化的角色。服务器状态和机制判定不因此被删除。
## 原生入口与调用依据
| 路径 | 当前 RVA 与核对结果 |
| --- | --- |
| 状态 ID 转换 | PacketDispatcher 0x18D97FC 分支复制消息并按 12 字节条目减去会话相关值;最终处理发生在转换之后。沿用 0.1.11 的分派依据,不在捕获文件上猜测还原 ID |
| 普通列表 | 0xB385F0 → 0xB37F90 → 0x8A78F0;业务载荷 +0x14,30 个 12 字节条目 |
| 玩家专用单列表 | 0xB37D70 从全局本地角色取 StatusManager,再调用 0x8A78F0 |
| 双列表 | 0xB38A20 先以 r9b=1 调用公共前缀处理,跳过单列表写入,再将两块交给 0x8A7980;玩家专用入口 0xB37DD0 也调用 0x8A7980 |
| 特殊区域列表 | 0xB38600、0xB38760 将载荷 +4 交给 0xB37F90,附加区域字段仍由原生函数处理 |
| 批量写入 | 0x8A78F0 写槽位 0—29;0x8A7980 写 0—29 和 30—59。两者逐项调用 0x8A6BF0,并 OR 返回的变化标记,最后按需调用 0x8A9AD0 |
| 公共 setter | 0x8A6BF0,参数为 manager、int index、ushort id、float remaining、ushort param、64 位 source、byte refreshFlags;返回 byte 变化标记。SDK 的 SetStatus 委托与此一致(bool 以原生 byte 表达) |
| 状态变化与标志 | setter 对比旧 ID/source,更新条目,调用 0x8A1C20 的失去状态路径及 0x89FCB0 的获得状态路径;refreshFlags 非零时调用 0x8A9AD0。批量调用传 0,在批末统一刷新 |
| 标志刷新 | 0x8A9AD0 清零 +0x3C8 的七字节标志,按 +0x3D8 的有效范围和 16 字节状态项重算;另更新 +0x3D9 的部分位。其余状态通知继续由 setter 原函数执行 |
setter 的第 6 参数是完整 64 位 GameObjectId,不能截成网络列表的 uint32 来源字段。第 4 参数使用浮点 ABI。被屏蔽条目传入 id=0、remaining=0、param=0、source=0,保留槽位及 refreshFlags;不跳过 setter,以免旧槽位残留和批末标志不更新。
调用者中还有动作效果及其他入口。本版不宣称覆盖所有直接复制状态数组的路径;仅保证通过这个已核对 setter 的更新适用。回放分组会选择不同角色/管理器,另外通过 DutyRecorderPlayback 帧标记和条件变化事件暂停整个过滤,不改写回放记录。回放、特殊区域和首次角色载入仍需现场验收。
## 本地对象与生命周期
- Framework.Update 发布本地角色地址、EntityId、StatusManager 地址和回放标记;原生回调不读取 ObjectTable 或其他线程绑定服务。
- SDK 元数据确认 BattleChara.StatusManager=0x23B0、GameObject.EntityId=0x78。游戏 getter 0xAFF9E0/0xAFF9F0 返回角色 +0x23B0。启用时检查 SDK 字段偏移,客户端版本不符拒绝启用。
- 本地角色加载签名唯一匹配 0xB37D7A,RIP 引用全局地址 0x142AA0410。只对选中的本地候选更新,通过 SafeMemory 再读当前全局角色指针和实体 ID,与帧快照同时匹配。绝不依赖可能为空的 manager.Owner。
- setter 签名唯一匹配 0x8A6BF0。模块启用清空旧快照;切区、注销与进入回放清空快照;无登录角色或切区期间不发布有效快照。原有半秒过期规则继续生效,指针复用但实体不同会放行。
- Hook 和三个事件订阅都纳入现有 ResourceScope,启动失败、关闭和卸载释放。不保存状态内存副本,不在停用时写回。
## 验证与待验收
Release 构建通过,0 警告、0 错误;70 项离线测试通过。新增四组验证覆盖:当前身份/指针复用/过期与清空/回放,双列表槽位边界和不可变名单,空条目替换及原生返回/标志保留,放行时所有参数保真及异常时只调用一次。已有生命周期测试继续覆盖启动回滚和重复启停。没有用离线代理调用冒充原生 Hook 验收。
首轮游戏检查只聚焦一个状态:重新加载后进入编号 8,保留默认 1257,开启后再触发对应的 Forced March。观察最近状态 ID、拦截次数及实际强制移动表现;关闭后再次触发同一状态应恢复正常。若当前场景使用另一个 ID,在折叠名单中仅选该已审计 ID再测试。开启前已有状态不作立即消除预期。
仍待确认:目标状态效果、未选状态和其他角色正常、关闭后后续同步、切区/回放/卸载。先取得首个目标效果反馈,再扩展逐项状态验收。无需为本版泛化重抓网络样本。
@@ -0,0 +1,94 @@
# 两份 I-Ching-GL DLL 对比分析
日期:2026-10-11。范围:用户提供的两份 DLL 的静态文件、程序集元数据、接口与关键方法体可读性。原件未修改,目标程序集未执行,插件运行代码及已部署 0.1.5 未改动。
## 身份和构建差异
| 项目 | I-Ching-GL.dll(第一份) | I-Ching-GL (2).dll(第二份) |
| --- | --- | --- |
| 大小 | 5,811,712 字节 | 7,894,528 字节 |
| 程序集 / 文件版本 | 0.1.6.6 | 0.1.6.6 |
| InformationalVersion | 0.1.6.6+6e402483b7b629bdd57821bb9f4eb9f08701de0e | 相同 |
| 目标 | .NET 10,AMD64 DLL | 相同 |
| Dalamud 引用 | 15.0.3.6 | 15.0.3.6 |
| FFXIVClientStructs 引用 | 7.56.2.9458 | 7.56.2.9418 |
| ECommons 引用 | 3.2.1.17 | 3.2.1.17 |
| MVID | 36234178-ce88-4985-a78c-d2148d83f493 | bdcb5604-0284-4e0f-b9c9-fcaa9694c9c8 |
| 顶层类型数 | 1,933 | 2,724 |
| 含嵌套类型数 | 2,024 | 2,833 |
| 全 ASCII 名称类型数 | 152 | 200 |
第一份 SHA256:`DA648072A2CE0856B4884A332EFAC063FC8F0E03236D7D4DBC9334BF0B2A2AA8`。
第二份 SHA256:`CE269139FDFDB136BE382E10BE78E6E0BC346DEB335E9D99DF2E80097BD76CBF`。
结论:不是重复文件,也不是仅改了文件名。尽管版本与构建标识相同,依赖及声明有实际差异。不能仅用文件更大、复制时间或共享版本号判断新旧顺序和修复情况。本机当前 FFXIVClientStructs 为 7.56.2.9136,与两份引用版本均不同。
## 已确认的声明差异
递归比较两份全 ASCII 名称类型的基类、接口、字段(含偏移/标志)、方法签名及声明标志,不比较不可读的方法实现。
第二份独有的命名类型包括:
- `NekoVerifierLib`:NekoVerifierMain、Service、VerifyWindow、VerifyClient、PlayerData 及协议类型等。
- `OtpNet`:HOTP/TOTP、密钥和时间校正相关类型。
- `RSAsharp`:RSA_PEM、RSA_Util。
- `DataSender` 和额外编译器生成类型。
第二份额外引用了 System.Net.Http、System.Security.Cryptography、System.Runtime.Numerics、System.Linq.Expressions、System.Text.Encoding.Extensions、Microsoft.Win32.Registry;第一份引用集合未包含这些程序集。
共有类型中可见差异只有四处:
1. `SamplePlugin.Plugin`:第二份多了静态 `PVPWhiteList` 字段及静态构造器。
2. `SamplePlugin.Windows.ConfigWindow`:第二份多了 `ExecuteBoardMarketInternal(string,string)` 方法声明。
3. ConfigWindow 的编译器生成类型:DrawCommandGenerator 相关成员编号由 77 变为 78。
4. PrivateImplementationDetails:第二份多了一项长度为 15 的静态数据声明。
命名表明第二份包含额外验证/密码相关组件及少量插件入口差异;仅凭声明不能确定其运行时是否被调用、传送什么数据、PVPWhiteList 的内容或作用,亦不能确定是原作者不同打包还是其他来源处理。类型数增加不等于增加同等数量的游戏功能。
## 重点功能对照
| 功能 | 两份 DLL 的可核实结果 | 对重建的意义 |
| --- | --- | --- |
| 14 目标半径 | ActorRadiusHook 的字段、方法、委托声明一致,Detour 为 float(ulong,byte) | 没有可读取的新落点公式,不能判断哪份修复了 16461 |
| 9 高度偏移 | YMove、两条移动委托、层数相关声明一致 | 无法从这两份确认偏移索引或调用后恢复行为;保持已要求的按钮交互 |
| 16 突进无位移 | 两份均保留旧五参数委托声明 | 不能替代当前已实测的六参数共用入口 |
| 8 状态处理 | StatusCheck、普通/GL 委托、结构布局声明一致 | 第二份未补出可读取的签名值或网络长度依据 |
| 其他 Hook 与配置 | 两份 SamplePlugin.Hook 类型(含嵌套声明)及 Configuration 没有上述元数据差异 | 声明相同不代表函数体相同,不足以回退已验证功能 |
两份都保留状态结构的旧声明矛盾:EntryData 偏移 20、固定 240 字节;条目声明 Size=8,但偏移 8 的 uint 字段占到 12 字节。它是插件声明,不是当前游戏包布局的可靠证明。8 继续保持未适配。
## 方法体可读性与独立检查
在相同的 21 个重点方法中:第一份 18 个读取错误、3 个明显可疑;第二份 19 个读取错误、2 个明显可疑。第二份曾有一个 CombineOffsets 方法被 Cecil 形式上解析成功,但 castclass、stsfld 和分支等指令缺少必须的操作数,不能作为有效 IL。审计脚本已增加缺失操作数检查。
另使用 .NET 自带 System.Reflection.Metadata/PEReader 独立读取方法头,避免仅凭 Cecil 报错下结论:
| 方法 | 第一份 | 第二份 |
| --- | --- | --- |
| SendNormalMoveDetour | Invalid method header: 0xD1 | Invalid method header: 0x55 |
| SendCombatMoveDetour | Invalid method header: 0xA1 | Invalid method header: 0xF1 |
| ActorRadiusDetour | 方法头可形式上解析为 20 字节,但 Cecil 无法解析其 IL | 方法头可形式上解析为 45 字节,但 Cecil 无法解析其 IL |
两份都存在大量非 ASCII 混淆名称、异常关键方法体以及相同业务名称但链接到不同随机程序集名的资源。整体表现与方法体保护/混淆一致;未确定具体保护方案,未证明每个异常的原因,也不能仅由此排除损坏。未将形式上能读到的随机 IL 当作有效算法,未执行初始化器。
## 当前能用与不能用的内容
可用:对照接口形状、结构声明、依赖版本、存在的功能类型和不同打包的差异。
尚不可用:还原 14 的半径/落点公式、确认 9 的具体写入顺序、取得 8 的可用原生签名和网络包边界、判断验证组件的真实运行行为。第二份没有解除这些限制。
本次以分析为止,当前 0.1.5 的运行逻辑与部署不变。14 的实际落点仍应以 16461 的现场复测为准。
## 证据文件与复现
- `2026-10-11-original-dll-metadata.json`:第一份重点接口及读取结果。
- `2026-10-11-original-dll-2-metadata.json`:第二份相同范围。
- `2026-10-11-two-dll-comparison.json`:两份程序集信息、可读类型完整声明和差异。
在工作区根目录执行:
```powershell
./IC.Rebuild/Tools/ManagedAudit/Audit.ps1 -AssemblyPath './IC/I-Ching-GL (2).dll' -OutputPath './IC.Rebuild/diagnostics/2026-10-11-original-dll-2-metadata.json'
./IC.Rebuild/Tools/ManagedAudit/Compare.ps1 -FirstPath './IC/I-Ching-GL.dll' -SecondPath './IC/I-Ching-GL (2).dll' -OutputPath './IC.Rebuild/diagnostics/2026-10-11-two-dll-comparison.json'
```
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,456 @@
{
"Source": "capture-018.jsonl",
"SHA256": "224AE627F6F6E613662745300C01493E411BDBE02CBA72366CCBD373DD28ECFF",
"MapSHA256": "2764186EA528587F15D07569816D413E77E8C38C572E4157787B3092BD6D1DB6",
"MapSource": "local cache \u002B \u672C\u673A\u6838\u5B9E 7 \u9879",
"Version": "2026.09.15.0000.0000",
"Records": 891,
"Up": 534,
"Down": 357,
"ManagerReplay": {
"Matches": true,
"Records": 891,
"SendReturns": 534,
"ObserverErrors": 0,
"ReadErrors": 0
},
"FirstTime": "2026-10-11T10:12:32.1453158+00:00",
"LastTime": "2026-10-11T10:13:52.6616441+00:00",
"FirstSequence": 1,
"LastSequence": 891,
"SequenceContinuous": true,
"MonotonicOrder": true,
"Complete": 891,
"Incomplete": 0,
"CaptureIssues": 0,
"PayloadBytes": 56360,
"MinPayload": 8,
"MaxPayload": 656,
"EmptyPayloads": 0,
"Known": 891,
"Unknown": 0,
"Parsed": 891,
"SupportedButRejected": 0,
"Groups": [
{
"Key": {
"Direction": 0,
"Opcode": 920,
"Name": "UP_UpdatePositionHandler",
"Length": 24,
"PayloadComplete": true,
"Parsed": true
},
"Count": 494,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 787,
"Name": "DOWN_Effect",
"Length": 124,
"PayloadComplete": true,
"Parsed": true
},
"Count": 52,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 671,
"Name": "DOWN_UpdateHate",
"Length": 72,
"PayloadComplete": true,
"Parsed": true
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 697,
"Name": "DOWN_EffectResultBasic",
"Length": 24,
"PayloadComplete": true,
"Parsed": true
},
"Count": 51,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 558,
"Name": "DOWN_UpdateHater",
"Length": 264,
"PayloadComplete": true,
"Parsed": true
},
"Count": 50,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 516,
"Name": "DOWN_ActorControlSelf",
"Length": 40,
"PayloadComplete": true,
"Parsed": true
},
"Count": 48,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 238,
"Name": "DOWN_ObjectSpawn",
"Length": 64,
"PayloadComplete": true,
"Parsed": true
},
"Count": 38,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 913,
"Name": "UP_ActionSend",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 27,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 524,
"Name": "DOWN_NpcSpawn",
"Length": 656,
"PayloadComplete": true,
"Parsed": true
},
"Count": 18,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 974,
"Name": "DOWN_ActorDelete",
"Length": 8,
"PayloadComplete": true,
"Parsed": true
},
"Count": 12,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 614,
"Name": "DOWN_JobGauge",
"Length": 16,
"PayloadComplete": true,
"Parsed": true
},
"Count": 10,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 838,
"Name": "UP_PingReq",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 8,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 338,
"Name": "DOWN_PingRsp",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 8,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 607,
"Name": "DOWN_ActorControl",
"Length": 24,
"PayloadComplete": true,
"Parsed": true
},
"Count": 7,
"Rejection": null
},
{
"Key": {
"Direction": 0,
"Opcode": 391,
"Name": "UP_ClientTrigger",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 5,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 131,
"Name": "DOWN_StatusEffectList",
"Length": 384,
"PayloadComplete": true,
"Parsed": true
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 788,
"Name": "DOWN_UpdateClassInfo",
"Length": 16,
"PayloadComplete": true,
"Parsed": true
},
"Count": 4,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 305,
"Name": "DOWN_EffectResult",
"Length": 96,
"PayloadComplete": true,
"Parsed": true
},
"Count": 2,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 214,
"Name": "DOWN_FirstAttack",
"Length": 16,
"PayloadComplete": true,
"Parsed": true
},
"Count": 1,
"Rejection": null
},
{
"Key": {
"Direction": 1,
"Opcode": 856,
"Name": "DOWN_ActorControlTarget",
"Length": 32,
"PayloadComplete": true,
"Parsed": true
},
"Count": 1,
"Rejection": null
}
],
"PingPairs": [
{
"Request": 3,
"Response": 4,
"Milliseconds": 83.2735
},
{
"Request": 54,
"Response": 56,
"Milliseconds": 99.9771
},
{
"Request": 222,
"Response": 224,
"Milliseconds": 116.8623
},
{
"Request": 372,
"Response": 374,
"Milliseconds": 83.4204
},
{
"Request": 530,
"Response": 532,
"Milliseconds": 83.4215
},
{
"Request": 683,
"Response": 684,
"Milliseconds": 83.2034
},
{
"Request": 807,
"Response": 808,
"Milliseconds": 100
},
{
"Request": 870,
"Response": 871,
"Milliseconds": 83.2435
}
],
"ActionPairs": [
{
"Request": 31,
"Response": 36,
"Milliseconds": 166.3058
},
{
"Request": 70,
"Response": 73,
"Milliseconds": 150.0712
},
{
"Request": 117,
"Response": 120,
"Milliseconds": 150.333
},
{
"Request": 151,
"Response": 155,
"Milliseconds": 133.0785
},
{
"Request": 164,
"Response": 168,
"Milliseconds": 116.7569
},
{
"Request": 179,
"Response": 182,
"Milliseconds": 116.3995
},
{
"Request": 198,
"Response": 202,
"Milliseconds": 150.0261
},
{
"Request": 206,
"Response": 214,
"Milliseconds": 266.8726
},
{
"Request": 221,
"Response": 227,
"Milliseconds": 216.5409
},
{
"Request": 249,
"Response": 253,
"Milliseconds": 116.6774
},
{
"Request": 282,
"Response": 287,
"Milliseconds": 166.5952
},
{
"Request": 317,
"Response": 323,
"Milliseconds": 166.5913
},
{
"Request": 357,
"Response": 360,
"Milliseconds": 166.6749
},
{
"Request": 394,
"Response": 398,
"Milliseconds": 151.2212
},
{
"Request": 450,
"Response": 453,
"Milliseconds": 117.414
},
{
"Request": 490,
"Response": 493,
"Milliseconds": 117.0401
},
{
"Request": 523,
"Response": 526,
"Milliseconds": 116.5287
},
{
"Request": 565,
"Response": 568,
"Milliseconds": 135.5363
},
{
"Request": 619,
"Response": 621,
"Milliseconds": 100.0991
},
{
"Request": 655,
"Response": 657,
"Milliseconds": 99.9365
},
{
"Request": 713,
"Response": 716,
"Milliseconds": 117.0038
},
{
"Request": 724,
"Response": 728,
"Milliseconds": 83.3655
},
{
"Request": 763,
"Response": 765,
"Milliseconds": 116.5066
},
{
"Request": 795,
"Response": 798,
"Milliseconds": 133.1891
},
{
"Request": 812,
"Response": 814,
"Milliseconds": 117.6021
},
{
"Request": 819,
"Response": 822,
"Milliseconds": 99.5427
},
{
"Request": 823,
"Response": 826,
"Milliseconds": 166.6213
}
],
"Limitations": "No raw payload, coordinates or actor IDs included. Successful parsing does not verify all fields. Header-read failures absent from export require UI counters."
}
+66
View File
@@ -0,0 +1,66 @@
# 2026-10-12 阶段 2(0.1.14)协议补全、事件包分层与动作回包关联审计报告
- 审计日期:2026-10-12
- 目标二进制:`E:\SteamLibrary\steamapps\common\FINAL FANTASY XIV Online\game\ffxiv_dx11.exe`
- 客户端版本:`2026.09.15.0000.0000`
- 二进制 SHA256:`5BBC501DD5C7F22FD61A11D08C25356041D878DB7CD83203ADAE393E4DFACC44`
- 样本文件:`capture-018.jsonl`(SHA256 `407B6933E0886AA567C7A585B2732BA8064DC5B731987EB3744F14F4296AF639`,891 条完整记录)
- 映射缓存:`opcodes.json`(SHA256 `6B40585D43CC83C31EC16A8DD9CF2B3008D3084752472BD5E89B4D20C6C14F7E`)
- 离线回放报告:`diagnostics/2026-10-12-capture-018-v0114.json`
## 1. 上行构造与发送包装层核实
### 1.1 原生发送结构体与包装函数(为阶段 3 M4 预备证据)
- `ZoneClient.SendPacket`:`0x1D03040`(内部转调 `ZoneUp` `0x1D718C0`)。
- `NetworkModuleProxy` 发送包装层:`0x1CFD090`、`0x1CFD140`(由 `0x4810E0` 调用)、`0x1CFD170`(由 `0x481100` 调用)、`0x1CFD1A0`(由 `0x4810C0` 调用)。
- 原生发送结构体(`rdx`):`+0x00 uint Opcode`、`+0x08 ulong TotalSizeWithHeader`(等于 `payloadLength + 0x10`)、`+0x20 byte[] Payload`。
### 1.2 `UP_ActionSend`(`913` / `0x391`,载荷 32 字节)與 `UP_ActionSendPos`(`891` / `0x37B`,载荷 24 字节)
- 构造调用链:`0x8E21A3` → `0xB36F50`(`UP_ActionSend`,总长 `0x30` = 载荷 `0x20`);`0x8E2255` → `0xB37050`(`UP_ActionSendPos`,总长 `0x28` = 载荷 `0x18`,旧版 `UpPacketStructs.cs` 记为 `0x20` 已过期)。
- 共用头部(`+0x00..+0x0B`):
- `+0x00 uint ActionId`
- `+0x04 byte CastBuff`
- `+0x05 byte ActionKind`
- `+0x06 ushort RequestId`(样本 27 条递增为 `179..205`)
- `+0x08 ushort Facing`
- `+0x0A ushort TargetFacing`
- `UP_ActionSend` 尾部:`+0x10 ulong TargetId`、`+0x18 uint Arg`(共 32B)。
- `UP_ActionSendPos` 尾部:`+0x0C float X`、`+0x10 float Y`、`+0x14 float Z`(共 24B,校验有限浮点数)。
### 1.3 `UP_ClientTrigger`(`391` / `0x187`,载荷 32 字节)
- 构造器:`0xB352F0`、`0xB353B0`、`0xB35550`(总长 `0x30` = 载荷 `0x20`)。
- 载荷布局:`+0x00 uint CommandId`、`+0x04..+0x10 uint Arg0..Arg3`、`+0x18 ulong TargetId`。
### 1.4 P2 变长事件包冲突解决(`UP_EventFinish*` 与 `UP_EventAction*`)
- 旧版 `UpPacketStructs.cs` 将 `UP_EventFinish` 与 `UP_EventAction` 写成单一固定长度结构,与在线 `opcodes.json` 的变长后缀表冲突。
- 原生反汇编确认客户端按 `ArgCount`(`r9b`)分成 8 档固定长度 Opcode 发送:
- `UP_EventFinish*`(`0xB32C5C..0xB33022`):`UP_EventFinish`(`982`,`cap=2`,16B)、`4`(`607`,24B)、`8`(`516`,40B)、`16`(`856`,72B)、`32`(`283`,136B)、`64`(`787`,264B)、`128`(`779`,520B)、`255`(`658`,1032B,含 4B 对齐尾填充)。
- `UP_EventAction*`(`0xB33050..0xB333DA`):`UP_EventAction`(`140`,`cap=2`,16B)、`4`(`778`,24B)、`8`(`938`,40B)、`16`(`957`,72B)、`32`(`637`,136B)、`64`(`988`,264B)、`128`(`703`,520B)、`255`(`705`,1032B)。
- 共用 8 字节头部:`+0x00 uint EventId`、`+0x04 ushort SceneId`、`+0x06 byte State`、`+0x07 byte ArgCount`(校验 `ArgCount <= capacity`),`+0x08` 起为 `uint Args[capacity]`。
## 2. 下行 `PacketDispatcher`(`0x18D9500`,跳表 `0x18DD980`)核实
| 名称 | Opcode | 长度 | 跳表入口与消费函数 | 已核实字段与旧版差异 |
| --- | --- | --- | --- | --- |
| `DOWN_ActorControl` | `607` (`0x25F`) | 24B (`0x18`) | 预处理 `0x18DA1EC`;跳表 `0x18DAABB` → `0x18DAB03` → `0xB3A350` | `+0x00 ushort Category`,`+0x04..+0x10 uint Arg0..Arg3`。当 `Category == 0x22` 时,采集发生在 `0x18DA1EC` 减去会话值 `esi` 之前 |
| `DOWN_ActorControlSelf` | `516` (`0x204`) | 40B (`0x28`) | 跳表 `0x18DAB9E` → `0x18DABE6` → `0xB3A350` | `+0x00 ushort Category`,`+0x04..+0x20 uint Arg0..Arg7`(旧版 32B 仅 6 个参数,现为 8 个 `uint`) |
| `DOWN_ActorControlTarget` | `856` (`0x358`) | 32B (`0x20`) | 跳表 `0x18DAB4D` → `0x18DAB95` → `0xB3A350` | `+0x00 ushort Category`,`+0x04..+0x10 uint Arg0..Arg3`,`+0x18 ulong TargetId` |
| `DOWN_Effect` | `787` (`0x313`) | 124B (`0x7C`) | 预处理 `0x18DA4CC`;跳表 `0x18DA9C6` → `0xB3A0F0` → `0x902C20` | 旧版 120B 已变为 124B。`+0x08 uint RawActionId`(采集时含会话偏移 `esi`),`+0x0C uint Sequence`,`+0x10 float LockTime`(有限数),`+0x18 ushort RequestId`,`+0x1C ushort AnimationId`,`+0x1F byte ActionKind`,`+0x21 byte TargetCount`(`<=1`),`+0x70 ulong TargetId` |
| `DOWN_EffectResult` | `305` (`0x131`) | 96B (`0x60`) | 跳表 `0x18DAF52` → `0xB38CA0` → `0x8A6BF0` | `+0x00 byte Count`(`<=1`),`+0x04 uint Sequence`,`+0x0C uint CurrentHp`,`+0x10 uint MaxHp`,`+0x14 ushort Mp`,`+0x16 byte TargetIndex`,`+0x17 byte ClassJob`,`+0x18 byte Shield`,`+0x19 byte StatusCount`(`<=4`),`+0x1C` 起 4×16B 状态项(内部调用 `StatusManager.SetStatus` `0x8A6BF0`) |
| `DOWN_StatusEffectList` | `131` (`0x83`) | 384B (`0x180`) | 预处理 `0x18D97FC`;跳表 `0x18DAE4B` → `0xB385F0` → `0x8A78F0` | `+0x00 byte ClassJob`,`+0x01 byte Level`,`+0x04 uint CurrentHp`,`+0x08 uint MaxHp`,`+0x0C ushort Resource`,`+0x0E ushort MaxResource`,`+0x10 byte Shield`,`+0x14` 起 30×12B 状态槽(采集时 `+0x00 ushort RawStatusId` 尚未减去 `si`,`+0x04 float Timer` 校验有限数) |
| `DOWN_ActorDelete` | `974` (`0x3CE`) | 8B (`0x08`) | 跳表 `0x18DA75C` → `0xB37C00` | `+0x00 byte ObjectIndex` |
| `DOWN_ObjectSpawn` | `238` (`0xEE`) | 64B (`0x40`) | 跳表 `0x18DAD80` → `0xB4ADA0` (`0xB4B057`) | `+0x00 byte ObjectIndex`,`+0x01 byte Kind`,`+0x04 uint BaseId`,`+0x08 uint EntityId`,`+0x1C float Scale`,`+0x34 float X, +0x38 float Y, +0x3C float Z`(旧版坐标偏移 `0x30` 错误) |
| `DOWN_NpcSpawn` | `524` (`0x20C`) | 656B (`0x290`) | 跳表 `0x18DA6FA` → `0xB37A10` → `0x8CF750`(`rsi = payload + 0x10`) | `+0x40 uint BaseId`,`+0x54 uint OwnerId`,`+0x5C uint MaxHp`,`+0x60 uint CurrentHp`(旧版 HP 颠倒且 OwnerId 偏移错),`+0x7E byte ObjectIndex`,`+0x81 byte ObjectKind`,`+0x82 byte SubKind`,`+0x86 byte Level`,`+0x87 byte ClassJob`,`+0x200 float X, +0x204 float Y, +0x208 float Z` |
## 3. 动作发包与下行效果关联(`PacketCorrelator.Actions`)
- 关联依据:`UP_ActionSend`(32B)与 `UP_ActionSendPos`(24B)在 `+0x06` 写入递增非零 `ushort RequestId`;服务端返回的本地动作确认 `DOWN_Effect`(124B)在 `+0x18` 回传同一 `ushort RequestId`(其他角色/NPC 的 `DOWN_Effect` 该字段为 `0`)。
- 样本验证:`capture-018.jsonl` 中 27 条 `UP_ActionSend`(`RequestId = 179..205`)与 27 条 `DOWN_Effect`(`RequestId = 179..205`)100% 一一配对,往返耗时 `68.5 ms .. 138.3 ms`。
## 4. `capture-018.jsonl` 回放复核结果
- `Records = 891`(上行 `534`,下行 `357`)
- `Complete = 891`,`Known = 891`
- `Parsed = 891`(由 `0.1.13` 的 `679` 提升至 `891`,覆盖率 100%)
- `SupportedButRejected = 0`
- `PingPairs = 8`,`ActionPairs = 27`
+60
View File
@@ -0,0 +1,60 @@
# 阶段 3(0.1.15)M0 版本适配诊断与 M4 主动发送事务审计记录
日期:2026 年 10 月 12 日
客户端版本:国际服 `2026.09.15.0000.0000`
目标二进制:`ffxiv_dx11.exe`(SHA256 `5BBC501DD5C7F22FD61A11D08C25356041D878DB7CD83203ADAE393E4DFACC44`)
## 1. M0 统一版本适配清单与门控(`Core/AdaptationManifest.cs`)
针对全部 24 项保留功能及 M4 主动发送通道建立统一适配清单,按模块记录版本锁、SDK 偏移要求、原生签名及 RVA 证据:
| 诊断分类 (`AdaptationIssue`) | 判定条件 | 门控行为 (`AdaptationManifest.ApplyGate`) |
| --- | --- | --- |
| `None` | 实现存在、版本/偏移与签名全部匹配且未发生运行异常 | 清除不可用门控,允许启用 |
| `MissingImplementation` | 模块尚未注册实现 | 保持不可用,拒绝启用 |
| `VersionMismatch` | `VersionLocked == true` 的模块(`2, 7, 8, 14, 16, 36` 及 M4 主动发送)在非 `2026.09.15.0000.0000` 客户端运行 | 自动关闭并标记不可用;非版本锁定模块(如 `1, 3, 9, 10, 11, 37`)与离线导入/导出不受影响 |
| `OffsetMismatch` | `RequiresSdkOffsets == true`(模块 `8`:依赖 `Character.StatusManager` `0x23B0` 与 `GameObject.EntityId` `0x78`)偏移不匹配 | 仅门控对应模块,不影响其他模块 |
| `SignatureMissing` | 任一必需签名在当前客户端匹配数为 `0` | 自动关闭并标记不可用,显示缺失签名名称与已核对 RVA |
| `MultipleMatches` | `RequireUnique == true` 的签名在 `.text` 段出现 `>1` 处匹配 | 拒绝盲挂,标记不可用并显示匹配数量(模块 `15` `0x8D6F30` 显式声明 `RequireUnique = false` 使用首匹配包装函数) |
| `RuntimeFault` | 运行期捕获异常并标记为 `ModuleState.Failed` | 保留具体异常详情并显示在 M0 诊断面板 |
本机 `ffxiv_dx11.exe` 签名扫描核验:21 条唯一签名(`RequireUnique = true`)在 `.text` 段均精确匹配 `1` 处;模块 `15` 包装签名匹配首处 `0x8D6F30`。
## 2. M4 原生主动发送链路反汇编核实
### 2.1 为什么不沿用旧 `IC/NetManager.cs` 的 `0x4810E0` 包装函数
反汇编 `0x4810E0`(旧签名 `48 8B 49 08 48 85 C9 74 08 45 33 C9`):
- `0x4810E0`: `mov rcx, [rcx+8]`(从 `NetworkModuleProxy*` `+0x08` 读取 `ReceiverCallback*`)
- `0x4810E4`: `test rcx, rcx; jz 0x4810F1`
- `0x4810E9`: `xor r9d, r9d; xor r8d, r8d; call 0x1CFD140`
- `0x4810F1`: `mov al, 1; add rsp, 28h; ret`
**缺陷**:`0x4810E0` 在调用 `0x1CFD140` 后无条件执行 `mov al, 1`,即使 `ReceiverCallback*` 为空或底层 `ZoneUp` 返回 `0`(断线/未就绪),也会恒定返回 `1`,把发送失败伪装成成功。
### 2.2 已核实的原生发送链(保留真实返回值)
1. `Framework.Instance()->NetworkModuleProxy`(偏移 `+0x1678`,对应原生 getter `0xD28F0`)。
2. `ReceiverCallback* = *(nint*)((nint)networkModuleProxy + 0x08)`。
3. `ReceiverSendPacket`(RVA `0x1CFD140`,唯一签名 `48 83 EC 38 48 8B 89 70 0A 00 00 ...`,1 处匹配):
- 读取 `ZoneClient* = *(nint*)(receiver + 0xA70)`;若为空直接 `xor al, al; ret` 返回 `0`。
- 非空时以 `priority = 0` 调用 `ZoneClient.SendPacket`(RVA `0x1D03040`,唯一签名 `48 83 EC 28 48 8B 89 98 00 00 00 ...`,1 处匹配)。
4. `ZoneClient.SendPacket`(`0x1D03040`):
- 检查 `*(nint*)(zoneClient + 0x98) != 0`,调用 `ZoneUp`(`0x1D718C0`),并将 `ZoneUp` 的真实 `byte` 返回码原样返回给调用方。
5. `ZoneUp`(`0x1D718C0`)在 `0x1D7198C` 读取发送缓冲区契约:
- `+0x00`: `uint Opcode`
- `+0x08`: `ulong TotalSize`(`payload.Length + 0x10`,即含 16 字节 IPC 头)
- `+0x20`: `byte[payload.Length]` 业务载荷
- 原生调用方(如 `0xB8A7AA` `UP_EventStart`、`0xB352F0` `UP_ClientTrigger`)均在栈上分配 `0xF60` 字节清零缓冲区传入;`NetworkManager.SendNative` 同样采用至少 `0xF60` 字节的清零固定缓冲区调用 `0x1CFD140`。
### 2.3 为什么不用合成 `UP_PingReq` 做主动发包测试
反汇编 `0x1D02776`(`UP_PingReq` 构造)与 `0x1D022E1`(`DOWN_PingRsp` 消费)证实:客户端在发送 `UP_PingReq` 与接收 `DOWN_PingRsp` 时会直接读写 `NetworkModule` 内部延迟测量状态(`[r14+0BCCh]`、`[r14+0C3Ch]`)。插件在外部合成 `UP_PingReq` 会干扰客户端原生 Ping 状态机。因此 M4 仅提供经过结构审计的业务包编码器(`UP_ActionSend`、`UP_ClientTrigger`、`UP_EventStart`、`UP_EventFinish*` 8 档、`UP_EventAction*` 8 档)。
## 3. M4 主动发送调度与请求响应事务(`Core/ActivePacketSender.cs`)
- **来源标注(`ActiveSendScope`)**:`ActivePacketDispatcher.Pump` 调用原生发送时开启线程本地 `ActiveSendScope`,`NetworkPipeline.Read` 自动将该次 `ZoneUp` 捕获标记为 `PacketOrigin.PluginActiveSend`,与游戏自身触发的 `PacketOrigin.NativeZone` 明确区分。
- **主线程调度与重入防护**:仅在 `Framework.Update` 主线程调用 `PumpActiveSends`;`NetworkPipeline.InCallback` 与 `inReceiveCallback` 禁止在任何网络回调中递归调用 `Pump`。
- **有界队列、限速与会话绑定**:默认最大排队 `32` 条、最小发送间隔 `100 ms`、排队超时 `2000 ms`、响应超时 `5000 ms`。每次入队与发送均核对 `SendSession`(角色在场、非切区、非占卜回放、`Territory`、`LocalAddress`、`LocalEntityId` 一致);切区或会话变更自动取消未完成请求。
- **显式事务状态机**:区分 `Queued`、`SentNative`、`RejectedNative`、`Confirmed`、`TimedOut`、`Canceled`。`Cancel` 仅能取消仍处于 `Queued` 的请求,绝不把取消排队伪装成撤回已发送原生包。
- **请求响应关联**:`UP_ActionSend` 自动等待同 `RequestId` 的 `DOWN_Effect`(`0x313`),`UP_EventStart` / `UP_EventFinish*` 支持等待同 `EventId` 的 `DOWN_EventStart` / `DOWN_EventFinish`,并在收到响应时计算真实往返耗时 `RoundTripMs`。
@@ -0,0 +1,64 @@
# 国服客户端兼容性与反汇编审计记录(涵盖 2026.09.15 与 2026.10.06)
- **日期**:2026 年 10 月 13 日
- **国服游戏路径**:`D:\FINAL FANTASY XIV`
- **国服更新后版本**:`2026.10.06.0000.0000`
- **国服更新后二进制**:`D:\FINAL FANTASY XIV\game\ffxiv_dx11.exe`(51,910,400 字节,SHA256 `958B78E278AD896493C484EB313FF605AB41EDEFEF74F92B0EE078E69B281BF9`)
- **国服更新前基线备份**:[`binaries/2026.09.15.0000.0000-cn/ffxiv_dx11.exe`](file:///e:/SapphireServer/Dalamud%20Dev/IC.Rebuild/binaries/2026.09.15.0000.0000-cn/ffxiv_dx11.exe)(51,881,216 字节,SHA256 `7BA28760BC53CBBBF66B63105FEA6C1BFE09CB6B1C6353FC8FB0FF03CC1A30F4`)
- **国服启动器**:`XIVLauncherCN`(位于 `C:\Users\AinaSnow\AppData\Roaming\XIVLauncherCN`)
---
## 1. 国服更新前后 23 处特征码全量扫描对照
在更新后的国服二进制上执行扫描,**23/23 处特征码全部匹配成功**(22 处单一匹配,1 处 `NoBackswing` 包装入口匹配 2 处且首匹配正确):
| 序号 | 目标名称 | 模块 ID | 国服更新前 RVA (2026.09.15 CN) | 国服更新后 RVA (2026.10.06 CN) | 国际服新版 RVA (2026.10.06 Global) | 匹配数 | 状态 |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| 1 | `SpeedHook` | 1 | `0x8D5060` | `0x8D61A0` | `0x8D6AF0` | 1 | 匹配 |
| 2 | `AccelerationHook` | 2 | `0x1827FC0` | `0x1829480` | `0x182BB40` | 1 | 匹配 |
| 3 | `MovePermissionHook` | 3 | `0xE12940` | `0xE13F70` | `0xE16030` | 1 | 匹配 |
| 4 | `AntiKnockHook` | 4 | `0x909EB0` | `0x90AEB0` | `0x90B650` | 1 | 匹配 |
| 5 | `OnSendFlagHook` | 5 | `0x62A250` | `0x62B350` | `0x62B050` | 1 | 匹配 |
| 6 | `FallCheckHook` | 6 | `0x182BE84` | `0x182D344` | `0x182FA04` | 1 | 匹配 |
| 7 | `ForcedWalkHook` | 7 | `0x1947573` | `0x1948A83` | `0x194AFE3` | 1 | 匹配 |
| 8 | `StatusSetter` | 8 | `0x8A4E10` | `0x8A5F50` | `0x8A6A30` | 1 | 匹配 |
| 9 | `LocalPlayerPtr` | 8 | `0xB34FBA` | `0xB3660A` | `0xB37D0A` | 1 | 匹配 |
| 10 | `OnSendNormalMove` | 9 | `0x62A970` | `0x62BA70` | `0x62B770` | 1 | 匹配 |
| 11 | `OnSendCombatMove` | 9 | `0x62AA20` | `0x62BB20` | `0x62B820` | 1 | 匹配 |
| 12 | `ActorRadius` | 14 | `0x175360F` | `0x1754CDF` | `0x175720F` | 1 | 匹配 |
| 13 | `NativeTargetRingUpdate` | 14 | `0x7B43E0` | `0x7B54F0` | `0x7B52D0` | 1 | 匹配 |
| 14 | `NoBackswing` | 15 | `0x8D5150` | `0x8D6290` | `0x8D6BE0` | 2 (首匹配有效) | 匹配 |
| 15 | `ActionMovementStart` | 16 | `0x181E9B0` | `0x181FE70` | `0x1822530` | 1 | 匹配 |
| 16 | `SyncRecast` | 17 | `0x8ED480` | `0x8EE480` | `0x8EEC20` | 1 | 匹配 |
| 17 | `CastStaticAddress` | 19 | `0x1054C7` | `0x1054D7` | `0x104FF7` | 1 | 匹配 |
| 18 | `CastUpdate` | 19 | `0x8DE2C0` | `0x8DF400` | `0x8DFA60` | 1 | 匹配 |
| 19 | `SetScale` | 29 | `0x897940` | `0x898A80` | `0x899560` | 1 | 匹配 |
| 20 | `ZoneUp` | 36 | `0x1D6DAD0` | `0x1D706B0` | `0x1D72B00` | 1 | 匹配 |
| 21 | `ZoneDown` | 36 | `0x1D6D650` | `0x1D70230` | `0x1D72680` | 1 | 匹配 |
| 22 | `ReceiverSendPacket` | M4 | `0x1CF9020` | `0x1CFA9B0` | `0x1CFD120` | 1 | 匹配 |
| 23 | `ZoneClientSendPacket` | M4 | `0x1CFEF30` | `0x1D008B0` | `0x1D03020` | 1 | 匹配 |
---
## 2. 更新后关键原生反汇编核实
1. **M4 主动发送通道**:
- `ReceiverSendPacket`(`0x1CFA9B0`):`mov rcx, [rcx+0A70h]` 读取 `ZoneClient`,若空则返回 `0`;非空以 `priority=0` 调用 `ZoneClientSendPacket`(`0x1D008B0`)。
- `ZoneClientSendPacket`(`0x1D008B0`):`mov rcx, [rcx+98h]` 检查底层指针,调用 `ZoneUp`(`0x1D706B0`),保留真实返回码。
- `ZoneUp`(`0x1D706B0`):发送缓冲区契约(`+0x00 Opcode`、`+0x08 TotalSize`、`+0x20 Payload`)与旧版完全一致。
2. **模块 36 收包**:
- `ZoneDown`(`0x1D70230`):`cmp qword ptr [rcx+88h], 0`,消息解包偏移完全一致。
3. **模块 8 状态屏蔽**:
- `StatusSetter`(`0x8A5F50`):`cmp edx, 3Ch`(60 个状态栏槽位),槽位大小依然为 12 字节。
- `LocalPlayerPtr`(`0xB3660A`):虚表偏移 `+0x278`(`call qword ptr [rax+278h]`)完全一致。
4. **模块 2 最大加速度**:
- `AccelerationHook`(`0x1829480`):`cmp byte ptr [rcx+3Ch], 0`、`mov rdi, [rcx+20h]` 完全一致。
---
## 3. 国服环境与 Opcode
1. **客户端版本**:更新后 `ffxivgame.ver` 变为 `2026.10.06.0000.0000`,与代码中 `PacketParser.AuditedClientVersion` 完美吻合,门控全通。
2. **Opcode 配置**:本地 `opcodes.json` 中已含有 `"2026.10.06.0000.0000"`(`UP_PingReq: 137`,`DOWN_PingRsp: 338`),Ping 与收发包分析立即就绪。
3. **开发插件加载**:`XIVLauncherCN` 的 `dalamudConfig.json` 中已注册 `ICRebuild.dll`。
@@ -0,0 +1,89 @@
# 客户端更新补丁 2026.10.06 完整适配与反汇编审计记录
- **日期**:2026 年 10 月 13 日
- **新客户端版本**:国际服 `2026.10.06.0000.0000`
- **新目标二进制**:`ffxiv_dx11.exe`(51,890,944 字节,SHA256 `B38840761E2677128B6BEC1CEAEE3F2870CD84E1D38AB7958216373058383780`)
- **旧客户端基线**:国际服 `2026.09.15.0000.0000`(51,878,744 字节,SHA256 `5BBC501DD5C7F22FD61A11D08C25356041D878DB7CD83203ADAE393E4DFACC44`)
- **旧二进制备份路径**:[`binaries/2026.09.15.0000.0000/ffxiv_dx11.exe`](file:///e:/SapphireServer/Dalamud%20Dev/IC.Rebuild/binaries/2026.09.15.0000.0000/)
---
## 1. 原生二进制签名全量扫描对比
在新版二进制 `ffxiv_dx11.exe`(`2026.10.06.0000.0000`)上对所有 23 处特征码进行完整静态扫描,**23/23 处特征码全部在新二进制中唯一定位成功**(其中 22 处为单一匹配,1 处 `NoBackswing` 包装入口匹配 2 处且首匹配正确)。
在扫描过程中,修正了 [`AdaptationManifest.cs`](file:///e:/SapphireServer/Dalamud%20Dev/IC.Rebuild/Core/AdaptationManifest.cs) 中 `ForcedWalkHook` 的签名字符串笔误(`????` 修正为标准的 `?? ??` 分隔通配符),成功定位到新 RVA `0x194AFE3`。
### 23 处 Hook 与函数入口 RVA 偏移位移对照表
| 序号 | 目标名称 | 模块 ID | 旧版本 RVA (2026.09.15) | 新版本 RVA (2026.10.06) | RVA 偏移量 | 匹配数 | 状态 |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| 1 | `SpeedHook` | 1 | `0x8D6E40` | `0x8D6AF0` | -0x350 | 1 | 匹配 |
| 2 | `AccelerationHook` | 2 | `0x182BB20` | `0x182BB40` | +0x20 | 1 | 匹配 |
| 3 | `MovePermissionHook` | 3 | `0xE16130` | `0xE16030` | -0x100 | 1 | 匹配 |
| 4 | `AntiKnockHook` | 4 | `0x90BC90` | `0x90B650` | -0x640 | 1 | 匹配 |
| 5 | `OnSendFlagHook` | 5 | `0x62AF60` | `0x62B050` | +0xF0 | 1 | 匹配 |
| 6 | `FallCheckHook` | 6 | `0x182F9E4` | `0x182FA04` | +0x20 | 1 | 匹配 |
| 7 | `ForcedWalkHook` | 7 | `0x194AEC3` | `0x194AFE3` | +0x120 | 1 | 匹配 |
| 8 | `StatusSetter` | 8 | `0x8A6BF0` | `0x8A6A30` | -0x1C0 | 1 | 匹配 |
| 9 | `LocalPlayerPtr` | 8 | `0xB37D7A` | `0xB37D0A` | -0x70 | 1 | 匹配 |
| 10 | `OnSendNormalMove` | 9 | `0x62B680` | `0x62B770` | +0xF0 | 1 | 匹配 |
| 11 | `OnSendCombatMove` | 9 | `0x62B730` | `0x62B820` | +0xF0 | 1 | 匹配 |
| 12 | `ActorRadius` | 14 | `0x175728F` | `0x175720F` | -0x80 | 1 | 匹配 |
| 13 | `NativeTargetRingUpdate` | 14 | `0x7B5430` | `0x7B52D0` | -0x160 | 1 | 匹配 |
| 14 | `NoBackswing` | 15 | `0x8D6F30` | `0x8D6BE0` | -0x350 | 2 (首匹配有效) | 匹配 |
| 15 | `ActionMovementStart` | 16 | `0x1822510` | `0x1822530` | +0x20 | 1 | 匹配 |
| 16 | `SyncRecast` | 17 | `0x8EF260` | `0x8EEC20` | -0x640 | 1 | 匹配 |
| 17 | `CastStaticAddress` | 19 | `0x104F17` | `0x104FF7` | +0xE0 | 1 | 匹配 |
| 18 | `CastUpdate` | 19 | `0x8E00A0` | `0x8DFA60` | -0x640 | 1 | 匹配 |
| 19 | `SetScale` | 29 | `0x899720` | `0x899560` | -0x1C0 | 1 | 匹配 |
| 20 | `ZoneUp` | 36 | `0x1D718C0` | `0x1D72B00` | +0x1240 | 1 | 匹配 |
| 21 | `ZoneDown` | 36 | `0x1D71440` | `0x1D72680` | +0x1240 | 1 | 匹配 |
| 22 | `ReceiverSendPacket` | M4 | `0x1CFD140` | `0x1CFD120` | -0x20 | 1 | 匹配 |
| 23 | `ZoneClientSendPacket` | M4 | `0x1D03040` | `0x1D03020` | -0x20 | 1 | 匹配 |
---
## 2. 核心原生入口反汇编与结构偏移核实
对关键功能的原生反汇编指令和内存结构进行逐一反编译核验:
1. **M4 主动发包通道结构不变**:
- `ReceiverSendPacket`(`0x1CFD120`):依然检查 `*(nint*)(rcx + 0xA70)`(`ZoneClient` 指针),为空则直接返回 `0`;非空则调用 `ZoneClientSendPacket`。
- `ZoneClientSendPacket`(`0x1D03020`):依然检查 `*(nint*)(rcx + 0x98)`,调用底层网络发送函数 `ZoneUp`(`0x1D72B00`)。
- `ZoneUp`(`0x1D72B00`):发送数据缓冲区协议完全未变(`+0x00`: Opcode, `+0x08`: TotalSize, `+0x20`: Payload)。
2. **模块 36 原始收发包 Hook 结构不变**:
- `ZoneDown`(`0x1D72680`):检查 `*(nint*)(rcx + 0x88)`,下行载荷解包偏移完全一致。
3. **模块 8 状态屏蔽结构不变**:
- `StatusSetter`(`0x8A6A30`):汇编代码仍为 `83 FA 3C`(`cmp edx, 3Ch` 即 60 个状态栏槽位),槽位大小依然为 12 字节。
- `LocalPlayerPtr`(`0xB37D0A`):依然调用虚函数表 `+0x278`(`FF 90 78 02 00 00`),读取本地玩家。
4. **模块 2 最大加速度结构不变**:
- `AccelerationHook`(`0x182BB40`):依然核对偏移 `+0x20`、`+0x3C`、`+0x44` 与 owner `+0x3E0`。
---
## 3. 网络协议与 Opcode 变动核实
SE 在本次 `2026.10.06` 补丁中对 Opcode 编号进行了全量重排:
- `UP_PingReq`:旧版为 `838`(`0x346`),新版更新为 `137`(`0x89`)。
- `DOWN_PingRsp`:依然为 `338`(`0x152`)。
- 由于模块 36 属于通用二进制载荷抓取,无需等待所有 Opcode 逆向即可正常捕获和导出所有数据包。
- `XIVLauncher` 本地配置 `opcodes.json` 已追加 `2026.10.06.0000.0000` 节点,Ping 对齐功能可立即正常显示。
---
## 4. 双版本向后兼容设计(Dual-Version Support)
为确保过渡平滑与回滚安全,代码更新为支持双审计版本:
- 当前审计版本(`AuditedClientVersion`):`2026.10.06.0000.0000`
- 兼容基线版本(`BaselineClientVersion`):`2026.09.15.0000.0000`
- `IsAuditedVersion(v)` 同时认可两者,未在审计名单中的未知版本(如 `2026.99.99`)继续受 M0 严格门控保护。
---
## 5. 自动化验证与部署
1. **测试套件**:84/84 项单元测试全部一次性通过(涵盖双版本适配清单核验、门控行为、网络管线、M4 原生缓冲区分组、状态阻断等)。
2. **发布与备份**:
- 旧版本 `0.1.15` 已备份至 [`deploy-backups/0.1.15-before-0.1.16/`](file:///e:/SapphireServer/Dalamud%20Dev/IC.Rebuild/deploy-backups/0.1.15-before-0.1.16/)。
- 新版本 `0.1.16.0` 已部署至 `%APPDATA%\XIVLauncher\dev\ICRebuild`。
@@ -0,0 +1,90 @@
[
{
"ActionId": 2259,
"Name": "Ten",
"Timeline": 233,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": false
},
{
"ActionId": 2261,
"Name": "Chi",
"Timeline": 234,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": false
},
{
"ActionId": 2262,
"Name": "Shukuchi",
"Timeline": 231,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 2263,
"Name": "Jin",
"Timeline": 235,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": false
},
{
"ActionId": 3573,
"Name": "Ley Lines",
"Timeline": 3972,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": false
},
{
"ActionId": 18805,
"Name": "Ten",
"Timeline": 233,
"PvP": false,
"PlayerAction": false,
"AffectsPosition": false
},
{
"ActionId": 18806,
"Name": "Chi",
"Timeline": 234,
"PvP": false,
"PlayerAction": false,
"AffectsPosition": false
},
{
"ActionId": 18807,
"Name": "Jin",
"Timeline": 235,
"PvP": false,
"PlayerAction": false,
"AffectsPosition": false
},
{
"ActionId": 29066,
"Name": "Guardian",
"Timeline": 11501,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29513,
"Name": "Shukuchi",
"Timeline": 231,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 34675,
"Name": "Starry Muse",
"Timeline": 11786,
"PvP": false,
"PlayerAction": false,
"AffectsPosition": false
}
]
@@ -0,0 +1,126 @@
MATCH RVA=0x8E9980
PREFIX 48895C24104C894C242048894C240855565741544155415641574883EC608BEA0F29742450488BD9418BD08BCD418BF8E87B5DFFFF4C8B3D546A1B02448BE04D
00000001408E9980 mov [rsp+10h],rbx
00000001408E9985 mov [rsp+20h],r9
00000001408E998A mov [rsp+8],rcx
00000001408E998F push rbp
00000001408E9990 push rsi
00000001408E9991 push rdi
00000001408E9992 push r12
00000001408E9994 push r13
00000001408E9996 push r14
00000001408E9998 push r15
00000001408E999A sub rsp,60h
00000001408E999E mov ebp,edx
00000001408E99A0 movaps [rsp+50h],xmm6
00000001408E99A5 mov rbx,rcx
00000001408E99A8 mov edx,r8d
00000001408E99AB mov ecx,ebp
00000001408E99AD mov edi,r8d
00000001408E99B0 call 00000001408DF730h
00000001408E99B5 mov r15,[142AA0410h]
00000001408E99BC mov r12d,eax
00000001408E99BF test r15,r15
00000001408E99C2 je 00000001408E9B26h
00000001408E99C8 mov r14,[rsp+0D0h]
00000001408E99D0 xor esi,esi
00000001408E99D2 mov ecx,r12d
00000001408E99D5 call 0000000140834590h
00000001408E99DA mov r13,rax
00000001408E99DD test rax,rax
00000001408E99E0 je 00000001408E9B26h
00000001408E99E6 cmp ebp,5
00000001408E99E9 jne short 00000001408E9A1Fh
00000001408E99EB mov ecx,edi
00000001408E99ED call 0000000140834A90h
00000001408E99F2 mov [rsp+48h],rax
00000001408E99F7 test rax,rax
00000001408E99FA je 00000001408E9B26h
00000001408E9A00 movzx ecx,word ptr [rax+0Eh]
00000001408E9A04 test cx,cx
00000001408E9A07 je short 00000001408E9A1Fh
00000001408E9A09 mov edx,ecx
00000001408E9A0B lea rcx,[142ACBF20h]
00000001408E9A12 call 0000000140C4DD30h
00000001408E9A17 test al,al
00000001408E9A19 je 00000001408EA9F7h
00000001408E9A1F mov edx,[r13+4]
00000001408E9A23 test edx,edx
00000001408E9A25 je short 00000001408E9A53h
00000001408E9A27 mov rax,[142A98D28h]
00000001408E9A2E test rax,rax
00000001408E9A31 je short 00000001408E9A39h
00000001408E9A33 cmp byte ptr [rax+31h],1Fh
00000001408E9A37 je short 00000001408E9A53h
00000001408E9A39 mov r9b,1
00000001408E9A3C lea rcx,[142ACBF20h]
00000001408E9A43 xor r8d,r8d
00000001408E9A46 call 0000000140C4DD60h
00000001408E9A4B test al,al
00000001408E9A4D je 00000001408EA9F7h
00000001408E9A53 cmp r12d,4
00000001408E9A57 jne short 00000001408E9AB6h
00000001408E9A59 call 0000000140B79630h
00000001408E9A5E mov rcx,rax
00000001408E9A61 call 0000000140B86B80h
00000001408E9A66 test rax,rax
00000001408E9A69 je short 00000001408E9A7Fh
00000001408E9A6B mov rdx,[rax]
00000001408E9A6E mov rcx,rax
00000001408E9A71 call qword ptr [rdx+9A8h]
00000001408E9A77 test eax,eax
00000001408E9A79 jne 00000001408E9B2Bh
00000001408E9A7F call 0000000140B79630h
00000001408E9A84 mov rcx,rax
00000001408E9A87 call 0000000140B86C30h
00000001408E9A8C test rax,rax
00000001408E9A8F je short 00000001408E9AA5h
00000001408E9A91 mov rdx,[rax]
00000001408E9A94 mov rcx,rax
00000001408E9A97 call qword ptr [rdx+0A58h]
00000001408E9A9D test eax,eax
00000001408E9A9F jne 00000001408E9B2Bh
00000001408E9AA5 movzx eax,word ptr [r15+688h]
00000001408E9AAD test ax,ax
00000001408E9AB0 jne 00000001408E9DD5h
00000001408E9AB6 cmp ebp,11h
00000001408E9AB9 je 00000001408EB70Ch
00000001408E9ABF cmp ebp,10h
00000001408E9AC2 je 00000001408EB6E3h
00000001408E9AC8 cmp ebp,5
00000001408E9ACB je short 00000001408E9B48h
00000001408E9ACD cmp ebp,0Fh
00000001408E9AD0 je 00000001408E9E1Eh
00000001408E9AD6 cmp ebp,14h
00000001408E9AD9 jne 00000001408E9B63h
00000001408E9ADF lea rcx,[r15+960h]
00000001408E9AE6 call 00000001408B5310h
00000001408E9AEB test al,al
00000001408E9AED je short 00000001408E9B63h
00000001408E9AEF test r14,r14
00000001408E9AF2 je short 00000001408E9AFBh
00000001408E9AF4 mov dword ptr [r14],0C1h
00000001408E9AFB xor r9d,r9d
00000001408E9AFE lea rcx,[142AE6610h]
00000001408E9B05 xor r8d,r8d
00000001408E9B08 mov edx,0C1h
00000001408E9B0D call 0000000140E16130h
00000001408E9B12 test al,al
00000001408E9B14 je short 00000001408E9B26h
00000001408E9B16 movzx ecx,di
00000001408E9B19 call 0000000140BC4E70h
00000001408E9B1E test al,al
00000001408E9B20 je 00000001408EB729h
00000001408E9B26 mov eax,243h
00000001408E9B2B mov rbx,[rsp+0A8h]
00000001408E9B33 movaps xmm6,[rsp+50h]
00000001408E9B38 add rsp,60h
00000001408E9B3C pop r15
00000001408E9B3E pop r14
00000001408E9B40 pop r13
00000001408E9B42 pop r12
00000001408E9B44 pop rdi
00000001408E9B45 pop rsi
00000001408E9B46 pop rbp
00000001408E9B47 ret
Matches: 1
@@ -0,0 +1,10 @@
{
"File": "capture-20261010-233625-cccab3b9c9bb427893d6effe41c910b7.jsonl",
"Total": 2048,
"Up": 92,
"Down": 1956,
"Matched": 1675,
"FullPayloads": 0,
"First": "2026-10-10T23:45:10.7130834+08:00",
"Last": "2026-10-10T23:47:24.1238529+08:00"
}
+634
View File
@@ -0,0 +1,634 @@
[
{
"ActionId": 94,
"Name": "Elusive Jump",
"Timeline": 406,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 96,
"Name": "Dragonfire Dive",
"Timeline": 408,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 112,
"Name": "Repelling Shot",
"Timeline": 364,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 155,
"Name": "Aetherial Manipulation",
"Timeline": 431,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 2262,
"Name": "Shukuchi",
"Timeline": 231,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 7386,
"Name": "Onslaught",
"Timeline": 5189,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 7419,
"Name": "Between the Lines",
"Timeline": 5238,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 7492,
"Name": "Hissatsu: Gyoten",
"Timeline": 5123,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 7493,
"Name": "Hissatsu: Yaten",
"Timeline": 5124,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 7506,
"Name": "Corps-a-corps",
"Timeline": 5148,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 7515,
"Name": "Displacement",
"Timeline": 5149,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 7571,
"Name": "Rescue",
"Timeline": 5458,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 7857,
"Name": "Hissatsu: Soten",
"Timeline": 5135,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 8765,
"Name": "Onslaught",
"Timeline": 5189,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 8777,
"Name": "Plunge",
"Timeline": 3812,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 8787,
"Name": "Shoulder Tackle",
"Timeline": 394,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 8802,
"Name": "Spineshatter Dive",
"Timeline": 407,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 8812,
"Name": "Shukuchi",
"Timeline": 231,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 8839,
"Name": "Repelling Shot",
"Timeline": 364,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 8869,
"Name": "Aetherial Manipulation",
"Timeline": 431,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 8890,
"Name": "Corps-a-corps",
"Timeline": 5148,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 8891,
"Name": "Displacement",
"Timeline": 5149,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 11389,
"Name": "Flying Frenzy",
"Timeline": 6571,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 11401,
"Name": "Loom",
"Timeline": 6592,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 16010,
"Name": "En Avant",
"Timeline": 7002,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 16461,
"Name": "Intervene",
"Timeline": 7017,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 16480,
"Name": "Stardiver",
"Timeline": 7050,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 17674,
"Name": "Backstep",
"Timeline": 6662,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 17694,
"Name": "Intervene",
"Timeline": 7017,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 17716,
"Name": "Rough Divide",
"Timeline": 6939,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 17728,
"Name": "High Jump",
"Timeline": 7048,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 17729,
"Name": "Stardiver",
"Timeline": 7050,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 17764,
"Name": "En Avant",
"Timeline": 7002,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 18325,
"Name": "J Kick",
"Timeline": 7235,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 24295,
"Name": "Icarus",
"Timeline": 8309,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 24401,
"Name": "Hell\u0027s Ingress",
"Timeline": 8361,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 24402,
"Name": "Hell\u0027s Egress",
"Timeline": 8404,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 25753,
"Name": "Primal Rend",
"Timeline": 8212,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 25762,
"Name": "Thunderclap",
"Timeline": 8213,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 25777,
"Name": "Forked Raiju",
"Timeline": 8257,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 27817,
"Name": "Hell\u0027s Ingress",
"Timeline": 8361,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 27818,
"Name": "Hell\u0027s Egress",
"Timeline": 8404,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 27834,
"Name": "Icarus",
"Timeline": 8309,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29065,
"Name": "Intervene",
"Timeline": 12243,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29066,
"Name": "Guardian",
"Timeline": 11501,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29079,
"Name": "Onslaught",
"Timeline": 12244,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29084,
"Name": "Primal Rend",
"Timeline": 12245,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29092,
"Name": "Plunge",
"Timeline": 12310,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29123,
"Name": "Rough Divide",
"Timeline": 12320,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29229,
"Name": "Seraph Strike",
"Timeline": 12137,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29261,
"Name": "Icarus",
"Timeline": 8309,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29399,
"Name": "Repelling Shot",
"Timeline": 12248,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29430,
"Name": "En Avant",
"Timeline": 7002,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29484,
"Name": "Thunderclap",
"Timeline": 8213,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29485,
"Name": "Meteodrive",
"Timeline": 11518,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29493,
"Name": "High Jump",
"Timeline": 11521,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29513,
"Name": "Shukuchi",
"Timeline": 231,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29515,
"Name": "Seiton Tenchu",
"Timeline": 11526,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29532,
"Name": "Hissatsu: Soten",
"Timeline": 5135,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29537,
"Name": "Zantetsuken",
"Timeline": 11530,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29550,
"Name": "Hell\u0027s Ingress",
"Timeline": 8361,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29660,
"Name": "Aetherial Manipulation",
"Timeline": 431,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29667,
"Name": "Crimson Cyclone",
"Timeline": 12350,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29699,
"Name": "Corps-a-corps",
"Timeline": 12352,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 29700,
"Name": "Displacement",
"Timeline": 12353,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 34646,
"Name": "Slither",
"Timeline": 11740,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 34684,
"Name": "Smudge",
"Timeline": 11793,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 36926,
"Name": "Shadowstride",
"Timeline": 11808,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 36934,
"Name": "Trajectory",
"Timeline": 11820,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 36951,
"Name": "Winged Glide",
"Timeline": 11821,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 37008,
"Name": "Aetherial Shift",
"Timeline": 11880,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 39184,
"Name": "Slither",
"Timeline": 11740,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 39190,
"Name": "World-swallower",
"Timeline": 11921,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 39210,
"Name": "Smudge",
"Timeline": 11793,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 41506,
"Name": "Epicycle",
"Timeline": 12140,
"PvP": true,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 44893,
"Name": "Shield Charge",
"Timeline": 12442,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 44898,
"Name": "Cloud Skim",
"Timeline": 12445,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 44930,
"Name": "Brutal Rage",
"Timeline": 12456,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
},
{
"ActionId": 44931,
"Name": "Hawkish Talons",
"Timeline": 12457,
"PvP": false,
"PlayerAction": true,
"AffectsPosition": true
}
]
File diff suppressed because it is too large Load Diff