feat: 支持 2026.10.06 协议与强制注入脚本,移除 UI 中的 M0 诊断折叠卡片

This commit is contained in:
2026-10-14 00:11:41 +08:00
parent 16d61f7a5e
commit 8008519d8b
7 changed files with 141 additions and 41 deletions
+21 -3
View File
@@ -3,7 +3,7 @@ namespace ICRebuild.Core;
public static class CurrentProtocolEvidence public static class CurrentProtocolEvidence
{ {
// Only fill missing names/slots; do not rewrite explicit mappings or the cache file. // Only fill missing names/slots; do not rewrite explicit mappings or the cache file.
private static readonly (int Opcode,string Name)[] Downstream = private static readonly (int Opcode,string Name)[] Downstream20260915 =
[ [
(338,"DOWN_PingRsp"), (338,"DOWN_PingRsp"),
(671,"DOWN_UpdateHate"), (671,"DOWN_UpdateHate"),
@@ -14,11 +14,29 @@ public static class CurrentProtocolEvidence
(788,"DOWN_UpdateClassInfo"), (788,"DOWN_UpdateClassInfo"),
(214,"DOWN_FirstAttack") (214,"DOWN_FirstAttack")
]; ];
private static readonly (int Opcode,string Name)[] Downstream20261006 =
[
(338,"DOWN_PingRsp"),
(673,"DOWN_UpdateHate"),
(171,"DOWN_UpdateHater"),
(549,"DOWN_EffectResultBasic"),
(748,"DOWN_JobGauge"),
(592,"DOWN_UpdateClassInfo"),
(374,"DOWN_FirstAttack")
];
public static int AddMissing(string version,Dictionary<int,string> down) public static int AddMissing(string version,Dictionary<int,string> down)
{ {
if(version!=PacketParser.AuditedClientVersion) return 0; var evidence = version switch
{
PacketParser.AuditedClientVersion => Downstream20261006,
PacketParser.BaselineClientVersion => Downstream20260915,
_ => null
};
if(evidence == null) return 0;
var added=0; var added=0;
foreach(var (opcode,name) in Downstream) foreach(var (opcode,name) in evidence)
if(!down.ContainsKey(opcode) && !down.ContainsValue(name)) { down[opcode]=name; added++; } if(!down.ContainsKey(opcode) && !down.ContainsValue(name)) { down[opcode]=name; added++; }
return added; return added;
} }
-32
View File
@@ -179,7 +179,6 @@ public sealed class Plugin : IDalamudPlugin
ImGui.TextWrapped($"IC Rebuild 0.1.16 · {region} · API 15 · 客户端 {gameVersion}"); ImGui.TextWrapped($"IC Rebuild 0.1.16 · {region} · API 15 · 客户端 {gameVersion}");
if(ImGui.Button("关闭全部模块")) { modules.DisableAll(); config.Requested.Clear(); Try(Save); } if(ImGui.Button("关闭全部模块")) { modules.DisableAll(); config.Requested.Clear(); Try(Save); }
ImGui.TextWrapped(notice); ImGui.TextWrapped(notice);
DrawAdaptation();
foreach(var group in Features.All.GroupBy(x=>x.Group)) foreach(var group in Features.All.GroupBy(x=>x.Group))
{ {
if(!ImGui.CollapsingHeader(group.Key)) continue; if(!ImGui.CollapsingHeader(group.Key)) continue;
@@ -233,37 +232,6 @@ public sealed class Plugin : IDalamudPlugin
} }
ImGui.End(); ImGui.End();
} }
private void DrawAdaptation()
{
if(!ImGui.CollapsingHeader("版本适配与诊断 (M0)")) return;
if(ImGui.Button("重新评估适配清单")) Try(()=>
{
adaptationReport=game.EvaluateAdaptation(modules);
AdaptationManifest.ApplyGate(modules,adaptationReport);
});
if(adaptationReport is not {} report)
{
ImGui.TextWrapped("尚未生成适配诊断报告。");
return;
}
ImGui.TextWrapped($"客户端 {report.ClientVersion}(已审计基线 {report.AuditedVersion})· 可用模块 {report.ReadyCount} · 受阻模块 {report.BlockedCount}");
ImGui.TextWrapped(report.ActiveSendSummary);
foreach(var entry in report.Entries)
{
var tag=entry.Issue switch
{
AdaptationIssue.None=>"就绪",
AdaptationIssue.MissingImplementation=>"未实现",
AdaptationIssue.VersionMismatch=>"版本不匹配",
AdaptationIssue.OffsetMismatch=>"SDK 偏移变化",
AdaptationIssue.SignatureMissing=>"签名缺失",
AdaptationIssue.MultipleMatches=>"签名不唯一",
AdaptationIssue.RuntimeFault=>"运行异常",
_=>"受限"
};
ImGui.TextWrapped($"{entry.FeatureId} · {entry.FeatureName}:{tag} · {entry.Summary}");
}
}
private void DrawStatusBlock() private void DrawStatusBlock()
{ {
ImGui.TextWrapped($"已选 {config.BlockedStatuses.Count} 项 · 本次启用拦截 {statusBlock.Blocked} 次 · 最近状态 ID {statusBlock.LastStatus}"); ImGui.TextWrapped($"已选 {config.BlockedStatuses.Count} 项 · 本次启用拦截 {statusBlock.Blocked} 次 · 最近状态 ID {statusBlock.LastStatus}");
+17 -6
View File
@@ -756,10 +756,16 @@ Test("audited protocol additions preserve explicit opcode and name assignments",
{ {
var down=new Dictionary<int,string>{{671,"DOWN_Explicit"},{100,"DOWN_UpdateHater"}}; var down=new Dictionary<int,string>{{671,"DOWN_Explicit"},{100,"DOWN_UpdateHater"}};
Check(CurrentProtocolEvidence.AddMissing("other",down)==0); Check(CurrentProtocolEvidence.AddMissing("other",down)==0);
Check(CurrentProtocolEvidence.AddMissing(PacketParser.AuditedClientVersion,down)==5); Check(CurrentProtocolEvidence.AddMissing(PacketParser.BaselineClientVersion,down)==5);
Check(down[671]=="DOWN_Explicit" && !down.ContainsKey(558)); Check(down[671]=="DOWN_Explicit" && !down.ContainsKey(558));
Check(down[697]=="DOWN_EffectResultBasic" && down[338]=="DOWN_PingRsp"); Check(down[697]=="DOWN_EffectResultBasic" && down[338]=="DOWN_PingRsp");
Check(CurrentProtocolEvidence.AddMissing(PacketParser.AuditedClientVersion,down)==0); Check(CurrentProtocolEvidence.AddMissing(PacketParser.BaselineClientVersion,down)==0);
var downAudited=new Dictionary<int,string>{{673,"DOWN_Explicit"},{100,"DOWN_UpdateHater"}};
Check(CurrentProtocolEvidence.AddMissing(PacketParser.AuditedClientVersion,downAudited)==5);
Check(downAudited[673]=="DOWN_Explicit" && !downAudited.ContainsKey(171));
Check(downAudited[549]=="DOWN_EffectResultBasic" && downAudited[338]=="DOWN_PingRsp");
Check(CurrentProtocolEvidence.AddMissing(PacketParser.AuditedClientVersion,downAudited)==0);
}); });
Test("enmity parsers respect capacities and native byte value stride",()=> Test("enmity parsers respect capacities and native byte value stride",()=>
{ {
@@ -813,10 +819,15 @@ Test("remaining fixed packets decode only proven fields and retain 64-bit tag id
}); });
Test("gauge evidence label preserves explicit ActorGauge mapping",()=> Test("gauge evidence label preserves explicit ActorGauge mapping",()=>
{ {
var map=new Dictionary<int,string>{{8,"DOWN_ActorGauge"}}; var mapBaseline=new Dictionary<int,string>{{8,"DOWN_ActorGauge"}};
CurrentProtocolEvidence.AddMissing(PacketParser.AuditedClientVersion,map); CurrentProtocolEvidence.AddMissing(PacketParser.BaselineClientVersion,mapBaseline);
Check(map[8]=="DOWN_ActorGauge" && map[614]=="DOWN_JobGauge"); Check(mapBaseline[8]=="DOWN_ActorGauge" && mapBaseline[614]=="DOWN_JobGauge");
Check(map[788]=="DOWN_UpdateClassInfo" && map[214]=="DOWN_FirstAttack"); Check(mapBaseline[788]=="DOWN_UpdateClassInfo" && mapBaseline[214]=="DOWN_FirstAttack");
var mapAudited=new Dictionary<int,string>{{8,"DOWN_ActorGauge"}};
CurrentProtocolEvidence.AddMissing(PacketParser.AuditedClientVersion,mapAudited);
Check(mapAudited[8]=="DOWN_ActorGauge" && mapAudited[748]=="DOWN_JobGauge");
Check(mapAudited[592]=="DOWN_UpdateClassInfo" && mapAudited[374]=="DOWN_FirstAttack");
}); });
Test("stage 2 upstream action, trigger and event tier parsers enforce audited sizes and capacities",()=> Test("stage 2 upstream action, trigger and event tier parsers enforce audited sizes and capacities",()=>
{ {
+6
View File
@@ -0,0 +1,6 @@
@echo off
chcp 65001 >nul
title Dalamud 国服强制注入
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0inject-cn.ps1"
echo.
pause
+45
View File
@@ -0,0 +1,45 @@
<#
.SYNOPSIS
在官方 Dalamud 尚未解锁新版本前,向已启动的国服客户端手动注入 Dalamud。
#>
$ErrorActionPreference = 'Stop'
Write-Host "=== FFXIV 国服 Dalamud 强制注入工具 ===" -ForegroundColor Cyan
# 1. 寻找正在运行的 ffxiv_dx11 游戏进程
$processes = Get-Process -Name "ffxiv_dx11" -ErrorAction SilentlyContinue
if (-not $processes) {
Write-Host "[!] 未检测到运行中的 ffxiv_dx11.exe 游戏进程!" -ForegroundColor Yellow
Write-Host " 步骤:" -ForegroundColor Gray
Write-Host " 1. 请先打开 XIVLauncherCN 正常登录并启动国服游戏。" -ForegroundColor Gray
Write-Host " 2. 待游戏进入标题画面或角色选择界面后,再次运行本脚本。" -ForegroundColor Gray
return
}
# 2. 定位 Dalamud.Injector
$injectorPath = Join-Path $env:APPDATA "XIVLauncherCN\addon\Hooks\15.0.3.6\Dalamud.Injector.exe"
if (-not (Test-Path $injectorPath)) {
$injectorPath = Join-Path $env:APPDATA "XIVLauncherCN\addon\Hooks\dev\Dalamud.Injector.exe"
}
if (-not (Test-Path $injectorPath)) {
Write-Host "[X] 未找到 XIVLauncherCN 的 Dalamud.Injector.exe,请确认启动器环境。" -ForegroundColor Red
return
}
Write-Host "[+] 找到 Dalamud 注入器: $injectorPath" -ForegroundColor Green
foreach ($proc in $processes) {
Write-Host "[*] 正在向游戏进程 PID: $($proc.Id) ($($proc.ProcessName)) 注入 Dalamud..." -ForegroundColor Cyan
& $injectorPath inject $proc.Id
$exitCode = $LASTEXITCODE
if ($exitCode -eq 0) {
Write-Host "[+] 注入指令执行成功 (ExitCode 0)!" -ForegroundColor Green
Write-Host " 请切回游戏窗口:" -ForegroundColor Yellow
Write-Host " - Dalamud 将自动初始化并加载 Dev 插件 [IC.Rebuild 0.1.16.0]" -ForegroundColor Gray
Write-Host " - 在聊天框输入 /icr 可打开 IC.Rebuild 面板" -ForegroundColor Gray
} else {
Write-Host "[!] 注入器返回退出码 $exitCode,如提示权限不足,请右键选择『以管理员身份运行』本脚本。" -ForegroundColor Red
}
}
+6
View File
@@ -0,0 +1,6 @@
@echo off
chcp 65001 >nul
title Dalamud 国际服强制注入
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0inject-global.ps1"
echo.
pause
+46
View File
@@ -0,0 +1,46 @@
<#
.SYNOPSIS
在官方 Dalamud 尚未解锁新版本前,向已启动的国际服客户端手动注入 Dalamud。
#>
$ErrorActionPreference = 'Stop'
Write-Host "=== FFXIV 国际服 Dalamud 强制注入工具 ===" -ForegroundColor Cyan
# 1. 寻找正在运行的 ffxiv_dx11 游戏进程
$processes = Get-Process -Name "ffxiv_dx11" -ErrorAction SilentlyContinue
if (-not $processes) {
Write-Host "[!] 未检测到运行中的 ffxiv_dx11.exe 游戏进程!" -ForegroundColor Yellow
Write-Host " 步骤:" -ForegroundColor Gray
Write-Host " 1. 请先打开 XIVLauncher 正常登录并启动国际服游戏(即使提示插件已锁定也不影响启动客户端)。" -ForegroundColor Gray
Write-Host " 2. 待游戏进入标题画面或角色选择界面后,再次运行本脚本。" -ForegroundColor Gray
return
}
# 2. 定位 Dalamud.Injector
$injectorPath = Join-Path $env:APPDATA "XIVLauncher\addon\Hooks\15.0.3.6\Dalamud.Injector.exe"
if (-not (Test-Path $injectorPath)) {
$injectorPath = Join-Path $env:APPDATA "XIVLauncher\addon\Hooks\dev\Dalamud.Injector.exe"
}
if (-not (Test-Path $injectorPath)) {
Write-Host "[X] 未找到 Dalamud.Injector.exe,请确认 XIVLauncher 已正确下载 Dalamud 环境。" -ForegroundColor Red
return
}
Write-Host "[+] 找到 Dalamud 注入器: $injectorPath" -ForegroundColor Green
foreach ($proc in $processes) {
Write-Host "[*] 正在向游戏进程 PID: $($proc.Id) ($($proc.ProcessName)) 注入 Dalamud..." -ForegroundColor Cyan
& $injectorPath inject $proc.Id
$exitCode = $LASTEXITCODE
if ($exitCode -eq 0) {
Write-Host "[+] 注入指令执行成功 (ExitCode 0)!" -ForegroundColor Green
Write-Host " 请切回游戏窗口:" -ForegroundColor Yellow
Write-Host " - Dalamud 将自动初始化并加载 Dev 插件 [IC.Rebuild 0.1.16.0]" -ForegroundColor Gray
Write-Host " - 在聊天框输入 /icr 可打开 IC.Rebuild 面板" -ForegroundColor Gray
Write-Host " - 检查 M0 状态(23/23 关键特征码均已 100% 匹配)" -ForegroundColor Gray
} else {
Write-Host "[!] 注入器返回退出码 $exitCode,如提示权限不足,请右键选择『以管理员身份运行』本脚本。" -ForegroundColor Red
}
}