BattletechModders / ModTek

Mod system for HBS's PC game BattleTech.
GNU Lesser General Public License v2.1
121 stars 34 forks source link

Multitargeted patches only executing one patch #236

Closed 0x1d7 closed 1 month ago

0x1d7 commented 1 month ago

I attempted to decorate a single function with multiple patches unsuccessfully. Only one of the two decorations took effect per the battletech_log file. Is this feature not functional in the version of Harmony in use or is something else needed beyond the above provided example in HarmonyX?

While not critical, it would simplify my code.

CptMoore commented 1 month ago
  1. battletech_log gets the logs from HarmonyX, however it is not a "dump state" after all patching is done, but a "dump state" after each patch. So usually you have to reverse search from the bottom to get the latest patched state of a method. Maybe you overlooked it working? Or overlooked the exception generated during patching?
  2. we use the official HarmonyX release, there were major changes in the last couple releases of HarmonyX though, maybe something broke. An idea would be to join the BepInEx discord and ask around there or use the search function there
  3. ModTek itself uses multi targeting via the TargetMethods static method, see https://github.com/BattletechModders/ModTek/blob/81d8a13bb7fd37d6143b7f4af70da4575348e90b/ModTek/Features/Logging/Patches/Exception_ctor_Patch.cs#L29 It is not the same as multi-targeting via patch annotations on a method due to prefix/postfix patches being shared, but maybe it helps.
0x1d7 commented 1 month ago

No exceptions, mod loads and shows as enabled with only a single method patched. In this example, the method being patched per the log is void BattleTech.SimGameState::ResolveCompleteContract().

    [HarmonyPatch(typeof(SimGameState), "SaveSerializationComplete")]
    [HarmonyPatch(typeof(SaveGameStructure), "NotifyRefresh")]
    [HarmonyPatch(typeof(SaveGameStructure), "NotifyLoadCcomplete")]
    [HarmonyPatch(typeof(SimGameState), "OnHeadAttachedStateCompleteListener")]
    [HarmonyPatch(typeof(TurnDirector), "StartFirstRound")]
    [HarmonyPatch(typeof(TurnDirector), "BeginNewRound")]
    [HarmonyPatch(typeof(SimGameState), "ResolveCompleteContract")]
    static internal class GcPostSaveSerialization

I'll ask/search on the discord. Thanks!

CptMoore commented 1 month ago

I don't see any prefix or postfix annotation, did you just not include it here or forgot to add it altogether?

0x1d7 commented 1 month ago

Ultimately I was able to resolve this with the help of the BepInEx discord. I needed to move my decorations to my method and then instead of calling Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(),..., I needed to specify my type Harmony.CreateAndPatchAll(typeof(GcPostSaveSerialization)...