Skip to content

Debugging Security Compatibility

雪绫 edited this page Aug 25, 2026 · 4 revisions

调试、安全与兼容性

Mixin 直接修改进程内代码。调试重点是包是否被发现、依赖是否满足、配置是否被读取、目标是否匹配以及 Patch 是否按预期执行。

日志

启动器日志位于:

<LauncherOutput>/PCL/Log/

成功应用时日志会包含:

  • 插件 ID 和程序集。
  • Mixin 配置名和 Mixin 类型。
  • 目标类型和目标方法。
  • 操作种类和注入点。
  • Target 描述符和优先级。
  • 多 Mixin 修改同一方法时的应用顺序。

失败日志应优先检查最内层原因,例如目标类型不存在、重载歧义、注入点匹配数不符、处理器签名不匹配或局部变量捕获失败。

required 与 optional

Mixin 配置级别:

{
  "required": true
}
  • required: true:配置中未被声明为 Optional 的失败会使插件加载失败;运行时回滚该插件程序集已经应用的 Patch,并禁用插件。
  • required: false:配置加载失败只记录警告,继续其他配置和插件。

Mixin 类型级别:

[Mixin("Optional.Target", Optional = true)]
internal static class OptionalMixin
{
}

Optional Mixin 的失败会被隔离,不阻止同一配置中的其他 Mixin。用于可选第三方集成时,应把可选目标拆成独立 Mixin 类型。

匹配约束

为所有指令级注入设置合理约束:

[Inject("Run", At = MixinAt.Invoke, Target = TargetCall,
    Require = 1, Expect = 1, Allow = 1)]
private static void BeforeCall()
{
}
  • Require 防止目标消失后静默失效。
  • Expect 防止目标数量变化后修改错误位置。
  • Allow 防止目标新增重复调用后应用过多次。

如果目标在不同版本中允许出现 01 次,应明确设计 Optional 行为,而不是删除全部约束。

常见失败

日志现象 常见原因 处理
找不到目标类型 名称错误、程序集尚未加载、目标已重命名 使用完整类型名;确认依赖和加载顺序
多个重载 只写了方法名 Name(Type...)ArgumentTypes
只匹配 0 处 Target、Ordinal、Slice 或 Opcode 不再符合 检查实际 IL,缩小但不要猜测定位条件
超过 Allow 新版本新增了相同调用/常量 重新选择 Slice 或 Ordinal
CallbackInfo 类型不匹配 void/返回值类型选择错误 void 用 CallbackInfo,返回值用准确的泛型类型
Local Capture 失败 HEAD、索引越界或类型不匹配 改注入点;校对本地变量表;选择 FailSoft/FailHard
Shadow 失败 成员名、类型或签名变化 更新 Shadow;可选成员声明 Optional=true
Accessor 创建失败 不是接口、缺少 [Mixin] 或成员签名不匹配 修正接口声明和目标实例
前置插件失败 未安装、未启用、版本不符或循环依赖 修正 dependencies 和启用顺序

安全模式

设置环境变量后启动:

$env:PCL_NEX_SAFE_MODE = '1'
& '.\Plain Craft Launcher 2.exe'

安全模式跳过全部第三方 PCLX Mixin,用于排查启动失败或 UI 无法进入。它不是单个插件的调试开关,也不会修复损坏的包。

PCL.Core 兼容性

插件只声明一个版本:构建时引用的 PCL.Core.dll BaseVersion。

{
  "pclCoreVersion": "2026.07.1"
}

BaseVersion 严格为三个数字段:

yyyy.MM.patch

启动器内部维护 MinimumSupportedPclCoreVersion 和当前 BaseVersion。插件作者不要声明最低版本或独立 Mixin API 版本。

判断 状态 行为
小于内部最低支持版本 Core 版本过旧 禁止安装或启用
位于支持范围内 兼容 直接继续
大于当前启动器版本 使用未来 Core 版本 警告并要求用户明确确认
缺失或格式错误 未知 警告并要求用户明确确认

版本比较按年、月、小版本的数值进行,不是字符串比较。启动器没有 VersionCode、UpstreamVersion、suffix 或独立 PCL.Mixin 版本。

当前实现边界

以下限制应在设计阶段考虑:

  • 不支持插件运行时热卸载或热重载。
  • 不支持对开放泛型方法应用 Mixin。
  • 不支持对 ref-return 方法应用边界 Mixin。
  • [Local] 不能在 HEAD 捕获尚未建立的局部变量。
  • Accessor 接口暂不支持泛型接口方法。
  • 指令级定位依赖编译后的 IL,目标版本变化可能要求更新 Ordinal、Slice 或描述符。
  • 直接修改主程序私有类型没有跨版本稳定保证;pclCoreVersion 只表示编译基线,不替代版本测试。

安全清单

  • 只从可信来源安装插件。
  • 对每个发布包计算并校验 SHA-256。
  • 不在插件中下载并执行未经校验的二进制。
  • 不把用户令牌、账户数据或启动参数写入日志。
  • UI 和文件操作失败时保留启动器可恢复路径。
  • 对网络、文件、进程和脚本 Bridge 采用最小权限与明确超时。
  • 在 Windows、Linux、macOS 的 AMD64 和 ARM64 目标上分别测试包含平台代码或原生依赖的包。
  • 为 required 失败、optional 失败、目标漂移和更新回滚建立自动化测试。

Clone this wiki locally