Closed dymanoid closed 6 years ago
Could easily be another mod that user has installed, also changing this method and leading to incompatibilities.
Do you mean a "direct" patch?
I think the IL code of that message could be changed by another mods transpiler before or after you change it. Have you tried to turn on the debug log of Harmony to see the result of your transpiler and to verify if it produces correct IL code?
Now having the same exception with another game method:
System.FormatException: Method WeatherManager.SimulationStepImpl(System.Int32) cannot be patched. Reason: Invalid IL code in (wrapper dynamic-method) WeatherManager:SimulationStepImpl_Patch1 (object,int): IL_0025: stfld 0x00000009
I'm not using any transpilers in my patches, just plain prefixes and postfixes. Does a debug log help in this case? On my machine, there are no exceptions. That's why it makes it so difficult to diagnose. The user who experience this is not a dev, so it's hard to explain what he needs to do.
Yes. Use HarmonyInstance.DEBUG = true
before the patch assignment an it will give you a log file on your desktop. Post the part that shows the IL of your patched original method. Thanks
So I was able to get the Harmony log from the user who experiences this issue. I also switched the debug log on on my machine to compare them.
First of all, all methods appear twice in the log. I suppose, the first time after patching and the second time after reverting the patch. Is this correct?
Then, I compared the logs from the user and mine. The second appearances of the method in both logs are exactly the same. (After reverting the patch?)
Here is the beginning of the method:
### Patch WeatherManager, Void SimulationStepImpl(Int32)
L_0000: Local var 0: SimulationManager
L_0000: Local var 1: System.Single
L_0000: Local var 2: System.Single
L_0000: Local var 3: ItemClass+Availability
L_0000: Local var 4: System.Single
L_0000: Local var 5: System.Int32
L_0000: Local var 6: System.Single
L_0000: Local var 7: System.Int32
L_0000: Local var 8: System.Int32
L_0000: Local var 9: System.Single
L_0000: Local var 10: System.Single
L_0000: Local var 11: System.Single
L_0000: Local var 12: System.Int32
L_0000: Local var 13: System.Int32
L_0000: Local var 14: System.Single
L_0000: Local var 15: System.Single
L_0000: Local var 16: System.Single
L_0000: Local var 17: System.Int32
L_0000: Local var 18: System.UInt32
L_0000: Local var 19: InstanceID
L_0000: Local var 20: System.Single
L_0000: Local var 21: System.Int32
L_0000: ldarg.1
L_0001: brfalse Label1
L_0006: ldarg.1
L_0007: ldc.i4 1000
L_000c: beq Label2
L_0011: call SimulationManager get_instance()
L_0016: stloc.0
L_0017: ldarg.0
L_0018: ldfld System.Single m_targetDirection
L_001d: ldarg.0
L_001e: ldfld System.Single m_windDirection
L_0023: call Single DeltaAngle(Single, Single)
So it looks like the original code is the same both on my machine and on the user's one.
But the first appearances of the method in the logs differ! Here is my log (WORKING):
### Patch WeatherManager, Void SimulationStepImpl(Int32)
L_0000: Local var 0: SimulationManager
L_0000: Local var 1: System.Single
L_0000: Local var 2: System.Single
L_0000: Local var 3: ItemClass+Availability
L_0000: Local var 4: System.Single
L_0000: Local var 5: System.Int32
L_0000: Local var 6: System.Single
L_0000: Local var 7: System.Int32
L_0000: Local var 8: System.Int32
L_0000: Local var 9: System.Single
L_0000: Local var 10: System.Single
L_0000: Local var 11: System.Single
L_0000: Local var 12: System.Int32
L_0000: Local var 13: System.Int32
L_0000: Local var 14: System.Single
L_0000: Local var 15: System.Single
L_0000: Local var 16: System.Single
L_0000: Local var 17: System.Int32
L_0000: Local var 18: System.UInt32
L_0000: Local var 19: InstanceID
L_0000: Local var 20: System.Single
L_0000: Local var 21: System.Int32
L_0000: ldarg.0
L_0001: ldflda System.Single m_temperatureSpeed
L_0006: ldarg.0
L_0007: ldfld System.Single m_targetTemperature
L_000c: ldarg.0
L_000d: ldfld System.Single m_currentTemperature
L_0012: call Void Prefix(Single ByRef, Single, Single)
L_0017: ldarg.1
L_0018: brfalse Label1
L_001d: ldarg.1
L_001e: ldc.i4 1000
L_0023: beq Label2
L_0028: call SimulationManager get_instance()
L_002d: stloc.0
L_002e: ldarg.0
L_002f: ldfld System.Single m_targetDirection
L_0034: ldarg.0
L_0035: ldfld System.Single m_windDirection
L_003a: call Single DeltaAngle(Single, Single)
Here is the user's log (NOT WORKING)
FormatException: Invalid IL code: IL_0025: stfld 0x00000009
### Patch WeatherManager, Void SimulationStepImpl(Int32)
L_0000: Local var 0: SimulationManager
L_0000: Local var 1: System.Single
L_0000: Local var 2: System.Single
L_0000: Local var 3: ItemClass+Availability
L_0000: Local var 4: System.Single
L_0000: Local var 5: System.Int32
L_0000: Local var 6: System.Single
L_0000: Local var 7: System.Int32
L_0000: Local var 8: System.Int32
L_0000: Local var 9: System.Single
L_0000: Local var 10: System.Single
L_0000: Local var 11: System.Single
L_0000: Local var 12: System.Int32
L_0000: Local var 13: System.Int32
L_0000: Local var 14: System.Single
L_0000: Local var 15: System.Single
L_0000: Local var 16: System.Single
L_0000: Local var 17: System.Int32
L_0000: Local var 18: System.UInt32
L_0000: Local var 19: InstanceID
L_0000: Local var 20: System.Single
L_0000: Local var 21: System.Int32
L_0000: Local var 22: System.Single
L_0000: ldc.r4 0
L_0005: stloc 22 (System.Single)
L_0007: ldarg.0
L_0008: ldfld System.Single m_temperatureSpeed
L_000d: stloc 22 (System.Single)
L_000f: ldloca 22 (System.Single)
L_0011: ldarg.0
L_0012: ldfld System.Single m_targetTemperature
L_0017: ldarg.0
L_0018: ldfld System.Single m_currentTemperature
L_001d: call Void Prefix(Single ByRef, Single, Single)
L_0022: ldloc 22 (System.Single)
L_0024: ldarg.0
L_0025: stfld System.Single m_temperatureSpeed
L_002a: ldarg.1
L_002b: brfalse Label1
L_0030: ldarg.1
L_0031: ldc.i4 1000
L_0036: beq Label2
L_003b: call SimulationManager get_instance()
L_0040: stloc.0
L_0041: ldarg.0
L_0042: ldfld System.Single m_targetDirection
L_0047: ldarg.0
L_0048: ldfld System.Single m_windDirection
L_004d: call Single DeltaAngle(Single, Single)
Note that IL code at the beginning of the method differs! There is an additional local variable that is missing in my log, and e.g. some stloc 22 (System.Single)
statements.
This local variable (22) is never used in the method again, the last usage is at L_0022.
And for your reference, here is the prefix method signature:
static void Prefix(
ref float ___m_temperatureSpeed,
float ___m_targetTemperature,
float ___m_currentTemperature)
And another comment: the user reports that sometimes it works.
In the game's log file, I see that there are multiple mods that load different Harmony assemblies: 0Harmony, Version=1.0.9.1 0Harmony, Version=1.1.0.0 (my mod) 0Harmony, Version=1.1.1.0
Could the invalid IL be caused by some conflict of which Harmony version "wins"?
Please test again with the latest HEAD. I made a few changes and bug fixes regarding loading and unloading of mods and patches. Specifically, transpilers were not correctly removed.
Unfortunately I cannot test it actually. On my dev machine, I cannot reproduce the exceptions. But I'm not willing to deploy a not-yet-released library to 15,000+ players just to see if something became better. I have to wait for the next official Harmony release.
Okay, the 1.2.0.1 is out. Despite it has a bug that potentially might lead to a crash due to a MissingFieldException
(see #115), I will roll out this version and let the players test whether the `FormatException´ described in the original post is fixed.
Can you explain where the MissingFieldException
is coming from?
Okay, I didn't check the Traverse
implementation, my bad. There will be no MissingFieldException
. However, due to a potential hash collision, the Harmony code might get a wrong version field value (0). I cannot say what happens then, but it's a thing I'm not expecting in a library that messes with the IL code on such a low level.
This issue seems to be fixed. No more user complaints with version 1.2.0.1.
I have a very strange issue. Using Harmony 1.1.0. This is again a patch for the Cities:Skylines game.
I have an x64 assembly that perfectly works on my system: Windows 10 64bit. No issues, the patching works very well. A Steam user reports an exception with the same assembly on his machine: Windows 10 64bit, same game version, same binary of my assembly.
The exception is:
Again, I cannot reproduce this on my machine. The game recompiles the assemblies with Mono, so I thought the user has a Mac or a Linux version and that causes some binary incompatibility. But no - Windows 10 64bit, exactly like mine. There are hundreds of other users having no issues too.
What can we do to diagnose this issue and find a solution?
Maybe this is somewhat similar to #38, but the exception is FormatException in my case.