HarmonyPatchExtensions

版本 v1.3.0·更新於 2026-08-20

Adds mixin like patching to Harmony

模組介紹 作者原文

Harmony.PatchExtensions

Attribute based extensions for Harmony that lets you define mixin style patches.

Features

  • Attribute based patches
  • Injection points: HEAD (prefix), POSTFIX, RETURN (At every return), INVOKE (insert before call), REDIRECT (replace call), AFTER (after call), FINALLY, ARG, LOOP_BEFORE/TOP/BOTTOM/AFTER, BRANCH_TRUE/FALSE, LOCAL_WRITE/READ, ARG_WRITE/READ, FIELD_WRITE/READ
  • Occurrence and start-index targeting
  • Conflict detection
  • Optional wrapper for overwriting prefixes that return the target's return type
  • Patching variable declarations in methods

Install

Use one of the following:

  • Reference the project directly in your solution
  • Install the published NuGet package: (Insert package when uploaded here)
  • If using publicizers add `` to an ItemGroup so documentations shows up in the code editor

Quick Start

using System.Reflection;

using HarmonyLib;

using HarmonyLib.PatchExtensions;

public static class Program

{

public static void Main()

{

var harmony = new Harmony("example.patching");

MixinLoader.ApplyPatches(harmony, Assembly.GetExecutingAssembly());

// Or for using a single patch class

// MixinLoader.ApplyPatches(harmony, Assembly.GetExecutingAssembly(), typeof(Patches));

}

}

Patch Examples

HEAD (prefix)

using HarmonyLib.PatchExtensions;

public static class Patches

{

[Patch(typeof(Target), "Add", AT.HEAD)]

public static void AddPrefix(int a, int b)

{

// Will run before Target.Add

a += 1;

}

}

Result:

public class Target

{

public int Add(int a, int b)

{

+ a += 1;

return a + b;

}

}

HEAD overwrite (skip original)

If overwriting: true, the patch can return bool (Harmony style) or the same return type as the target.

using HarmonyLib.PatchExtensions;

public static class OverwritePatches

{

[Patch(typeof(Target), "Add", AT.HEAD, overwriting: true)]

public static int AddOverwrite(int a, int b)

{

return 68; // the wrapper sets __result and skips original automatically

}

}

Result:

public class Target

{

public int Add(int a, int b)

{

+ return 68;

  • return a + b;

}

}

POSTFIX (Just harmony postfix)

using HarmonyLib.PatchExtensions;

public static class PostfixPatches

{

[Patch(typeof(Target), "Add", AT.POSTFIX)]

public static void AddPostfix(int a, int b, ref int __result)

{

__result += 1;

}

}

Result:

public class Target

{

public int Add(int a, int b)

{

  • return a + b;

+ __result = a + b;

+ __result += 1;

return __result;

}

}

RETURN

using HarmonyLib.PatchExtensions;

public static class ReturnPatches

{

[Patch(typeof(Target), "Foo", AT.RETURN)]

public static void AddReturn(int a, int b, bool c, ref int __result)

{

__result += 1;

}

}

Result:

public class Target

{

public int Foo(int a, int b, bool c)

{

if (c)

{

__result = a;

+ __result += 1;

return __result;

}

else

{

__result = b;

+ __result += 1;

return __result;

}

}

}

INVOKE (insert before call)

using HarmonyLib.PatchExtensions;

public static class InvokePatches

{

[Patch(typeof(TargetCalls), "Foo", AT.INVOKE, target: "Helper.DoThing", occurrence: 2)] // occurrence: 0 matches all

public static void BeforeSecondCall()

{

// Injected before the 2nd call to Helper.DoThing

}

}

Result:

public class TargetCalls

{

public void Foo()

{

Helper.DoThing();

+ InvokePatches.BeforeSecondCall();

Helper.DoThing();

}

}

REDIRECT (replace call)

using HarmonyLib.PatchExtensions;

public static class RedirectPatches

{

[Patch(typeof(TargetCalls), "Foo", AT.REDIRECT, target: "Helper.DoThing", occurrence: 0)] // occurrence can also be specified to target

public static void ReplaceCall()

{

// Replaces Helper.DoThing with this method

}

}

Result:

public class TargetCalls

{

public void Foo()

{

  • Helper.DoThing();
  • Helper.DoThing();

+ RedirectPatches.ReplaceCall();

+ RedirectPatches.ReplaceCall();

}

}

REDIRECT with occurrence

using HarmonyLib.PatchExtensions;

public static class RedirectPatches

{

[Patch(typeof(TargetCalls), "Foo", AT.REDIRECT, target: "Helper.DoThing", occurrence: 1)] // occurrence

安裝與使用 安裝:BepInEx 外掛

  1. 本站下載的壓縮包就是模組本體,通常是 BepInEx 外掛(解壓後得到 .dll 或外掛資料夾)。
  2. 建議流程:用社群模組管理器(如 r2modman)選中本遊戲後匯入該模組,管理器會自動裝好 BepInEx 前置並處理依賴。
  3. 手動流程:先在遊戲目錄裝好 BepInEx 載入器,再把解壓出的 .dll 或外掛資料夾放進 BepInEx/plugins/。
  4. 啟動遊戲,BepInEx 控制台會列印載入日誌;確認這個模組出現在日誌裡即為安裝成功。

帶「前置依賴」的模組需要一併安裝,否則不會載入。功能開關通常在遊戲內或外掛自帶的設定檔裡調整。

前置依賴

下面這些內容需要先安裝,否則該模組不會生效:

BepInEx-BepInExPack

檔案與校驗

檔案名稱
HarmonyPatchExtensions-1.3.0.zip
檔案大小
81.3 KiB