You are viewing a potentially older version of this package. View all versions.
cat_yummi-YummiHarness-0.2.3 icon

YummiHarness

Safe patch injection for DSP mods: patch only if the game method is unchanged. | 戴森球计划安全注入前置:目标方法与原版一致才打补丁

Date uploaded 9 hours ago
Version 0.2.3
Download link cat_yummi-YummiHarness-0.2.3.zip
Downloads 128
Dependency string cat_yummi-YummiHarness-0.2.3

This mod requires the following mods to function

xiaoye97-BepInEx-5.4.17 icon
xiaoye97-BepInEx

BepInEx5.4.17 mod plugin framework, Mod框架

Preferred version: 5.4.17

README

YummiHarness

https://github.com/cat-yummi-dspmod/DSP-YummiHarness

English

A "safe injection" prerequisite mod + CLI for Dyson Sphere Program. A patch is applied only if its target method's IL is identical to vanilla. A failed patch only skips itself, and every problem is shown in one main-menu dialog with details in the log.

What it does

  • Fingerprint check: the target method's IL is normalized and hashed. After a game update, any change to the method makes the matching patch skip itself; the rest of the mod keeps working.
  • Failure recording: a failed patch records the mod and shows "xxx: some patches failed, see the log" in the main menu. Return false from PatchOptions.OnFailure to opt out (recording is the default).
  • Conflict registry: Harness.RegisterConflict(...); when the other mod is present it shares the same dialog as patch failures.
  • Custom compatibility advisories: Harness.RegisterCompatibilityAdvisory(...) shows a main-menu notice when every listed plugin GUID is loaded (e.g. "Mod A and Mod B work poorly together for feature X; may cause Y"). Optional detail goes to the log. Unlike conflicts, nothing is auto-disabled.
  • Notice levels: Error / Warning / Info; Harness.Report(...) for custom notices. Config General/DialogLevel controls the main-menu dialog (None, ErrorOnly default, WarningAndError, All). Everything is always logged.
  • Shared-target warning: warns when several mods patch the same game method (including mods that do not use this one). The later mod can decide in PatchOptions.OnShared whether to still apply; Harness.DeclareCompatible(a, b) silences known-safe pairs.
  • Language: dialog and detailed log use the game language. When a patch runs the game language is usually not loaded yet, so that single log line falls back to the OS language.

Config schema (cfg format version)

BepInEx never removes renamed or moved keys. Before your other Config.Bind calls:

var mig = Harness.ApplyConfigSchema(Config, currentVersion: 2, new ConfigSchemaOptions
{
    WipeIfBelow = 2, // stored [_ConfigSchema] Version < 2 → wipe all keys (except Version) then re-bind defaults
    Upgrade = ctx =>
    {
        if (ctx.FromVersion < 2)
        {
            ctx.MigrateKey<int>("Slots", "AutoStellarSlots", "SlotsChange", "AutoStellarSlots");
            ctx.Remove("Slots", "PageSize");
        }
    }
});
// ... Config.Bind ...
ctx?.ApplyTransferred("SlotsChange", "AutoStellarSlots", autoStellarEntry);

[_ConfigSchema] Version in the cfg is the format version, not the mod assembly version.

After all Config.Bind calls, drop keys BepInEx would otherwise keep forever:

Harness.PruneConfigKeys(config, entry1.Definition, entry2.Definition,
    new ConfigDefinition(Harness.ConfigSchemaSection, Harness.ConfigSchemaVersionKey));

For mod authors

[BepInDependency("com.yummi.dsp.yummiharness")]
...
Harness.RegisterConflict("MyMod", "other.guid", "OtherMod");
Harness.RegisterCompatibilityAdvisory(
    "MyMod",
    new[] { "com.other.mod.guid" },
    summaryZh: "MyMod 与 OtherMod 在物流统计上兼容性较差,可能出现产量显示异常",
    summaryEn: "MyMod and OtherMod may disagree on logistics stats; production UI can look wrong",
    detailZh: "建议关闭 OtherMod 的统计增强或只保留一个 mod 的 GameTick 逻辑。",
    detailEn: "Disable the other mod's stat tweak or keep only one GameTick-related feature.",
    advisoryId: "MyMod.WithOtherMod.Stats");
Harness.PatchAll(harmony, typeof(MyPatches), new PatchOptions { ModName = "MyMod" });

// write patches as usual, add [Guard]
[HarmonyPostfix]
[HarmonyPatch(typeof(StationComponent), nameof(StationComponent.AddItem))]
[YummiHarness.Guard("806f415ada529868")]
public static void AddItem_Postfix(...) { }

How to get fingerprints (you do not need to be the mod author)

You need the .NET SDK and the unstripped vanilla Assembly-CSharp.dll from the game folder (the NuGet GameLibs package has empty method bodies and cannot be used).

# 1. See which methods any mod patches and their fingerprints
.\tools\get-fingerprint.ps1 -Mod "C:\path\SomeMod.dll"

# 2. Fingerprint and normalized IL of one game method
.\tools\get-fingerprint.ps1 -Method "StationComponent::AddItem"

# 3. After a game update, diff one method between two versions
.\tools\get-fingerprint.ps1 -Method "StationComponent::AddItem" -OldGame "D:\old\Dyson Sphere Program"

The script finds the Steam install automatically (or use -Game / env var DSP_GAME_DIR) and builds the CLI on first use. In the output:

  • [OK] matches [Guard]; [已变化] (changed) the target was modified by a game update; [找不到] (not found) the method was removed or its signature changed; [无Guard] (no Guard) the patch has no fingerprint, and a paste-ready [Guard("...")] is printed at the end of the line.
  • Exit code is 1 when a patch changed or is missing, so it can be used in a build script.

Without the script: harness scan <Mod.dll> <game folder>, harness dump <game folder> <Type::Method>, harness diff <old game folder> <new game folder> <Type::Method>.

Build

dotnet build plugin -c Release -o bin     # YummiHarness.dll
dotnet build cli -c Release -o bin        # harness.exe

Limitations

  • The fingerprint covers only the target method itself, not the methods it calls.
  • At runtime the game's IL is read through the Mono.Cecil that ships with BepInEx.
中文

戴森球计划的"安全注入"前置 mod + 命令行工具。 补丁只在目标方法与原版 IL 完全一致时才会应用;失败只跳过这一个补丁;所有问题在主菜单一次性弹窗,详情写入日志。

它做什么

  • 指纹校验:对目标方法的 IL 做规范化后哈希。游戏更新后方法有任何变化,对应补丁自动跳过,不影响 mod 的其他功能。
  • 失败记录:patch 失败时记录该 mod,并在主菜单弹窗:"xxx 部分 patch 失败,详情请看日志"。可通过 PatchOptions.OnFailure 返回 false 关闭记录(默认记录)。
  • 互斥登记:Harness.RegisterConflict(...),对方存在时和 patch 失败合并在同一个弹窗。
  • 自定义兼容性告警:Harness.RegisterCompatibilityAdvisory(...),当指定的几个 mod 都已加载时,在主菜单弹窗提示(例如「A 与 B 在某功能上兼容性较差,可能引发 xxx」);详情可写进日志。与互斥不同:不强制停用 mod。
  • 提示分级:Error / Warning / Info;Harness.Report(...) 登记自定义提示。配置 General/DialogLevel 控制主菜单弹窗(None、ErrorOnly 默认、WarningAndError、All)。日志始终全部记录。
  • 同函数警告:多个 mod 修改同一个游戏函数时给出警告(含没用本 mod 的 mod)。后打补丁的一方可用 PatchOptions.OnShared 决定自己是否仍然应用;Harness.DeclareCompatible(a, b) 可对已知安全的组合静音。
  • 语言:弹窗和详细日志使用游戏语言。补丁发生的那一刻游戏语言通常还没加载,那一行日志退回系统语言。

配置格式版本(cfg)

BepInEx 不会自动删掉改名/换段的旧键。在其它 Config.Bind 之前调用 Harness.ApplyConfigSchema:写入 [_ConfigSchema] Version;WipeIfBelow 表示版本过旧则整表重建;Upgrade 里可 MigrateKey / Remove,Bind 后再 ApplyTransferred。详见上文 English 节的代码示例。全部 Bind 完成后可用 Harness.PruneConfigKeys 删掉未登记的废弃键。

mod 作者怎么用

[BepInDependency("com.yummi.dsp.yummiharness")]
...
Harness.RegisterConflict("MyMod", "other.guid", "OtherMod");
Harness.RegisterCompatibilityAdvisory(
    "MyMod",
    new[] { "com.other.mod.guid" },
    summaryZh: "MyMod 与 OtherMod 在物流统计上兼容性较差,可能出现产量显示异常",
    summaryEn: "MyMod and OtherMod may disagree on logistics stats; production UI can look wrong",
    detailZh: "建议关闭 OtherMod 的统计增强或只保留一个 mod 的 GameTick 逻辑。",
    detailEn: "Disable the other mod's stat tweak or keep only one GameTick-related feature.",
    advisoryId: "MyMod.WithOtherMod.Stats");
Harness.PatchAll(harmony, typeof(MyPatches), new PatchOptions { ModName = "MyMod" });

// 补丁方法照旧写,另加 [Guard]
[HarmonyPostfix]
[HarmonyPatch(typeof(StationComponent), nameof(StationComponent.AddItem))]
[YummiHarness.Guard("806f415ada529868")]
public static void AddItem_Postfix(...) { }

怎么获取指纹(不是 mod 作者也可以)

需要 .NET SDK,以及游戏目录里未剥离的原版 Assembly-CSharp.dll(NuGet 的 GameLibs 方法体被剥空,不能用)。

# 1. 看一个 mod(任何人写的)补丁了哪些函数、指纹是多少
.\tools\get-fingerprint.ps1 -Mod "C:\path\SomeMod.dll"

# 2. 看某个游戏函数的指纹和规范化 IL
.\tools\get-fingerprint.ps1 -Method "StationComponent::AddItem"

# 3. 游戏更新后,比较同一函数新旧版本的差异
.\tools\get-fingerprint.ps1 -Method "StationComponent::AddItem" -OldGame "D:\old\Dyson Sphere Program"

脚本会自动查找 Steam 版游戏目录(或用 -Game / 环境变量 DSP_GAME_DIR 指定),首次使用自动编译命令行工具。输出中:

  • [OK] 与 [Guard] 一致;[已变化] 目标方法被游戏更新改动;[找不到] 方法被删除或改签名;[无Guard] 该补丁没有设置指纹,行尾给出可直接粘贴的 [Guard("...")]。
  • 有补丁已变化/找不到时,退出码为 1,可放进构建脚本。

不用脚本也行:harness scan <Mod.dll> <游戏目录>、harness dump <游戏目录> <类::方法>、harness diff <旧游戏目录> <新游戏目录> <类::方法>。

构建

dotnet build plugin -c Release -o bin     # YummiHarness.dll
dotnet build cli -c Release -o bin        # harness.exe

局限

  • 指纹只覆盖目标方法自身,不覆盖它调用的其他方法。
  • 运行时通过 BepInEx 自带的 Mono.Cecil 读取游戏 dll 的 IL。

中国用户特殊说明

  • 有问题可以直接来我QQ群问我,目前群为629176031。

CHANGELOG

Changelog

0.2.3 - 2026-10-17

  • Harness.PruneConfigKeys to drop cfg entries no longer bound by the mod.

0.2.2 - 2026-10-17

  • Notice levels (Error / Warning / Info), Harness.Report, and DialogLevel config (default ErrorOnly); shared-patch warnings demoted to log when below threshold.
  • RegisterCompatibilityAdvisory optional NoticeLevel parameter.

0.2.1 - 2026-10-15

  • Harness.RegisterCompatibilityAdvisory: custom bilingual warnings when selected mods are all loaded (main-menu dialog + log detail).

0.2.0 - 2026-10-15

  • Fix fingerprinting when CommonAPI Preloader loads Assembly-CSharp from in-memory modules (data-0000… paths): resolve vanilla DLL via BepInEx ManagedPath and signature fallback.
  • Thunderstore manifest.json for distribution.
  • Shared-patch detection: log safe multi-mod Postfix combinations as info; warn only on risky Harmony pairs.

0.1.0

  • Initial release: Harness.PatchAll, [Guard], failure aggregation, conflict registration, bilingual main-menu dialog, harness CLI and get-fingerprint.ps1.

更新日志

0.2.3 - 2026-10-17

  • Harness.PruneConfigKeys:Bind 后删除 cfg 里已废弃、未登记的键。

0.2.2 - 2026-10-17

  • 提示分级(Error / Warning / Info)、Harness.Report、DialogLevel 配置(默认仅 Error 弹窗);无害同函数补丁按级别写日志。
  • RegisterCompatibilityAdvisory 可选 NoticeLevel。

0.2.1 - 2026-10-15

  • Harness.RegisterCompatibilityAdvisory:登记自定义中英兼容性告警,指定 mod 全部加载时在主菜单提示,详情写入日志。

0.2.0 - 2026-10-15

  • 修复 CommonAPI Preloader 将程序集载入内存后指纹路径为 data-0000… 的问题:从 BepInEx ManagedPath 读原版 DLL,并按签名回退查找方法。
  • 增加 Thunderstore 用 manifest.json。
  • 同函数多 mod:安全 Postfix 组合记 Info,仅对高风险 Harmony 组合告警。

0.1.0

  • 初版:Harness.PatchAll、[Guard]、失败汇总、互斥登记、主菜单双语弹窗、harness CLI 与 get-fingerprint.ps1。