dymanoid / RealTime

A mod for the Cities: Skylines game. Adjusts the time flow and the citizens behavior to make them more real.
MIT License
98 stars 59 forks source link

Avoid patching of virtual methods without body #264

Open boformer opened 4 years ago

boformer commented 4 years ago

While working on my Harmony 2 mod, I noticed that Real Time attempts to apply patch methods without a method body, which is technically impossible.

In Harmony 1.2, this will not throw any exceptions, but instead patch the method on the first base type that implements it.

Harmony 2.0.0.9 no longer permits patching those patches and throws an exception instead.

Solution:

Log when patches are applied with Harmony 2.0.0.9:

Patching method virtual System.Boolean HumanAI::ArriveAtTarget(System.UInt16 instanceID, CitizenInstance& citizenData) (HarmonyId: com.cities_skylines.dymanoid.realtime)

(Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

Harmony (ID 'com.cities_skylines.dymanoid.realtime') method patch failed for RealTime.GameConnection.Patches.ResidentAIPatch+HumanAI_ArriveAtTarget: System.ArgumentException: You can only patch implemented methods/constructors. Path the declared method virtual System.Boolean HumanAI::ArriveAtTarget(System.UInt16 instanceID, CitizenInstance& citizenData) instead.
at HarmonyLib.PatchProcessor.Patch () <0x002c8>
at CitiesHarmony.Harmony1201SelfPatcher.PatchProcessor_Patch_Prefix (object,System.Collections.Generic.List`1<System.Reflection.MethodBase>,object,object,object,System.Collections.Generic.List`1<System.Reflection.Emit.DynamicMethod>&) <0x002f2>
at (wrapper dynamic-method) Harmony.PatchProcessor.DMD<DMD<Patch_Patch1>?-33854976..Patch_Patch1> (Harmony.PatchProcessor) <0x00085>
at Harmony.HarmonyInstance.Patch (System.Reflection.MethodBase,Harmony.HarmonyMethod,Harmony.HarmonyMethod,Harmony.HarmonyMethod) <0x000c2>
at SkyTools.Patching.MethodPatcher/Patcher.ApplyPatch (System.Reflection.MethodInfo,System.Reflection.MethodInfo,System.Reflection.MethodInfo,System.Reflection.MethodInfo) <0x00161>
at SkyTools.Patching.PatchBase.ApplyPatch (SkyTools.Patching.IPatcher) <0x00121>
at SkyTools.Patching.MethodPatcher.Apply () <0x000f3>

(Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

PatchProcessor_Patch_Prefix

(Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

Patching method System.Boolean HumanAI::StartMoving(System.UInt32 citizenID, Citizen& data, System.UInt16 sourceBuilding, System.UInt16 targetBuilding) (HarmonyId: com.cities_skylines.dymanoid.realtime)

(Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

Harmony (ID 'com.cities_skylines.dymanoid.realtime') method patch failed for RealTime.GameConnection.Patches.ResidentAIPatch+ResidentAI_StartMoving: System.ArgumentException: You can only patch implemented methods/constructors. Path the declared method System.Boolean HumanAI::StartMoving(System.UInt32 citizenID, Citizen& data, System.UInt16 sourceBuilding, System.UInt16 targetBuilding) instead.
at HarmonyLib.PatchProcessor.Patch () <0x002c8>
at CitiesHarmony.Harmony1201SelfPatcher.PatchProcessor_Patch_Prefix (object,System.Collections.Generic.List`1<System.Reflection.MethodBase>,object,object,object,System.Collections.Generic.List`1<System.Reflection.Emit.DynamicMethod>&) <0x002f2>
at (wrapper dynamic-method) Harmony.PatchProcessor.DMD<DMD<Patch_Patch1>?-33854976..Patch_Patch1> (Harmony.PatchProcessor) <0x00085>
at Harmony.HarmonyInstance.Patch (System.Reflection.MethodBase,Harmony.HarmonyMethod,Harmony.HarmonyMethod,Harmony.HarmonyMethod) <0x000c2>
at SkyTools.Patching.MethodPatcher/Patcher.ApplyPatch (System.Reflection.MethodInfo,System.Reflection.MethodInfo,System.Reflection.MethodInfo,System.Reflection.MethodInfo) <0x00161>
at SkyTools.Patching.PatchBase.ApplyPatch (SkyTools.Patching.IPatcher) <0x00121>
at SkyTools.Patching.MethodPatcher.Apply () <0x000f3>