pardeike / Harmony

A library for patching, replacing and decorating .NET and Mono methods during runtime
https://www.patreon.com/pardeike
MIT License
5.22k stars 490 forks source link

System.InvalidProgramException: Invalid IL code #38

Closed Leigon closed 5 years ago

Leigon commented 7 years ago

Hi

I am trying to mod Cities Skylines and came across your lib last week replacing Detours. Just testing I am prefixing a simple function however a System.InvalidProgramException exeption is thrown.

I assume this is something similar to a previous issue... #3 as L_0750 is a function call with refs? L_0750: callvirt Void GetNodeBuilding(UInt16, NetNode ByRef, BuildingInfo ByRef, Single ByRef)

Thanks in advance, -Adrian

System.InvalidProgramException: Invalid IL code in (wrapper dynamic-method) NetNode:CalculateNode_Patch1 (object,uint16): IL_0750: callvirt  0x0000011b
 at (wrapper managed-to-native) System.RuntimeMethodHandle:GetFunctionPointer (intptr)
 at System.RuntimeMethodHandle.GetFunctionPointer () [0x00000] in <filename unknown>:0 
 at Harmony.ILCopying.Memory.GetMethodStart (System.Reflection.MethodBase method) [0x00000] in <filename unknown>:0 
 at Harmony.PatchFunctions.UpdateWrapper (System.Reflection.MethodBase original, Harmony.PatchInfo patchInfo) [0x00000] in <filename unknown>:0 
 at Harmony.PatchProcessor.Patch () [0x00000] in <filename unknown>:0 
 at Harmony.HarmonyInstance.Patch (System.Reflection.MethodBase original, Harmony.HarmonyMethod prefix, Harmony.HarmonyMethod postfix, Harmony.HarmonyMethod transpiler) [0x00000] in <filename unknown>:0 
 at TollRoad.Node.Hook () [0x00000] in <filename unknown>:0 
PATCHING NetNode Void CalculateNode(UInt16)
L_0000: Local var 0 NetManager
L_0000: Local var 1 UnityEngine.Vector3
L_0000: Local var 2 System.Int32
L_0000: Local var 3 System.Int32
L_0000: Local var 4 System.Boolean
L_0000: Local var 5 System.Boolean
L_0000: Local var 6 System.Boolean
L_0000: Local var 7 System.Boolean
L_0000: Local var 8 System.Boolean
L_0000: Local var 9 System.Boolean
L_0000: Local var 10 System.Boolean
L_0000: Local var 11 System.Boolean
L_0000: Local var 12 System.Boolean
L_0000: Local var 13 System.Boolean
L_0000: Local var 14 System.Boolean
L_0000: Local var 15 System.Boolean
L_0000: Local var 16 NetInfo
L_0000: Local var 17 System.Int32
L_0000: Local var 18 System.Int32
L_0000: Local var 19 NetInfo
L_0000: Local var 20 System.Single
L_0000: Local var 21 System.Int32
L_0000: Local var 22 System.UInt16
L_0000: Local var 23 NetInfo
L_0000: Local var 24 System.Single
L_0000: Local var 25 System.Boolean
L_0000: Local var 26 System.Int32
L_0000: Local var 27 System.UInt16
L_0000: Local var 28 System.UInt16
L_0000: Local var 29 System.UInt16
L_0000: Local var 30 UnityEngine.Vector3
L_0000: Local var 31 UnityEngine.Vector3
L_0000: Local var 32 System.Boolean
L_0000: Local var 33 UnityEngine.Vector3
L_0000: Local var 34 NetInfo
L_0000: Local var 35 ItemClass
L_0000: Local var 36 System.Int32
L_0000: Local var 37 System.Int32
L_0000: Local var 38 System.Int32
L_0000: Local var 39 System.UInt16
L_0000: Local var 40 NetInfo
L_0000: Local var 41 ItemClass
L_0000: Local var 42 System.Boolean
L_0000: Local var 43 UnityEngine.Vector3
L_0000: Local var 44 System.Single
L_0000: Local var 45 System.Single
L_0000: Local var 46 UnityEngine.Vector3
L_0000: Local var 47 UnityEngine.Vector3
L_0000: Local var 48 System.Single
L_0000: Local var 49 NetNode+Flags
L_0000: Local var 50 BuildingInfo
L_0000: Local var 51 System.Single
L_0000: call Void CalculateNode_Prefix()
L_0005: ldarg.0
L_0006: ldfld NetNode+Flags m_flags
L_000b: brtrue Label 2
L_0010: br Label 0
L_0015: Label 2
L_0015: call NetManager get_instance()
L_001a: stloc.0
L_001b: call Vector3 get_zero()
L_0020: stloc.1
L_0021: ldc.i4.0
L_0022: stloc.2
L_0023: ldc.i4.0
L_0024: stloc.3
L_0025: ldc.i4.0
L_0026: stloc.s 4 (System.Boolean)
L_0028: ldc.i4.0
L_0029: stloc.s 5 (System.Boolean)
L_002b: ldc.i4.0
L_002c: stloc.s 6 (System.Boolean)
L_002e: ldc.i4.0
L_002f: stloc.s 7 (System.Boolean)
L_0031: ldc.i4.0
L_0032: stloc.s 8 (System.Boolean)
L_0034: ldc.i4.0
L_0035: stloc.s 9 (System.Boolean)
L_0037: ldc.i4.0
L_0038: stloc.s 10 (System.Boolean)
L_003a: ldc.i4.0
L_003b: stloc.s 11 (System.Boolean)
L_003d: ldc.i4.0
L_003e: stloc.s 12 (System.Boolean)
L_0040: ldc.i4.1
L_0041: stloc.s 13 (System.Boolean)
L_0043: ldc.i4.1
L_0044: stloc.s 14 (System.Boolean)
L_0046: call TerrainManager get_instance()
L_004b: ldarg.0
L_004c: ldfld UnityEngine.Vector3 m_position
L_0051: callvirt Boolean HasDetailMapping(Vector3)
L_0056: stloc.s 15 (System.Boolean)
L_0058: ldnull
L_0059: stloc.s 16 (NetInfo)
L_005b: ldc.i4.0
L_005c: stloc.s 17 (System.Int32)
L_005e: ldc.i4.0
L_005f: stloc.s 18 (System.Int32)
L_0061: ldnull
L_0062: stloc.s 19 (NetInfo)
L_0064: ldc.r4 -1E+07
L_0069: stloc.s 20 (System.Single)
L_006b: ldc.i4.0
L_006c: stloc.s 21 (System.Int32)
L_006e: br Label 3
L_0073: Label 6
L_0073: ldarg.0
L_0074: ldloc.s 21 (System.Int32)
L_0076: call UInt16 GetSegment(Int32)
L_007b: stloc.s 22 (System.UInt16)
L_007d: ldloc.s 22 (System.UInt16)
L_007f: brfalse Label 4
L_0084: ldloc.0
L_0085: ldfld Array16`1[NetSegment] m_segments
L_008a: ldfld NetSegment[] m_buffer
L_008f: ldloc.s 22 (System.UInt16)
L_0091: ldelema NetSegment
L_0096: call NetInfo get_Info()
L_009b: stloc.s 23 (NetInfo)
L_009d: ldloc.s 23 (NetInfo)
L_009f: ldfld NetAI m_netAI
L_00a4: ldloc.s 22 (System.UInt16)
L_00a6: ldloc.0
L_00a7: ldfld Array16`1[NetSegment] m_segments
L_00ac: ldfld NetSegment[] m_buffer
L_00b1: ldloc.s 22 (System.UInt16)
L_00b3: ldelema NetSegment
L_00b8: callvirt Single GetNodeInfoPriority(UInt16, NetSegment ByRef)
L_00bd: stloc.s 24 (System.Single)
L_00bf: ldloc.s 24 (System.Single)
L_00c1: ldloc.s 20 (System.Single)
L_00c3: ble.un Label 5
L_00c8: ldloc.s 23 (NetInfo)
L_00ca: stloc.s 19 (NetInfo)
L_00cc: ldloc.s 24 (System.Single)
L_00ce: stloc.s 20 (System.Single)
L_00d0: Label 4
L_00d0: Label 5
L_00d0: ldloc.s 21 (System.Int32)
L_00d2: ldc.i4.1
L_00d3: add
L_00d4: stloc.s 21 (System.Int32)
L_00d6: Label 3
L_00d6: ldloc.s 21 (System.Int32)
L_00d8: ldc.i4.8
L_00d9: blt Label 6
L_00de: ldloc.s 19 (NetInfo)
L_00e0: brtrue Label 7
L_00e5: ldarg.0
L_00e6: call NetInfo get_Info()
L_00eb: stloc.s 19 (NetInfo)
L_00ed: Label 7
L_00ed: ldloc.s 19 (NetInfo)
L_00ef: ldarg.0
L_00f0: call NetInfo get_Info()
L_00f5: beq Label 8
L_00fa: ldarg.0
L_00fb: ldloc.s 19 (NetInfo)
L_00fd: call Void set_Info(NetInfo)
L_0102: call NetManager get_instance()
L_0107: ldarg.1
L_0108: callvirt Void UpdateNodeColors(UInt16)
L_010d: ldloc.s 19 (NetInfo)
L_010f: ldfld System.Boolean m_canDisable
L_0114: brtrue Label 9
L_0119: ldarg.0
L_011a: dup
L_011b: ldfld NetNode+Flags m_flags
L_0120: ldc.i4.s -9
L_0122: and
L_0123: stfld NetNode+Flags m_flags
L_0128: Label 8
L_0128: Label 9
L_0128: ldc.i4.0
L_0129: stloc.s 25 (System.Boolean)
L_012b: ldc.i4.0
L_012c: stloc.s 26 (System.Int32)
L_012e: br Label 10
L_0133: Label 58
L_0133: ldarg.0
L_0134: ldloc.s 26 (System.Int32)
L_0136: call UInt16 GetSegment(Int32)
L_013b: stloc.s 27 (System.UInt16)
L_013d: ldloc.s 27 (System.UInt16)
L_013f: brfalse Label 11
L_0144: ldloc.2
L_0145: ldc.i4.1
L_0146: add
L_0147: stloc.2
L_0148: ldloc.0
L_0149: ldfld Array16`1[NetSegment] m_segments
L_014e: ldfld NetSegment[] m_buffer
L_0153: ldloc.s 27 (System.UInt16)
L_0155: ldelema NetSegment
L_015a: ldfld System.UInt16 m_startNode
L_015f: stloc.s 28 (System.UInt16)
L_0161: ldloc.0
L_0162: ldfld Array16`1[NetSegment] m_segments
L_0167: ldfld NetSegment[] m_buffer
L_016c: ldloc.s 27 (System.UInt16)
L_016e: ldelema NetSegment
L_0173: ldfld System.UInt16 m_endNode
L_0178: stloc.s 29 (System.UInt16)
L_017a: ldloc.0
L_017b: ldfld Array16`1[NetSegment] m_segments
L_0180: ldfld NetSegment[] m_buffer
L_0185: ldloc.s 27 (System.UInt16)
L_0187: ldelema NetSegment
L_018c: ldfld UnityEngine.Vector3 m_startDirection
L_0191: stloc.s 30 (UnityEngine.Vector3)
L_0193: ldloc.0
L_0194: ldfld Array16`1[NetSegment] m_segments
L_0199: ldfld NetSegment[] m_buffer
L_019e: ldloc.s 27 (System.UInt16)
L_01a0: ldelema NetSegment
L_01a5: ldfld UnityEngine.Vector3 m_endDirection
L_01aa: stloc.s 31 (UnityEngine.Vector3)
L_01ac: ldarg.1
L_01ad: ldloc.s 28 (System.UInt16)
L_01af: ceq
L_01b1: stloc.s 32 (System.Boolean)
L_01b3: ldloc.s 32 (System.Boolean)
L_01b5: brfalse Label 12
L_01ba: ldloc.s 30 (UnityEngine.Vector3)
L_01bc: br Label 13
L_01c1: Label 12
L_01c1: ldloc.s 31 (UnityEngine.Vector3)
L_01c3: Label 13
L_01c3: stloc.s 33 (UnityEngine.Vector3)
L_01c5: ldloc.0
L_01c6: ldfld Array16`1[NetSegment] m_segments
L_01cb: ldfld NetSegment[] m_buffer
L_01d0: ldloc.s 27 (System.UInt16)
L_01d2: ldelema NetSegment
L_01d7: call NetInfo get_Info()
L_01dc: stloc.s 34 (NetInfo)
L_01de: ldloc.s 34 (NetInfo)
L_01e0: callvirt ItemClass GetConnectionClass()
L_01e5: stloc.s 35 (ItemClass)
L_01e7: ldloc.s 34 (NetInfo)
L_01e9: ldfld NetAI m_netAI
L_01ee: callvirt Boolean CanModify()
L_01f3: brtrue Label 14
L_01f8: ldc.i4.0
L_01f9: stloc.s 14 (System.Boolean)
L_01fb: Label 14
L_01fb: ldloc.s 32 (System.Boolean)
L_01fd: ldloc.0
L_01fe: ldfld Array16`1[NetSegment] m_segments
L_0203: ldfld NetSegment[] m_buffer
L_0208: ldloc.s 27 (System.UInt16)
L_020a: ldelema NetSegment
L_020f: ldfld NetSegment+Flags m_flags
L_0214: ldc.i4.s 16
L_0216: and
L_0217: ldc.i4.0
L_0218: ceq
L_021a: ldc.i4.0
L_021b: ceq
L_021d: bne.un Label 15
L_0222: ldloc.s 34 (NetInfo)
L_0224: ldfld System.Int32 m_backwardVehicleLaneCount
L_0229: stloc.s 36 (System.Int32)
L_022b: ldloc.s 34 (NetInfo)
L_022d: ldfld System.Int32 m_forwardVehicleLaneCount
L_0232: stloc.s 37 (System.Int32)
L_0234: br Label 16
L_0239: Label 15
L_0239: ldloc.s 34 (NetInfo)
L_023b: ldfld System.Int32 m_forwardVehicleLaneCount
L_0240: stloc.s 36 (System.Int32)
L_0242: ldloc.s 34 (NetInfo)
L_0244: ldfld System.Int32 m_backwardVehicleLaneCount
L_0249: stloc.s 37 (System.Int32)
L_024b: Label 16
L_024b: ldloc.s 26 (System.Int32)
L_024d: ldc.i4.1
L_024e: add
L_024f: stloc.s 38 (System.Int32)
L_0251: br Label 17
L_0256: Label 33
L_0256: ldarg.0
L_0257: ldloc.s 38 (System.Int32)
L_0259: call UInt16 GetSegment(Int32)
L_025e: stloc.s 39 (System.UInt16)
L_0260: ldloc.s 39 (System.UInt16)
L_0262: brfalse Label 18
L_0267: ldloc.0
L_0268: ldfld Array16`1[NetSegment] m_segments
L_026d: ldfld NetSegment[] m_buffer
L_0272: ldloc.s 39 (System.UInt16)
L_0274: ldelema NetSegment
L_0279: call NetInfo get_Info()
L_027e: stloc.s 40 (NetInfo)
L_0280: ldloc.s 40 (NetInfo)
L_0282: callvirt ItemClass GetConnectionClass()
L_0287: stloc.s 41 (ItemClass)
L_0289: ldloc.s 41 (ItemClass)
L_028b: ldfld ItemClass+Service m_service
L_0290: ldloc.s 35 (ItemClass)
L_0292: ldfld ItemClass+Service m_service
L_0297: beq Label 19
L_029c: ldloc.s 40 (NetInfo)
L_029e: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_02a3: ldloc.s 34 (NetInfo)
L_02a5: ldfld NetInfo+ConnectGroup m_connectGroup
L_02aa: and
L_02ab: brtrue Label 20
L_02b0: ldloc.s 34 (NetInfo)
L_02b2: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_02b7: ldloc.s 40 (NetInfo)
L_02b9: ldfld NetInfo+ConnectGroup m_connectGroup
L_02be: and
L_02bf: brfalse Label 21
L_02c4: Label 19
L_02c4: Label 20
L_02c4: ldarg.1
L_02c5: ldloc.0
L_02c6: ldfld Array16`1[NetSegment] m_segments
L_02cb: ldfld NetSegment[] m_buffer
L_02d0: ldloc.s 39 (System.UInt16)
L_02d2: ldelema NetSegment
L_02d7: ldfld System.UInt16 m_startNode
L_02dc: ceq
L_02de: stloc.s 42 (System.Boolean)
L_02e0: ldloc.s 42 (System.Boolean)
L_02e2: brfalse Label 22
L_02e7: ldloc.0
L_02e8: ldfld Array16`1[NetSegment] m_segments
L_02ed: ldfld NetSegment[] m_buffer
L_02f2: ldloc.s 39 (System.UInt16)
L_02f4: ldelema NetSegment
L_02f9: ldfld UnityEngine.Vector3 m_startDirection
L_02fe: br Label 23
L_0303: Label 22
L_0303: ldloc.0
L_0304: ldfld Array16`1[NetSegment] m_segments
L_0309: ldfld NetSegment[] m_buffer
L_030e: ldloc.s 39 (System.UInt16)
L_0310: ldelema NetSegment
L_0315: ldfld UnityEngine.Vector3 m_endDirection
L_031a: Label 23
L_031a: stloc.s 43 (UnityEngine.Vector3)
L_031c: ldloca.s 33 (UnityEngine.Vector3)
L_031e: ldfld System.Single x
L_0323: ldloca.s 43 (UnityEngine.Vector3)
L_0325: ldfld System.Single x
L_032a: mul
L_032b: ldloca.s 33 (UnityEngine.Vector3)
L_032d: ldfld System.Single z
L_0332: ldloca.s 43 (UnityEngine.Vector3)
L_0334: ldfld System.Single z
L_0339: mul
L_033a: add
L_033b: stloc.s 44 (System.Single)
L_033d: ldc.r4 0.01
L_0342: ldloc.s 34 (NetInfo)
L_0344: ldfld System.Single m_maxTurnAngleCos
L_0349: ldloc.s 40 (NetInfo)
L_034b: ldfld System.Single m_maxTurnAngleCos
L_0350: call Single Min(Single, Single)
L_0355: sub
L_0356: stloc.s 45 (System.Single)
L_0358: ldloc.s 44 (System.Single)
L_035a: ldloc.s 45 (System.Single)
L_035c: bge.un Label 24
L_0361: ldloc.s 34 (NetInfo)
L_0363: ldfld System.Boolean m_requireDirectRenderers
L_0368: brfalse Label 25
L_036d: ldloc.s 34 (NetInfo)
L_036f: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_0374: brfalse Label 26
L_0379: ldloc.s 34 (NetInfo)
L_037b: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_0380: ldloc.s 40 (NetInfo)
L_0382: ldfld NetInfo+ConnectGroup m_connectGroup
L_0387: and
L_0388: brtrue Label 27
L_038d: Label 25
L_038d: ldloc.s 40 (NetInfo)
L_038f: ldfld System.Boolean m_requireDirectRenderers
L_0394: brfalse Label 28
L_0399: ldloc.s 40 (NetInfo)
L_039b: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_03a0: brfalse Label 29
L_03a5: ldloc.s 40 (NetInfo)
L_03a7: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_03ac: ldloc.s 34 (NetInfo)
L_03ae: ldfld NetInfo+ConnectGroup m_connectGroup
L_03b3: and
L_03b4: brfalse Label 30
L_03b9: Label 26
L_03b9: Label 27
L_03b9: Label 29
L_03b9: ldloc.3
L_03ba: ldc.i4.1
L_03bb: add
L_03bc: stloc.3
L_03bd: Label 28
L_03bd: Label 30
L_03bd: br Label 31
L_03c2: Label 24
L_03c2: ldc.i4.1
L_03c3: stloc.s 9 (System.Boolean)
L_03c5: Label 31
L_03c5: br Label 32
L_03ca: Label 21
L_03ca: ldc.i4.1
L_03cb: stloc.s 9 (System.Boolean)
L_03cd: Label 18
L_03cd: Label 32
L_03cd: ldloc.s 38 (System.Int32)
L_03cf: ldc.i4.1
L_03d0: add
L_03d1: stloc.s 38 (System.Int32)
L_03d3: Label 17
L_03d3: ldloc.s 38 (System.Int32)
L_03d5: ldc.i4.8
L_03d6: blt Label 33
L_03db: ldloc.0
L_03dc: ldfld Array16`1[NetNode] m_nodes
L_03e1: ldfld NetNode[] m_buffer
L_03e6: ldloc.s 28 (System.UInt16)
L_03e8: ldelema NetNode
L_03ed: ldfld System.Byte m_elevation
L_03f2: ldloc.0
L_03f3: ldfld Array16`1[NetNode] m_nodes
L_03f8: ldfld NetNode[] m_buffer
L_03fd: ldloc.s 29 (System.UInt16)
L_03ff: ldelema NetNode
L_0404: ldfld System.Byte m_elevation
L_0409: beq Label 34
L_040e: ldc.i4.0
L_040f: stloc.s 13 (System.Boolean)
L_0411: Label 34
L_0411: ldloc.0
L_0412: ldfld Array16`1[NetNode] m_nodes
L_0417: ldfld NetNode[] m_buffer
L_041c: ldloc.s 28 (System.UInt16)
L_041e: ldelema NetNode
L_0423: ldfld UnityEngine.Vector3 m_position
L_0428: stloc.s 46 (UnityEngine.Vector3)
L_042a: ldloc.0
L_042b: ldfld Array16`1[NetNode] m_nodes
L_0430: ldfld NetNode[] m_buffer
L_0435: ldloc.s 29 (System.UInt16)
L_0437: ldelema NetNode
L_043c: ldfld UnityEngine.Vector3 m_position
L_0441: stloc.s 47 (UnityEngine.Vector3)
L_0443: ldloc.s 32 (System.Boolean)
L_0445: brfalse Label 35
L_044a: ldloc.s 15 (System.Boolean)
L_044c: brfalse Label 36
L_0451: call TerrainManager get_instance()
L_0456: ldloc.s 47 (UnityEngine.Vector3)
L_0458: callvirt Boolean HasDetailMapping(Vector3)
L_045d: br Label 37
L_0462: Label 36
L_0462: ldc.i4.0
L_0463: Label 37
L_0463: stloc.s 15 (System.Boolean)
L_0465: br Label 38
L_046a: Label 35
L_046a: ldloc.s 15 (System.Boolean)
L_046c: brfalse Label 39
L_0471: call TerrainManager get_instance()
L_0476: ldloc.s 46 (UnityEngine.Vector3)
L_0478: callvirt Boolean HasDetailMapping(Vector3)
L_047d: br Label 40
L_0482: Label 39
L_0482: ldc.i4.0
L_0483: Label 40
L_0483: stloc.s 15 (System.Boolean)
L_0485: Label 38
L_0485: ldloc.s 46 (UnityEngine.Vector3)
L_0487: ldloc.s 30 (UnityEngine.Vector3)
L_0489: ldloc.s 47 (UnityEngine.Vector3)
L_048b: ldloc.s 31 (UnityEngine.Vector3)
L_048d: call Boolean IsStraight(Vector3, Vector3, Vector3, Vector3)
L_0492: brfalse Label 41
L_0497: ldc.i4.1
L_0498: stloc.s 11 (System.Boolean)
L_049a: br Label 42
L_049f: Label 41
L_049f: ldc.i4.1
L_04a0: stloc.s 10 (System.Boolean)
L_04a2: Label 42
L_04a2: ldloc.2
L_04a3: ldc.i4.1
L_04a4: bne.un Label 43
L_04a9: ldloc.s 32 (System.Boolean)
L_04ab: stloc.s 25 (System.Boolean)
L_04ad: ldloc.s 33 (UnityEngine.Vector3)
L_04af: stloc.1
L_04b0: ldc.i4.1
L_04b1: stloc.s 4 (System.Boolean)
L_04b3: br Label 44
L_04b8: Label 43
L_04b8: ldloc.2
L_04b9: ldc.i4.2
L_04ba: bne.un Label 45
L_04bf: ldloc.s 34 (NetInfo)
L_04c1: ldloc.s 16 (NetInfo)
L_04c3: callvirt Boolean IsCombatible(NetInfo)
L_04c8: brfalse Label 46
L_04cd: ldloc.s 34 (NetInfo)
L_04cf: ldloc.s 19 (NetInfo)
L_04d1: callvirt Boolean IsCombatible(NetInfo)
L_04d6: brfalse Label 47
L_04db: ldloc.s 36 (System.Int32)
L_04dd: ldc.i4.0
L_04de: ceq
L_04e0: ldc.i4.0
L_04e1: ceq
L_04e3: ldloc.s 18 (System.Int32)
L_04e5: ldc.i4.0
L_04e6: ceq
L_04e8: ldc.i4.0
L_04e9: ceq
L_04eb: bne.un Label 48
L_04f0: ldloc.s 37 (System.Int32)
L_04f2: ldc.i4.0
L_04f3: ceq
L_04f5: ldc.i4.0
L_04f6: ceq
L_04f8: ldloc.s 17 (System.Int32)
L_04fa: ldc.i4.0
L_04fb: ceq
L_04fd: ldc.i4.0
L_04fe: ceq
L_0500: bne.un Label 49
L_0505: ldloca.s 1 (UnityEngine.Vector3)
L_0507: ldfld System.Single x
L_050c: ldloca.s 33 (UnityEngine.Vector3)
L_050e: ldfld System.Single x
L_0513: mul
L_0514: ldloca.s 1 (UnityEngine.Vector3)
L_0516: ldfld System.Single z
L_051b: ldloca.s 33 (UnityEngine.Vector3)
L_051d: ldfld System.Single z
L_0522: mul
L_0523: add
L_0524: stloc.s 48 (System.Single)
L_0526: ldloc.s 36 (System.Int32)
L_0528: ldloc.s 18 (System.Int32)
L_052a: bne.un Label 50
L_052f: ldloc.s 37 (System.Int32)
L_0531: ldloc.s 17 (System.Int32)
L_0533: beq Label 51
L_0538: Label 50
L_0538: ldloc.s 36 (System.Int32)
L_053a: ldloc.s 37 (System.Int32)
L_053c: ble Label 52
L_0541: ldc.i4.1
L_0542: stloc.s 7 (System.Boolean)
L_0544: ldc.i4.1
L_0545: stloc.s 6 (System.Boolean)
L_0547: br Label 53
L_054c: Label 52
L_054c: ldc.i4.1
L_054d: stloc.s 8 (System.Boolean)
L_054f: ldc.i4.1
L_0550: stloc.s 6 (System.Boolean)
L_0552: Label 53
L_0552: br Label 54
L_0557: Label 51
L_0557: ldloc.s 48 (System.Single)
L_0559: ldc.r4 -0.999
L_055e: bge.un Label 55
L_0563: ldc.i4.1
L_0564: stloc.s 5 (System.Boolean)
L_0566: br Label 56
L_056b: Label 55
L_056b: ldc.i4.1
L_056c: stloc.s 6 (System.Boolean)
L_056e: Label 54
L_056e: Label 56
L_056e: ldloc.s 32 (System.Boolean)
L_0570: ldloc.s 25 (System.Boolean)
L_0572: ceq
L_0574: ldc.i4.0
L_0575: ceq
L_0577: stloc.s 12 (System.Boolean)
L_0579: br Label 57
L_057e: Label 45
L_057e: Label 46
L_057e: Label 47
L_057e: Label 48
L_057e: Label 49
L_057e: ldc.i4.1
L_057f: stloc.s 9 (System.Boolean)
L_0581: Label 44
L_0581: Label 57
L_0581: ldloc.s 34 (NetInfo)
L_0583: stloc.s 16 (NetInfo)
L_0585: ldloc.s 36 (System.Int32)
L_0587: stloc.s 17 (System.Int32)
L_0589: ldloc.s 37 (System.Int32)
L_058b: stloc.s 18 (System.Int32)
L_058d: Label 11
L_058d: ldloc.s 26 (System.Int32)
L_058f: ldc.i4.1
L_0590: add
L_0591: stloc.s 26 (System.Int32)
L_0593: Label 10
L_0593: ldloc.s 26 (System.Int32)
L_0595: ldc.i4.8
L_0596: blt Label 58
L_059b: ldloc.s 19 (NetInfo)
L_059d: ldfld System.Boolean m_enableMiddleNodes
L_05a2: ldc.i4.0
L_05a3: ceq
L_05a5: ldloc.s 5 (System.Boolean)
L_05a7: and
L_05a8: brfalse Label 59
L_05ad: ldc.i4.1
L_05ae: stloc.s 6 (System.Boolean)
L_05b0: Label 59
L_05b0: ldloc.s 19 (NetInfo)
L_05b2: ldfld System.Boolean m_enableBendingNodes
L_05b7: ldc.i4.0
L_05b8: ceq
L_05ba: ldloc.s 6 (System.Boolean)
L_05bc: and
L_05bd: brfalse Label 60
L_05c2: ldc.i4.1
L_05c3: stloc.s 9 (System.Boolean)
L_05c5: Label 60
L_05c5: ldloc.s 19 (NetInfo)
L_05c7: ldfld System.Boolean m_requireContinuous
L_05cc: brfalse Label 61
L_05d1: ldarg.0
L_05d2: ldfld NetNode+Flags m_flags
L_05d7: ldc.i4 512
L_05dc: and
L_05dd: brfalse Label 62
L_05e2: ldc.i4.1
L_05e3: stloc.s 9 (System.Boolean)
L_05e5: Label 61
L_05e5: Label 62
L_05e5: ldloc.s 19 (NetInfo)
L_05e7: ldfld System.Boolean m_requireContinuous
L_05ec: brfalse Label 63
L_05f1: ldloc.s 12 (System.Boolean)
L_05f3: brtrue Label 64
L_05f8: ldloc.s 5 (System.Boolean)
L_05fa: brtrue Label 65
L_05ff: ldloc.s 6 (System.Boolean)
L_0601: brfalse Label 66
L_0606: Label 65
L_0606: ldc.i4.1
L_0607: stloc.s 9 (System.Boolean)
L_0609: Label 63
L_0609: Label 64
L_0609: Label 66
L_0609: ldarg.0
L_060a: ldfld NetNode+Flags m_flags
L_060f: ldc.i4 -1610613233
L_0614: and
L_0615: stloc.s 49 (NetNode+Flags)
L_0617: ldloc.s 49 (NetNode+Flags)
L_0619: ldc.i4 1024
L_061e: and
L_061f: brfalse Label 67
L_0624: ldarg.0
L_0625: ldloc.s 49 (NetNode+Flags)
L_0627: stfld NetNode+Flags m_flags
L_062c: br Label 68
L_0631: Label 67
L_0631: ldloc.s 9 (System.Boolean)
L_0633: brfalse Label 69
L_0638: ldarg.0
L_0639: ldloc.s 49 (NetNode+Flags)
L_063b: ldc.i4 128
L_0640: or
L_0641: stfld NetNode+Flags m_flags
L_0646: br Label 70
L_064b: Label 69
L_064b: ldloc.s 6 (System.Boolean)
L_064d: brfalse Label 71
L_0652: ldloc.s 7 (System.Boolean)
L_0654: brfalse Label 72
L_0659: ldloc.s 49 (NetNode+Flags)
L_065b: ldc.i4 536870912
L_0660: or
L_0661: stloc.s 49 (NetNode+Flags)
L_0663: Label 72
L_0663: ldloc.s 8 (System.Boolean)
L_0665: brfalse Label 73
L_066a: ldloc.s 49 (NetNode+Flags)
L_066c: ldc.i4 1073741824
L_0671: or
L_0672: stloc.s 49 (NetNode+Flags)
L_0674: Label 73
L_0674: ldarg.0
L_0675: ldloc.s 49 (NetNode+Flags)
L_0677: ldc.i4.s 64
L_0679: or
L_067a: stfld NetNode+Flags m_flags
L_067f: br Label 74
L_0684: Label 71
L_0684: ldloc.s 5 (System.Boolean)
L_0686: brfalse Label 75
L_068b: ldloc.s 10 (System.Boolean)
L_068d: brfalse Label 76
L_0692: ldloc.s 11 (System.Boolean)
L_0694: brtrue Label 77
L_0699: Label 76
L_0699: ldarg.0
L_069a: ldfld NetNode+Flags m_flags
L_069f: ldc.i4 4608
L_06a4: and
L_06a5: brtrue Label 78
L_06aa: ldloc.s 13 (System.Boolean)
L_06ac: brfalse Label 79
L_06b1: ldloc.s 14 (System.Boolean)
L_06b3: brfalse Label 80
L_06b8: ldloc.s 49 (NetNode+Flags)
L_06ba: ldc.i4 256
L_06bf: or
L_06c0: stloc.s 49 (NetNode+Flags)
L_06c2: Label 77
L_06c2: Label 78
L_06c2: Label 79
L_06c2: Label 80
L_06c2: ldarg.0
L_06c3: ldloc.s 49 (NetNode+Flags)
L_06c5: ldc.i4.s 32
L_06c7: or
L_06c8: stfld NetNode+Flags m_flags
L_06cd: br Label 81
L_06d2: Label 75
L_06d2: ldloc.s 4 (System.Boolean)
L_06d4: brfalse Label 82
L_06d9: ldarg.0
L_06da: ldfld NetNode+Flags m_flags
L_06df: ldc.i4 512
L_06e4: and
L_06e5: brtrue Label 83
L_06ea: ldloc.s 13 (System.Boolean)
L_06ec: brfalse Label 84
L_06f1: ldloc.s 14 (System.Boolean)
L_06f3: brfalse Label 85
L_06f8: ldloc.s 19 (NetInfo)
L_06fa: ldfld System.Boolean m_enableMiddleNodes
L_06ff: brfalse Label 86
L_0704: ldloc.s 49 (NetNode+Flags)
L_0706: ldc.i4 256
L_070b: or
L_070c: stloc.s 49 (NetNode+Flags)
L_070e: Label 83
L_070e: Label 84
L_070e: Label 85
L_070e: Label 86
L_070e: ldarg.0
L_070f: ldloc.s 49 (NetNode+Flags)
L_0711: ldc.i4.s 16
L_0713: or
L_0714: stfld NetNode+Flags m_flags
L_0719: Label 68
L_0719: Label 70
L_0719: Label 74
L_0719: Label 81
L_0719: Label 82
L_0719: ldarg.0
L_071a: ldloc.s 15 (System.Boolean)
L_071c: brtrue Label 87
L_0721: ldloc.s 19 (NetInfo)
L_0723: ldfld System.Boolean m_requireSurfaceMaps
L_0728: brtrue Label 88
L_072d: Label 87
L_072d: ldc.i4.0
L_072e: br Label 89
L_0733: Label 88
L_0733: ldc.i4.s 64
L_0735: Label 89
L_0735: conv.u1
L_0736: stfld System.Byte m_heightOffset
L_073b: ldarg.0
L_073c: ldloc.3
L_073d: conv.u1
L_073e: stfld System.Byte m_connectCount
L_0743: ldloc.s 19 (NetInfo)
L_0745: ldfld NetAI m_netAI
L_074a: ldarg.1
L_074b: ldarg.0
L_074c: ldloca.s 50 (BuildingInfo)
L_074e: ldloca.s 51 (System.Single)
L_0750: callvirt Void GetNodeBuilding(UInt16, NetNode ByRef, BuildingInfo ByRef, Single ByRef)
L_0755: ldarg.0
L_0756: ldarg.1
L_0757: ldloc.s 50 (BuildingInfo)
L_0759: ldloc.s 51 (System.Single)
L_075b: call Void UpdateBuilding(UInt16, BuildingInfo, Single)
L_0760: br Label 0
L_0765: Label 0
L_0765: ret

DONE

pardeike commented 7 years ago

Please add information about the method being patched as well as the used patch methods. Mainly the signatures.

Leigon commented 7 years ago
namespace TollRoad
{
    public class Node
    {
        public static void Hook()
        {
            try
            {
                // NetNode override
                //public void CalculateNode( ushort nodeID )
                var harmony = HarmonyInstance.Create( "com.leigon.cities_skylines.toll_road" );
                HarmonyInstance.DEBUG = true;

                MethodInfo targetmethod = AccessTools.Method( typeof( NetNode ), "CalculateNode" );
                HarmonyMethod prefixmethod = new HarmonyMethod( typeof( TollRoad.Node ).GetMethod( "CalculateNode_Prefix" ) );
                harmony.Patch( targetmethod, prefixmethod, null );
            }
            catch( System.Exception ex )
            {
                Logger.LogError( "Node", ex.ToString() );
            }
        }

        public static void CalculateNode_Prefix( NetNode __instance, ushort nodeID )
        {
            NetNode thisNode = NetManager.instance.m_nodes.m_buffer[ nodeID ];

            Logger.Log( "NetNode", "CalculateNode" );

            NetManager.instance.m_nodes.m_buffer[ nodeID ] = thisNode;
        }
    }
}

Reflection of prefixed mathod:

  public void CalculateNode(ushort nodeID)
  {
    if (this.m_flags == NetNode.Flags.None)
      return;
    NetManager instance = Singleton<NetManager>.instance;
    Vector3 vector3_1 = Vector3.zero;
    int num1 = 0;
    int num2 = 0;
    bool flag1 = false;
    bool flag2 = false;
    bool flag3 = false;
    bool flag4 = false;
    bool flag5 = false;
    bool flag6 = false;
    bool flag7 = false;
    bool flag8 = false;
    bool flag9 = false;
    bool flag10 = true;
    bool flag11 = true;
    bool flag12 = Singleton<TerrainManager>.instance.HasDetailMapping(this.m_position);
    NetInfo with1 = (NetInfo) null;
    int num3 = 0;
    int num4 = 0;
    NetInfo with2 = (NetInfo) null;
    float num5 = -1E+07f;
    for (int index = 0; index < 8; ++index)
    {
      ushort segment = this.GetSegment(index);
      if ((int) segment != 0)
      {
        NetInfo info = instance.m_segments.m_buffer[(int) segment].Info;
        float nodeInfoPriority = info.m_netAI.GetNodeInfoPriority(segment, ref instance.m_segments.m_buffer[(int) segment]);
        if ((double) nodeInfoPriority > (double) num5)
        {
          with2 = info;
          num5 = nodeInfoPriority;
        }
      }
    }
    if (with2 == null)
      with2 = this.Info;
    if (with2 != this.Info)
    {
      this.Info = with2;
      Singleton<NetManager>.instance.UpdateNodeColors(nodeID);
      if (!with2.m_canDisable)
        this.m_flags &= NetNode.Flags.OneWayOutTrafficLights | NetNode.Flags.UndergroundTransition | NetNode.Flags.Created | NetNode.Flags.Deleted | NetNode.Flags.Original | NetNode.Flags.End | NetNode.Flags.Middle | NetNode.Flags.Bend | NetNode.Flags.Junction | NetNode.Flags.Moveable | NetNode.Flags.Untouchable | NetNode.Flags.Outside | NetNode.Flags.Temporary | NetNode.Flags.Double | NetNode.Flags.Fixed | NetNode.Flags.OnGround | NetNode.Flags.Ambiguous | NetNode.Flags.Water | NetNode.Flags.Sewage | NetNode.Flags.ForbidLaneConnection | NetNode.Flags.LevelCrossing | NetNode.Flags.OneWayIn | NetNode.Flags.Heating | NetNode.Flags.Electricity | NetNode.Flags.Collapsed | NetNode.Flags.DisableOnlyMiddle | NetNode.Flags.AsymForward | NetNode.Flags.AsymBackward | NetNode.Flags.CustomTrafficLights;
    }
    bool flag13 = false;
    for (int index1 = 0; index1 < 8; ++index1)
    {
      ushort segment1 = this.GetSegment(index1);
      if ((int) segment1 != 0)
      {
        ++num1;
        ushort startNode = instance.m_segments.m_buffer[(int) segment1].m_startNode;
        ushort endNode = instance.m_segments.m_buffer[(int) segment1].m_endNode;
        Vector3 startDirection = instance.m_segments.m_buffer[(int) segment1].m_startDirection;
        Vector3 endDirection = instance.m_segments.m_buffer[(int) segment1].m_endDirection;
        bool flag14 = (int) nodeID == (int) startNode;
        Vector3 vector3_2 = !flag14 ? endDirection : startDirection;
        NetInfo info1 = instance.m_segments.m_buffer[(int) segment1].Info;
        ItemClass connectionClass = info1.GetConnectionClass();
        if (!info1.m_netAI.CanModify())
          flag11 = false;
        int vehicleLaneCount1;
        int vehicleLaneCount2;
        if (flag14 == ((instance.m_segments.m_buffer[(int) segment1].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None))
        {
          vehicleLaneCount1 = info1.m_backwardVehicleLaneCount;
          vehicleLaneCount2 = info1.m_forwardVehicleLaneCount;
        }
        else
        {
          vehicleLaneCount1 = info1.m_forwardVehicleLaneCount;
          vehicleLaneCount2 = info1.m_backwardVehicleLaneCount;
        }
        for (int index2 = index1 + 1; index2 < 8; ++index2)
        {
          ushort segment2 = this.GetSegment(index2);
          if ((int) segment2 != 0)
          {
            NetInfo info2 = instance.m_segments.m_buffer[(int) segment2].Info;
            if (info2.GetConnectionClass().m_service == connectionClass.m_service || (info2.m_nodeConnectGroups & info1.m_connectGroup) != NetInfo.ConnectGroup.None || (info1.m_nodeConnectGroups & info2.m_connectGroup) != NetInfo.ConnectGroup.None)
            {
              Vector3 vector3_3 = (int) nodeID != (int) instance.m_segments.m_buffer[(int) segment2].m_startNode ? instance.m_segments.m_buffer[(int) segment2].m_endDirection : instance.m_segments.m_buffer[(int) segment2].m_startDirection;
              if ((double) vector3_2.x * (double) vector3_3.x + (double) vector3_2.z * (double) vector3_3.z < (double) (0.01f - Mathf.Min(info1.m_maxTurnAngleCos, info2.m_maxTurnAngleCos)))
              {
                if (info1.m_requireDirectRenderers && (info1.m_nodeConnectGroups == NetInfo.ConnectGroup.None || (info1.m_nodeConnectGroups & info2.m_connectGroup) != NetInfo.ConnectGroup.None) || info2.m_requireDirectRenderers && (info2.m_nodeConnectGroups == NetInfo.ConnectGroup.None || (info2.m_nodeConnectGroups & info1.m_connectGroup) != NetInfo.ConnectGroup.None))
                  ++num2;
              }
              else
                flag6 = true;
            }
            else
              flag6 = true;
          }
        }
        if ((int) instance.m_nodes.m_buffer[(int) startNode].m_elevation != (int) instance.m_nodes.m_buffer[(int) endNode].m_elevation)
          flag10 = false;
        Vector3 position1 = instance.m_nodes.m_buffer[(int) startNode].m_position;
        Vector3 position2 = instance.m_nodes.m_buffer[(int) endNode].m_position;
        flag12 = !flag14 ? flag12 && Singleton<TerrainManager>.instance.HasDetailMapping(position1) : flag12 && Singleton<TerrainManager>.instance.HasDetailMapping(position2);
        if (NetSegment.IsStraight(position1, startDirection, position2, endDirection))
          flag8 = true;
        else
          flag7 = true;
        if (num1 == 1)
        {
          flag13 = flag14;
          vector3_1 = vector3_2;
          flag1 = true;
        }
        else if (num1 == 2 && info1.IsCombatible(with1) && (info1.IsCombatible(with2) && vehicleLaneCount1 != 0 == (num4 != 0)) && vehicleLaneCount2 != 0 == (num3 != 0))
        {
          float num6 = (float) ((double) vector3_1.x * (double) vector3_2.x + (double) vector3_1.z * (double) vector3_2.z);
          if (vehicleLaneCount1 != num4 || vehicleLaneCount2 != num3)
          {
            if (vehicleLaneCount1 > vehicleLaneCount2)
            {
              flag4 = true;
              flag3 = true;
            }
            else
            {
              flag5 = true;
              flag3 = true;
            }
          }
          else if ((double) num6 < -0.999000012874603)
            flag2 = true;
          else
            flag3 = true;
          flag9 = flag14 != flag13;
        }
        else
          flag6 = true;
        with1 = info1;
        num3 = vehicleLaneCount1;
        num4 = vehicleLaneCount2;
      }
    }
    if (!with2.m_enableMiddleNodes & flag2)
      flag3 = true;
    if (!with2.m_enableBendingNodes & flag3)
      flag6 = true;
    if (with2.m_requireContinuous && (this.m_flags & NetNode.Flags.Untouchable) != NetNode.Flags.None)
      flag6 = true;
    if (with2.m_requireContinuous && !flag9 && (flag2 || flag3))
      flag6 = true;
    NetNode.Flags flags = this.m_flags & (NetNode.Flags.OneWayOutTrafficLights | NetNode.Flags.UndergroundTransition | NetNode.Flags.Created | NetNode.Flags.Deleted | NetNode.Flags.Original | NetNode.Flags.Disabled | NetNode.Flags.Untouchable | NetNode.Flags.Outside | NetNode.Flags.Temporary | NetNode.Flags.Double | NetNode.Flags.Fixed | NetNode.Flags.OnGround | NetNode.Flags.Ambiguous | NetNode.Flags.Water | NetNode.Flags.Sewage | NetNode.Flags.ForbidLaneConnection | NetNode.Flags.LevelCrossing | NetNode.Flags.OneWayIn | NetNode.Flags.Heating | NetNode.Flags.Electricity | NetNode.Flags.Collapsed | NetNode.Flags.DisableOnlyMiddle | NetNode.Flags.CustomTrafficLights);
    if ((flags & NetNode.Flags.Outside) != NetNode.Flags.None)
      this.m_flags = flags;
    else if (flag6)
      this.m_flags = flags | NetNode.Flags.Junction;
    else if (flag3)
    {
      if (flag4)
        flags |= NetNode.Flags.AsymForward;
      if (flag5)
        flags |= NetNode.Flags.AsymBackward;
      this.m_flags = flags | NetNode.Flags.Bend;
    }
    else if (flag2)
    {
      if ((!flag7 || !flag8) && ((this.m_flags & (NetNode.Flags.Untouchable | NetNode.Flags.Double)) == NetNode.Flags.None && flag10) && flag11)
        flags |= NetNode.Flags.Moveable;
      this.m_flags = flags | NetNode.Flags.Middle;
    }
    else if (flag1)
    {
      if ((this.m_flags & NetNode.Flags.Untouchable) == NetNode.Flags.None && flag10 && (flag11 && with2.m_enableMiddleNodes))
        flags |= NetNode.Flags.Moveable;
      this.m_flags = flags | NetNode.Flags.End;
    }
    this.m_heightOffset = flag12 || !with2.m_requireSurfaceMaps ? (byte) 0 : (byte) 64;
    this.m_connectCount = (byte) num2;
    BuildingInfo building;
    float heightOffset;
    with2.m_netAI.GetNodeBuilding(nodeID, ref this, out building, out heightOffset);
    this.UpdateBuilding(nodeID, building, heightOffset);
  }
pardeike commented 7 years ago

Can you provide the IL code for the original method? Not necessarily the whole but mainly like +/- 10 lines around the calling for GetNodeBuilding to compare the IL code that Harmony spits out with the original IL code. Almost all problem can be examined by comparing the original IL code with the final Harmony result that is in the debug log.

Because currently, Harmony does not support TRY/CATCH on the IL level. And even if the decompiled code does not have a try/catch statement, the IL code can actually have it and right now, Harmony cannot handle the meta data of try/catch ranges and thus the corresponding IL codes will not work as expected. As a side result, a finally handler is not executed.

Leigon commented 7 years ago

Sure.

IL_06eb: ldfld bool NetInfo::m_enableMiddleNodes IL_06f0: brfalse IL_06ff IL_06f5: ldloc.s V_49 IL_06f7: ldc.i4 0x100 IL_06fc: or IL_06fd: stloc.s V_49 IL_06ff: ldarg.0 IL_0700: ldloc.s V_49 IL_0702: ldc.i4.s 16 IL_0704: or IL_0705: stfld valuetype NetNode/Flags NetNode::m_flags IL_070a: ldarg.0 IL_070b: ldloc.s V_15 IL_070d: brtrue IL_071e IL_0712: ldloc.s V_19 IL_0714: ldfld bool NetInfo::m_requireSurfaceMaps IL_0719: brtrue IL_0724 IL_071e: ldc.i4.0 IL_071f: br IL_0726 IL_0724: ldc.i4.s 64 IL_0726: conv.u1 IL_0727: stfld uint8 NetNode::m_heightOffset IL_072c: ldarg.0 IL_072d: ldloc.3 IL_072e: conv.u1 IL_072f: stfld uint8 NetNode::m_connectCount IL_0734: ldloc.s V_19 IL_0736: ldfld class NetAI NetInfo::m_netAI IL_073b: ldarg.1 IL_073c: ldarg.0 IL_073d: ldloca.s V_50 IL_073f: ldloca.s V_51 IL_0741: callvirt instance void NetAI::GetNodeBuilding(uint16, valuetype NetNode&, class BuildingInfo&, float32&) IL_0746: ldarg.0 IL_0747: ldarg.1 IL_0748: ldloc.s V_50 IL_074a: ldloc.s V_51 IL_074c: call instance void NetNode::UpdateBuilding(uint16, class BuildingInfo, float32) IL_0751: ret } // end of method NetNode::CalculateNode

Leigon commented 7 years ago

Hi @pardeike

Any luck with this? Thanks, -Adrian

pardeike commented 7 years ago

I only had a quick look but could not spot the problem right away. The thing is that this error is at a place where Harmony does not interface with the IL code much. It just copies it from the original. The only thing that might be unusual here is that it seems to be a ref this.

I have to look more into this. Meanwhile, would you be able to create a minimal test case to reproduce this? The method here is a bit too big to handle.

I am actively working on the next release that fixes a few things so the timing is right.

Thanks

pardeike commented 6 years ago

Can you please verify if this error persist with the latest master?

Leigon commented 6 years ago

Hi, sorry for not helping out with this, I have had a bit of real life issues.

With the latest master I get:

System.InvalidProgramException: Invalid IL code in (wrapper dynamic-method) NetNode:CalculateNode_Patch1 (object,uint16): IL_0007: call 0x00000001

at (wrapper managed-to-native) System.RuntimeMethodHandle:GetFunctionPointer (intptr) at System.RuntimeMethodHandle.GetFunctionPointer () [0x00000] in :0 at Harmony.ILCopying.Memory.GetMethodStart (System.Reflection.MethodBase method) [0x00000] in :0 at Harmony.PatchFunctions.UpdateWrapper (System.Reflection.MethodBase original, Harmony.PatchInfo patchInfo, System.String instanceID) [0x00000] in :0 at Harmony.PatchProcessor.Patch () [0x00000] in :0 at Harmony.HarmonyInstance.Patch (System.Reflection.MethodBase original, Harmony.HarmonyMethod prefix, Harmony.HarmonyMethod postfix, Harmony.HarmonyMethod transpiler) [0x00000] in :0 at TollRoad.Node.Hook () [0x00000] in :0

I assume my code is out of date?

using System.Reflection;
using System.Collections.Generic;
using UnityEngine;
using ColossalFramework;
using System;
using Harmony;
namespace TollRoad
{
    public class Node
    {
        public enum Flags
        {
            Toll = NetNode.Flags.Water
        }

        public static void Hook()
        {
            FileLog.logPath = "E:\\error.txt"; 
            try
            {
                // NetNode override
                //public void CalculateNode( ushort nodeID )
                var harmony = HarmonyInstance.Create( "com.leigon.cities_skylines.toll_road" );
                HarmonyInstance.DEBUG = true;

                MethodInfo targetmethod = AccessTools.Method( typeof( NetNode ), "CalculateNode" );
                HarmonyMethod prefixmethod = new HarmonyMethod( typeof( TollRoad.Node ).GetMethod( "CalculateNode_Prefix" ) );

                harmony.Patch( targetmethod, prefixmethod, null );
            }
            catch( System.Exception ex )
            {
                Logger.LogError( "Node", ex.ToString() );
                FileLog.Log( ex.ToString() );
            }
        }

        public static void CalculateNode_Prefix( NetNode __instance, ushort nodeID )
        {
            NetNode thisNode = NetManager.instance.m_nodes.m_buffer[ nodeID ];

            Logger.Log( "NetNode", "CalculateNode" );

            NetManager.instance.m_nodes.m_buffer[ nodeID ] = thisNode;
        }
    }
}
L_0000: Local var 0: NetManager
L_0000: Local var 1: UnityEngine.Vector3
L_0000: Local var 2: System.Int32
L_0000: Local var 3: System.Int32
L_0000: Local var 4: System.Boolean
L_0000: Local var 5: System.Boolean
L_0000: Local var 6: System.Boolean
L_0000: Local var 7: System.Boolean
L_0000: Local var 8: System.Boolean
L_0000: Local var 9: System.Boolean
L_0000: Local var 10: System.Boolean
L_0000: Local var 11: System.Boolean
L_0000: Local var 12: System.Boolean
L_0000: Local var 13: System.Boolean
L_0000: Local var 14: System.Boolean
L_0000: Local var 15: System.Boolean
L_0000: Local var 16: NetInfo
L_0000: Local var 17: System.Int32
L_0000: Local var 18: System.Int32
L_0000: Local var 19: NetInfo
L_0000: Local var 20: System.Single
L_0000: Local var 21: System.Int32
L_0000: Local var 22: System.UInt16
L_0000: Local var 23: NetInfo
L_0000: Local var 24: System.Single
L_0000: Local var 25: System.Boolean
L_0000: Local var 26: System.Int32
L_0000: Local var 27: System.UInt16
L_0000: Local var 28: System.UInt16
L_0000: Local var 29: System.UInt16
L_0000: Local var 30: UnityEngine.Vector3
L_0000: Local var 31: UnityEngine.Vector3
L_0000: Local var 32: System.Boolean
L_0000: Local var 33: UnityEngine.Vector3
L_0000: Local var 34: NetInfo
L_0000: Local var 35: ItemClass
L_0000: Local var 36: System.Int32
L_0000: Local var 37: System.Int32
L_0000: Local var 38: System.Int32
L_0000: Local var 39: System.UInt16
L_0000: Local var 40: NetInfo
L_0000: Local var 41: ItemClass
L_0000: Local var 42: System.Boolean
L_0000: Local var 43: UnityEngine.Vector3
L_0000: Local var 44: System.Single
L_0000: Local var 45: System.Single
L_0000: Local var 46: UnityEngine.Vector3
L_0000: Local var 47: UnityEngine.Vector3
L_0000: Local var 48: System.Single
L_0000: Local var 49: NetNode+Flags
L_0000: Local var 50: BuildingInfo
L_0000: Local var 51: System.Single
L_0000: ldarg.0
L_0001: ldarg 1
L_0007: call Void CalculateNode_Prefix(NetNode, UInt16)
L_000c: ldarg.0
L_000d: ldfld NetNode+Flags m_flags
L_0012: brtrue Label1
L_0017: br Label89
L_001c: Label1
L_001c: call NetManager get_instance()
L_0021: stloc.0
L_0022: call Vector3 get_zero()
L_0027: stloc.1
L_0028: ldc.i4.0
L_0029: stloc.2
L_002a: ldc.i4.0
L_002b: stloc.3
L_002c: ldc.i4.0
L_002d: stloc.s 4 (System.Boolean)
L_002f: ldc.i4.0
L_0030: stloc.s 5 (System.Boolean)
L_0032: ldc.i4.0
L_0033: stloc.s 6 (System.Boolean)
L_0035: ldc.i4.0
L_0036: stloc.s 7 (System.Boolean)
L_0038: ldc.i4.0
L_0039: stloc.s 8 (System.Boolean)
L_003b: ldc.i4.0
L_003c: stloc.s 9 (System.Boolean)
L_003e: ldc.i4.0
L_003f: stloc.s 10 (System.Boolean)
L_0041: ldc.i4.0
L_0042: stloc.s 11 (System.Boolean)
L_0044: ldc.i4.0
L_0045: stloc.s 12 (System.Boolean)
L_0047: ldc.i4.1
L_0048: stloc.s 13 (System.Boolean)
L_004a: ldc.i4.1
L_004b: stloc.s 14 (System.Boolean)
L_004d: call TerrainManager get_instance()
L_0052: ldarg.0
L_0053: ldfld UnityEngine.Vector3 m_position
L_0058: callvirt Boolean HasDetailMapping(Vector3)
L_005d: stloc.s 15 (System.Boolean)
L_005f: ldnull
L_0060: stloc.s 16 (NetInfo)
L_0062: ldc.i4.0
L_0063: stloc.s 17 (System.Int32)
L_0065: ldc.i4.0
L_0066: stloc.s 18 (System.Int32)
L_0068: ldnull
L_0069: stloc.s 19 (NetInfo)
L_006b: ldc.r4 -1E+07
L_0070: stloc.s 20 (System.Single)
L_0072: ldc.i4.0
L_0073: stloc.s 21 (System.Int32)
L_0075: br Label2
L_007a: Label5
L_007a: ldarg.0
L_007b: ldloc.s 21 (System.Int32)
L_007d: call UInt16 GetSegment(Int32)
L_0082: stloc.s 22 (System.UInt16)
L_0084: ldloc.s 22 (System.UInt16)
L_0086: brfalse Label3
L_008b: ldloc.0
L_008c: ldfld Array16`1[NetSegment] m_segments
L_0091: ldfld NetSegment[] m_buffer
L_0096: ldloc.s 22 (System.UInt16)
L_0098: ldelema NetSegment
L_009d: call NetInfo get_Info()
L_00a2: stloc.s 23 (NetInfo)
L_00a4: ldloc.s 23 (NetInfo)
L_00a6: ldfld NetAI m_netAI
L_00ab: ldloc.s 22 (System.UInt16)
L_00ad: ldloc.0
L_00ae: ldfld Array16`1[NetSegment] m_segments
L_00b3: ldfld NetSegment[] m_buffer
L_00b8: ldloc.s 22 (System.UInt16)
L_00ba: ldelema NetSegment
L_00bf: callvirt Single GetNodeInfoPriority(UInt16, NetSegment ByRef)
L_00c4: stloc.s 24 (System.Single)
L_00c6: ldloc.s 24 (System.Single)
L_00c8: ldloc.s 20 (System.Single)
L_00ca: ble.un Label4
L_00cf: ldloc.s 23 (NetInfo)
L_00d1: stloc.s 19 (NetInfo)
L_00d3: ldloc.s 24 (System.Single)
L_00d5: stloc.s 20 (System.Single)
L_00d7: Label3
L_00d7: Label4
L_00d7: ldloc.s 21 (System.Int32)
L_00d9: ldc.i4.1
L_00da: add
L_00db: stloc.s 21 (System.Int32)
L_00dd: Label2
L_00dd: ldloc.s 21 (System.Int32)
L_00df: ldc.i4.8
L_00e0: blt Label5
L_00e5: ldloc.s 19 (NetInfo)
L_00e7: brtrue Label6
L_00ec: ldarg.0
L_00ed: call NetInfo get_Info()
L_00f2: stloc.s 19 (NetInfo)
L_00f4: Label6
L_00f4: ldloc.s 19 (NetInfo)
L_00f6: ldarg.0
L_00f7: call NetInfo get_Info()
L_00fc: beq Label7
L_0101: ldarg.0
L_0102: ldloc.s 19 (NetInfo)
L_0104: call Void set_Info(NetInfo)
L_0109: call NetManager get_instance()
L_010e: ldarg.1
L_010f: callvirt Void UpdateNodeColors(UInt16)
L_0114: ldloc.s 19 (NetInfo)
L_0116: ldfld System.Boolean m_canDisable
L_011b: brtrue Label8
L_0120: ldarg.0
L_0121: dup
L_0122: ldfld NetNode+Flags m_flags
L_0127: ldc.i4.s -9
L_0129: and
L_012a: stfld NetNode+Flags m_flags
L_012f: Label7
L_012f: Label8
L_012f: ldc.i4.0
L_0130: stloc.s 25 (System.Boolean)
L_0132: ldc.i4.0
L_0133: stloc.s 26 (System.Int32)
L_0135: br Label9
L_013a: Label57
L_013a: ldarg.0
L_013b: ldloc.s 26 (System.Int32)
L_013d: call UInt16 GetSegment(Int32)
L_0142: stloc.s 27 (System.UInt16)
L_0144: ldloc.s 27 (System.UInt16)
L_0146: brfalse Label10
L_014b: ldloc.2
L_014c: ldc.i4.1
L_014d: add
L_014e: stloc.2
L_014f: ldloc.0
L_0150: ldfld Array16`1[NetSegment] m_segments
L_0155: ldfld NetSegment[] m_buffer
L_015a: ldloc.s 27 (System.UInt16)
L_015c: ldelema NetSegment
L_0161: ldfld System.UInt16 m_startNode
L_0166: stloc.s 28 (System.UInt16)
L_0168: ldloc.0
L_0169: ldfld Array16`1[NetSegment] m_segments
L_016e: ldfld NetSegment[] m_buffer
L_0173: ldloc.s 27 (System.UInt16)
L_0175: ldelema NetSegment
L_017a: ldfld System.UInt16 m_endNode
L_017f: stloc.s 29 (System.UInt16)
L_0181: ldloc.0
L_0182: ldfld Array16`1[NetSegment] m_segments
L_0187: ldfld NetSegment[] m_buffer
L_018c: ldloc.s 27 (System.UInt16)
L_018e: ldelema NetSegment
L_0193: ldfld UnityEngine.Vector3 m_startDirection
L_0198: stloc.s 30 (UnityEngine.Vector3)
L_019a: ldloc.0
L_019b: ldfld Array16`1[NetSegment] m_segments
L_01a0: ldfld NetSegment[] m_buffer
L_01a5: ldloc.s 27 (System.UInt16)
L_01a7: ldelema NetSegment
L_01ac: ldfld UnityEngine.Vector3 m_endDirection
L_01b1: stloc.s 31 (UnityEngine.Vector3)
L_01b3: ldarg.1
L_01b4: ldloc.s 28 (System.UInt16)
L_01b6: ceq
L_01b8: stloc.s 32 (System.Boolean)
L_01ba: ldloc.s 32 (System.Boolean)
L_01bc: brfalse Label11
L_01c1: ldloc.s 30 (UnityEngine.Vector3)
L_01c3: br Label12
L_01c8: Label11
L_01c8: ldloc.s 31 (UnityEngine.Vector3)
L_01ca: Label12
L_01ca: stloc.s 33 (UnityEngine.Vector3)
L_01cc: ldloc.0
L_01cd: ldfld Array16`1[NetSegment] m_segments
L_01d2: ldfld NetSegment[] m_buffer
L_01d7: ldloc.s 27 (System.UInt16)
L_01d9: ldelema NetSegment
L_01de: call NetInfo get_Info()
L_01e3: stloc.s 34 (NetInfo)
L_01e5: ldloc.s 34 (NetInfo)
L_01e7: callvirt ItemClass GetConnectionClass()
L_01ec: stloc.s 35 (ItemClass)
L_01ee: ldloc.s 34 (NetInfo)
L_01f0: ldfld NetAI m_netAI
L_01f5: callvirt Boolean CanModify()
L_01fa: brtrue Label13
L_01ff: ldc.i4.0
L_0200: stloc.s 14 (System.Boolean)
L_0202: Label13
L_0202: ldloc.s 32 (System.Boolean)
L_0204: ldloc.0
L_0205: ldfld Array16`1[NetSegment] m_segments
L_020a: ldfld NetSegment[] m_buffer
L_020f: ldloc.s 27 (System.UInt16)
L_0211: ldelema NetSegment
L_0216: ldfld NetSegment+Flags m_flags
L_021b: ldc.i4.s 16
L_021d: and
L_021e: ldc.i4.0
L_021f: ceq
L_0221: ldc.i4.0
L_0222: ceq
L_0224: bne.un Label14
L_0229: ldloc.s 34 (NetInfo)
L_022b: ldfld System.Int32 m_backwardVehicleLaneCount
L_0230: stloc.s 36 (System.Int32)
L_0232: ldloc.s 34 (NetInfo)
L_0234: ldfld System.Int32 m_forwardVehicleLaneCount
L_0239: stloc.s 37 (System.Int32)
L_023b: br Label15
L_0240: Label14
L_0240: ldloc.s 34 (NetInfo)
L_0242: ldfld System.Int32 m_forwardVehicleLaneCount
L_0247: stloc.s 36 (System.Int32)
L_0249: ldloc.s 34 (NetInfo)
L_024b: ldfld System.Int32 m_backwardVehicleLaneCount
L_0250: stloc.s 37 (System.Int32)
L_0252: Label15
L_0252: ldloc.s 26 (System.Int32)
L_0254: ldc.i4.1
L_0255: add
L_0256: stloc.s 38 (System.Int32)
L_0258: br Label16
L_025d: Label32
L_025d: ldarg.0
L_025e: ldloc.s 38 (System.Int32)
L_0260: call UInt16 GetSegment(Int32)
L_0265: stloc.s 39 (System.UInt16)
L_0267: ldloc.s 39 (System.UInt16)
L_0269: brfalse Label17
L_026e: ldloc.0
L_026f: ldfld Array16`1[NetSegment] m_segments
L_0274: ldfld NetSegment[] m_buffer
L_0279: ldloc.s 39 (System.UInt16)
L_027b: ldelema NetSegment
L_0280: call NetInfo get_Info()
L_0285: stloc.s 40 (NetInfo)
L_0287: ldloc.s 40 (NetInfo)
L_0289: callvirt ItemClass GetConnectionClass()
L_028e: stloc.s 41 (ItemClass)
L_0290: ldloc.s 41 (ItemClass)
L_0292: ldfld ItemClass+Service m_service
L_0297: ldloc.s 35 (ItemClass)
L_0299: ldfld ItemClass+Service m_service
L_029e: beq Label18
L_02a3: ldloc.s 40 (NetInfo)
L_02a5: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_02aa: ldloc.s 34 (NetInfo)
L_02ac: ldfld NetInfo+ConnectGroup m_connectGroup
L_02b1: and
L_02b2: brtrue Label19
L_02b7: ldloc.s 34 (NetInfo)
L_02b9: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_02be: ldloc.s 40 (NetInfo)
L_02c0: ldfld NetInfo+ConnectGroup m_connectGroup
L_02c5: and
L_02c6: brfalse Label20
L_02cb: Label18
L_02cb: Label19
L_02cb: ldarg.1
L_02cc: ldloc.0
L_02cd: ldfld Array16`1[NetSegment] m_segments
L_02d2: ldfld NetSegment[] m_buffer
L_02d7: ldloc.s 39 (System.UInt16)
L_02d9: ldelema NetSegment
L_02de: ldfld System.UInt16 m_startNode
L_02e3: ceq
L_02e5: stloc.s 42 (System.Boolean)
L_02e7: ldloc.s 42 (System.Boolean)
L_02e9: brfalse Label21
L_02ee: ldloc.0
L_02ef: ldfld Array16`1[NetSegment] m_segments
L_02f4: ldfld NetSegment[] m_buffer
L_02f9: ldloc.s 39 (System.UInt16)
L_02fb: ldelema NetSegment
L_0300: ldfld UnityEngine.Vector3 m_startDirection
L_0305: br Label22
L_030a: Label21
L_030a: ldloc.0
L_030b: ldfld Array16`1[NetSegment] m_segments
L_0310: ldfld NetSegment[] m_buffer
L_0315: ldloc.s 39 (System.UInt16)
L_0317: ldelema NetSegment
L_031c: ldfld UnityEngine.Vector3 m_endDirection
L_0321: Label22
L_0321: stloc.s 43 (UnityEngine.Vector3)
L_0323: ldloca.s 33 (UnityEngine.Vector3)
L_0325: ldfld System.Single x
L_032a: ldloca.s 43 (UnityEngine.Vector3)
L_032c: ldfld System.Single x
L_0331: mul
L_0332: ldloca.s 33 (UnityEngine.Vector3)
L_0334: ldfld System.Single z
L_0339: ldloca.s 43 (UnityEngine.Vector3)
L_033b: ldfld System.Single z
L_0340: mul
L_0341: add
L_0342: stloc.s 44 (System.Single)
L_0344: ldc.r4 0.01
L_0349: ldloc.s 34 (NetInfo)
L_034b: ldfld System.Single m_maxTurnAngleCos
L_0350: ldloc.s 40 (NetInfo)
L_0352: ldfld System.Single m_maxTurnAngleCos
L_0357: call Single Min(Single, Single)
L_035c: sub
L_035d: stloc.s 45 (System.Single)
L_035f: ldloc.s 44 (System.Single)
L_0361: ldloc.s 45 (System.Single)
L_0363: bge.un Label23
L_0368: ldloc.s 34 (NetInfo)
L_036a: ldfld System.Boolean m_requireDirectRenderers
L_036f: brfalse Label24
L_0374: ldloc.s 34 (NetInfo)
L_0376: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_037b: brfalse Label25
L_0380: ldloc.s 34 (NetInfo)
L_0382: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_0387: ldloc.s 40 (NetInfo)
L_0389: ldfld NetInfo+ConnectGroup m_connectGroup
L_038e: and
L_038f: brtrue Label26
L_0394: Label24
L_0394: ldloc.s 40 (NetInfo)
L_0396: ldfld System.Boolean m_requireDirectRenderers
L_039b: brfalse Label27
L_03a0: ldloc.s 40 (NetInfo)
L_03a2: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_03a7: brfalse Label28
L_03ac: ldloc.s 40 (NetInfo)
L_03ae: ldfld NetInfo+ConnectGroup m_nodeConnectGroups
L_03b3: ldloc.s 34 (NetInfo)
L_03b5: ldfld NetInfo+ConnectGroup m_connectGroup
L_03ba: and
L_03bb: brfalse Label29
L_03c0: Label25
L_03c0: Label26
L_03c0: Label28
L_03c0: ldloc.3
L_03c1: ldc.i4.1
L_03c2: add
L_03c3: stloc.3
L_03c4: Label27
L_03c4: Label29
L_03c4: br Label30
L_03c9: Label23
L_03c9: ldc.i4.1
L_03ca: stloc.s 9 (System.Boolean)
L_03cc: Label30
L_03cc: br Label31
L_03d1: Label20
L_03d1: ldc.i4.1
L_03d2: stloc.s 9 (System.Boolean)
L_03d4: Label17
L_03d4: Label31
L_03d4: ldloc.s 38 (System.Int32)
L_03d6: ldc.i4.1
L_03d7: add
L_03d8: stloc.s 38 (System.Int32)
L_03da: Label16
L_03da: ldloc.s 38 (System.Int32)
L_03dc: ldc.i4.8
L_03dd: blt Label32
L_03e2: ldloc.0
L_03e3: ldfld Array16`1[NetNode] m_nodes
L_03e8: ldfld NetNode[] m_buffer
L_03ed: ldloc.s 28 (System.UInt16)
L_03ef: ldelema NetNode
L_03f4: ldfld System.Byte m_elevation
L_03f9: ldloc.0
L_03fa: ldfld Array16`1[NetNode] m_nodes
L_03ff: ldfld NetNode[] m_buffer
L_0404: ldloc.s 29 (System.UInt16)
L_0406: ldelema NetNode
L_040b: ldfld System.Byte m_elevation
L_0410: beq Label33
L_0415: ldc.i4.0
L_0416: stloc.s 13 (System.Boolean)
L_0418: Label33
L_0418: ldloc.0
L_0419: ldfld Array16`1[NetNode] m_nodes
L_041e: ldfld NetNode[] m_buffer
L_0423: ldloc.s 28 (System.UInt16)
L_0425: ldelema NetNode
L_042a: ldfld UnityEngine.Vector3 m_position
L_042f: stloc.s 46 (UnityEngine.Vector3)
L_0431: ldloc.0
L_0432: ldfld Array16`1[NetNode] m_nodes
L_0437: ldfld NetNode[] m_buffer
L_043c: ldloc.s 29 (System.UInt16)
L_043e: ldelema NetNode
L_0443: ldfld UnityEngine.Vector3 m_position
L_0448: stloc.s 47 (UnityEngine.Vector3)
L_044a: ldloc.s 32 (System.Boolean)
L_044c: brfalse Label34
L_0451: ldloc.s 15 (System.Boolean)
L_0453: brfalse Label35
L_0458: call TerrainManager get_instance()
L_045d: ldloc.s 47 (UnityEngine.Vector3)
L_045f: callvirt Boolean HasDetailMapping(Vector3)
L_0464: br Label36
L_0469: Label35
L_0469: ldc.i4.0
L_046a: Label36
L_046a: stloc.s 15 (System.Boolean)
L_046c: br Label37
L_0471: Label34
L_0471: ldloc.s 15 (System.Boolean)
L_0473: brfalse Label38
L_0478: call TerrainManager get_instance()
L_047d: ldloc.s 46 (UnityEngine.Vector3)
L_047f: callvirt Boolean HasDetailMapping(Vector3)
L_0484: br Label39
L_0489: Label38
L_0489: ldc.i4.0
L_048a: Label39
L_048a: stloc.s 15 (System.Boolean)
L_048c: Label37
L_048c: ldloc.s 46 (UnityEngine.Vector3)
L_048e: ldloc.s 30 (UnityEngine.Vector3)
L_0490: ldloc.s 47 (UnityEngine.Vector3)
L_0492: ldloc.s 31 (UnityEngine.Vector3)
L_0494: call Boolean IsStraight(Vector3, Vector3, Vector3, Vector3)
L_0499: brfalse Label40
L_049e: ldc.i4.1
L_049f: stloc.s 11 (System.Boolean)
L_04a1: br Label41
L_04a6: Label40
L_04a6: ldc.i4.1
L_04a7: stloc.s 10 (System.Boolean)
L_04a9: Label41
L_04a9: ldloc.2
L_04aa: ldc.i4.1
L_04ab: bne.un Label42
L_04b0: ldloc.s 32 (System.Boolean)
L_04b2: stloc.s 25 (System.Boolean)
L_04b4: ldloc.s 33 (UnityEngine.Vector3)
L_04b6: stloc.1
L_04b7: ldc.i4.1
L_04b8: stloc.s 4 (System.Boolean)
L_04ba: br Label43
L_04bf: Label42
L_04bf: ldloc.2
L_04c0: ldc.i4.2
L_04c1: bne.un Label44
L_04c6: ldloc.s 34 (NetInfo)
L_04c8: ldloc.s 16 (NetInfo)
L_04ca: callvirt Boolean IsCombatible(NetInfo)
L_04cf: brfalse Label45
L_04d4: ldloc.s 34 (NetInfo)
L_04d6: ldloc.s 19 (NetInfo)
L_04d8: callvirt Boolean IsCombatible(NetInfo)
L_04dd: brfalse Label46
L_04e2: ldloc.s 36 (System.Int32)
L_04e4: ldc.i4.0
L_04e5: ceq
L_04e7: ldc.i4.0
L_04e8: ceq
L_04ea: ldloc.s 18 (System.Int32)
L_04ec: ldc.i4.0
L_04ed: ceq
L_04ef: ldc.i4.0
L_04f0: ceq
L_04f2: bne.un Label47
L_04f7: ldloc.s 37 (System.Int32)
L_04f9: ldc.i4.0
L_04fa: ceq
L_04fc: ldc.i4.0
L_04fd: ceq
L_04ff: ldloc.s 17 (System.Int32)
L_0501: ldc.i4.0
L_0502: ceq
L_0504: ldc.i4.0
L_0505: ceq
L_0507: bne.un Label48
L_050c: ldloca.s 1 (UnityEngine.Vector3)
L_050e: ldfld System.Single x
L_0513: ldloca.s 33 (UnityEngine.Vector3)
L_0515: ldfld System.Single x
L_051a: mul
L_051b: ldloca.s 1 (UnityEngine.Vector3)
L_051d: ldfld System.Single z
L_0522: ldloca.s 33 (UnityEngine.Vector3)
L_0524: ldfld System.Single z
L_0529: mul
L_052a: add
L_052b: stloc.s 48 (System.Single)
L_052d: ldloc.s 36 (System.Int32)
L_052f: ldloc.s 18 (System.Int32)
L_0531: bne.un Label49
L_0536: ldloc.s 37 (System.Int32)
L_0538: ldloc.s 17 (System.Int32)
L_053a: beq Label50
L_053f: Label49
L_053f: ldloc.s 36 (System.Int32)
L_0541: ldloc.s 37 (System.Int32)
L_0543: ble Label51
L_0548: ldc.i4.1
L_0549: stloc.s 7 (System.Boolean)
L_054b: ldc.i4.1
L_054c: stloc.s 6 (System.Boolean)
L_054e: br Label52
L_0553: Label51
L_0553: ldc.i4.1
L_0554: stloc.s 8 (System.Boolean)
L_0556: ldc.i4.1
L_0557: stloc.s 6 (System.Boolean)
L_0559: Label52
L_0559: br Label53
L_055e: Label50
L_055e: ldloc.s 48 (System.Single)
L_0560: ldc.r4 -0.999
L_0565: bge.un Label54
L_056a: ldc.i4.1
L_056b: stloc.s 5 (System.Boolean)
L_056d: br Label55
L_0572: Label54
L_0572: ldc.i4.1
L_0573: stloc.s 6 (System.Boolean)
L_0575: Label53
L_0575: Label55
L_0575: ldloc.s 32 (System.Boolean)
L_0577: ldloc.s 25 (System.Boolean)
L_0579: ceq
L_057b: ldc.i4.0
L_057c: ceq
L_057e: stloc.s 12 (System.Boolean)
L_0580: br Label56
L_0585: Label44
L_0585: Label45
L_0585: Label46
L_0585: Label47
L_0585: Label48
L_0585: ldc.i4.1
L_0586: stloc.s 9 (System.Boolean)
L_0588: Label43
L_0588: Label56
L_0588: ldloc.s 34 (NetInfo)
L_058a: stloc.s 16 (NetInfo)
L_058c: ldloc.s 36 (System.Int32)
L_058e: stloc.s 17 (System.Int32)
L_0590: ldloc.s 37 (System.Int32)
L_0592: stloc.s 18 (System.Int32)
L_0594: Label10
L_0594: ldloc.s 26 (System.Int32)
L_0596: ldc.i4.1
L_0597: add
L_0598: stloc.s 26 (System.Int32)
L_059a: Label9
L_059a: ldloc.s 26 (System.Int32)
L_059c: ldc.i4.8
L_059d: blt Label57
L_05a2: ldloc.s 19 (NetInfo)
L_05a4: ldfld System.Boolean m_enableMiddleNodes
L_05a9: ldc.i4.0
L_05aa: ceq
L_05ac: ldloc.s 5 (System.Boolean)
L_05ae: and
L_05af: brfalse Label58
L_05b4: ldc.i4.1
L_05b5: stloc.s 6 (System.Boolean)
L_05b7: Label58
L_05b7: ldloc.s 19 (NetInfo)
L_05b9: ldfld System.Boolean m_enableBendingNodes
L_05be: ldc.i4.0
L_05bf: ceq
L_05c1: ldloc.s 6 (System.Boolean)
L_05c3: and
L_05c4: brfalse Label59
L_05c9: ldc.i4.1
L_05ca: stloc.s 9 (System.Boolean)
L_05cc: Label59
L_05cc: ldloc.s 19 (NetInfo)
L_05ce: ldfld System.Boolean m_requireContinuous
L_05d3: brfalse Label60
L_05d8: ldarg.0
L_05d9: ldfld NetNode+Flags m_flags
L_05de: ldc.i4 512
L_05e3: and
L_05e4: brfalse Label61
L_05e9: ldc.i4.1
L_05ea: stloc.s 9 (System.Boolean)
L_05ec: Label60
L_05ec: Label61
L_05ec: ldloc.s 19 (NetInfo)
L_05ee: ldfld System.Boolean m_requireContinuous
L_05f3: brfalse Label62
L_05f8: ldloc.s 12 (System.Boolean)
L_05fa: brtrue Label63
L_05ff: ldloc.s 5 (System.Boolean)
L_0601: brtrue Label64
L_0606: ldloc.s 6 (System.Boolean)
L_0608: brfalse Label65
L_060d: Label64
L_060d: ldc.i4.1
L_060e: stloc.s 9 (System.Boolean)
L_0610: Label62
L_0610: Label63
L_0610: Label65
L_0610: ldarg.0
L_0611: ldfld NetNode+Flags m_flags
L_0616: ldc.i4 -1610613233
L_061b: and
L_061c: stloc.s 49 (NetNode+Flags)
L_061e: ldloc.s 49 (NetNode+Flags)
L_0620: ldc.i4 1024
L_0625: and
L_0626: brfalse Label66
L_062b: ldarg.0
L_062c: ldloc.s 49 (NetNode+Flags)
L_062e: stfld NetNode+Flags m_flags
L_0633: br Label67
L_0638: Label66
L_0638: ldloc.s 9 (System.Boolean)
L_063a: brfalse Label68
L_063f: ldarg.0
L_0640: ldloc.s 49 (NetNode+Flags)
L_0642: ldc.i4 128
L_0647: or
L_0648: stfld NetNode+Flags m_flags
L_064d: br Label69
L_0652: Label68
L_0652: ldloc.s 6 (System.Boolean)
L_0654: brfalse Label70
L_0659: ldloc.s 7 (System.Boolean)
L_065b: brfalse Label71
L_0660: ldloc.s 49 (NetNode+Flags)
L_0662: ldc.i4 536870912
L_0667: or
L_0668: stloc.s 49 (NetNode+Flags)
L_066a: Label71
L_066a: ldloc.s 8 (System.Boolean)
L_066c: brfalse Label72
L_0671: ldloc.s 49 (NetNode+Flags)
L_0673: ldc.i4 1073741824
L_0678: or
L_0679: stloc.s 49 (NetNode+Flags)
L_067b: Label72
L_067b: ldarg.0
L_067c: ldloc.s 49 (NetNode+Flags)
L_067e: ldc.i4.s 64
L_0680: or
L_0681: stfld NetNode+Flags m_flags
L_0686: br Label73
L_068b: Label70
L_068b: ldloc.s 5 (System.Boolean)
L_068d: brfalse Label74
L_0692: ldloc.s 10 (System.Boolean)
L_0694: brfalse Label75
L_0699: ldloc.s 11 (System.Boolean)
L_069b: brtrue Label76
L_06a0: Label75
L_06a0: ldarg.0
L_06a1: ldfld NetNode+Flags m_flags
L_06a6: ldc.i4 4608
L_06ab: and
L_06ac: brtrue Label77
L_06b1: ldloc.s 13 (System.Boolean)
L_06b3: brfalse Label78
L_06b8: ldloc.s 14 (System.Boolean)
L_06ba: brfalse Label79
L_06bf: ldloc.s 49 (NetNode+Flags)
L_06c1: ldc.i4 256
L_06c6: or
L_06c7: stloc.s 49 (NetNode+Flags)
L_06c9: Label76
L_06c9: Label77
L_06c9: Label78
L_06c9: Label79
L_06c9: ldarg.0
L_06ca: ldloc.s 49 (NetNode+Flags)
L_06cc: ldc.i4.s 32
L_06ce: or
L_06cf: stfld NetNode+Flags m_flags
L_06d4: br Label80
L_06d9: Label74
L_06d9: ldloc.s 4 (System.Boolean)
L_06db: brfalse Label81
L_06e0: ldarg.0
L_06e1: ldfld NetNode+Flags m_flags
L_06e6: ldc.i4 512
L_06eb: and
L_06ec: brtrue Label82
L_06f1: ldloc.s 13 (System.Boolean)
L_06f3: brfalse Label83
L_06f8: ldloc.s 14 (System.Boolean)
L_06fa: brfalse Label84
L_06ff: ldloc.s 19 (NetInfo)
L_0701: ldfld System.Boolean m_enableMiddleNodes
L_0706: brfalse Label85
L_070b: ldloc.s 49 (NetNode+Flags)
L_070d: ldc.i4 256
L_0712: or
L_0713: stloc.s 49 (NetNode+Flags)
L_0715: Label82
L_0715: Label83
L_0715: Label84
L_0715: Label85
L_0715: ldarg.0
L_0716: ldloc.s 49 (NetNode+Flags)
L_0718: ldc.i4.s 16
L_071a: or
L_071b: stfld NetNode+Flags m_flags
L_0720: Label67
L_0720: Label69
L_0720: Label73
L_0720: Label80
L_0720: Label81
L_0720: ldarg.0
L_0721: ldloc.s 15 (System.Boolean)
L_0723: brtrue Label86
L_0728: ldloc.s 19 (NetInfo)
L_072a: ldfld System.Boolean m_requireSurfaceMaps
L_072f: brtrue Label87
L_0734: Label86
L_0734: ldc.i4.0
L_0735: br Label88
L_073a: Label87
L_073a: ldc.i4.s 64
L_073c: Label88
L_073c: conv.u1
L_073d: stfld System.Byte m_heightOffset
L_0742: ldarg.0
L_0743: ldloc.3
L_0744: conv.u1
L_0745: stfld System.Byte m_connectCount
L_074a: ldloc.s 19 (NetInfo)
L_074c: ldfld NetAI m_netAI
L_0751: ldarg.1
L_0752: ldarg.0
L_0753: ldloca.s 50 (BuildingInfo)
L_0755: ldloca.s 51 (System.Single)
L_0757: callvirt Void GetNodeBuilding(UInt16, NetNode ByRef, BuildingInfo ByRef, Single ByRef)
L_075c: ldarg.0
L_075d: ldarg.1
L_075e: ldloc.s 50 (BuildingInfo)
L_0760: ldloc.s 51 (System.Single)
L_0762: call Void UpdateBuilding(UInt16, BuildingInfo, Single)
L_0767: Label89
L_0767: ret
DONE
pardeike commented 6 years ago

I have no idea why the IL code at 0007 is illegal. It is the call to your prefix method. That method is static and takes two parameters: NetNode __instance and ushort nodeID and both are loaded onto the stack with the IL commands before: L_0000: ldarg.0 and L_0001: ldarg 1. That makes sense if the original method is an instance method of NetNode. Because the 0th argument is the instance (NetNode) and the 1st argument will be the argument to the method, in this case the nodeID.

Could it be that the nodeID of the original is not the same type as in your patch? I can see of the debug log that Harmony says uint16 but you are using a ushort.

pardeike commented 6 years ago

On a second thought, I think it has to do with the type of NetNode. Can you post the definition?

Leigon commented 6 years ago
#region Assembly Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// steamapps\common\Cities_Skylines\Cities_Data\Managed\Assembly-CSharp.dll
#endregion

using System;
using ColossalFramework.Math;
using UnityEngine;

public struct NetNode
{
    public Notification.Problem m_problems;
    public byte m_maxWaitTime;
    public byte m_connectCount;
    public byte m_heightOffset;
    public byte m_elevation;
    public byte m_laneOffset;
    public ushort m_infoIndex;
    public ushort m_finalCounter;
    public ushort m_tempCounter;
    public ushort m_nextGridNode;
    public ushort m_nextBuildingNode;
    public ushort m_nextLaneNode;
    public ushort m_transportLine;
    public ushort m_building;
    public byte m_coverage;
    public ushort m_segment6;
    public Bounds m_bounds;
    public Vector3 m_position;
    public uint m_buildIndex;
    public uint m_lane;
    public ushort m_segment0;
    public Flags m_flags;
    public ushort m_segment2;
    public ushort m_segment3;
    public ushort m_segment4;
    public ushort m_segment5;
    public ushort m_segment1;
    public ushort m_segment7;

    public NetInfo Info { get; set; }

    public static bool BlendJunction( ushort nodeID );
    public static void CalculateGroupData( NetInfo.Node nodeInfo, ref int vertexCount, ref int triangleCount, ref int objectCount, ref RenderGroup.VertexArrays vertexArrays );
    public static ushort FindOwnerBuilding( ushort nodeID, float maxDistance );
    public static void PopulateGroupData( NetInfo info, NetInfo.Node nodeInfo, Matrix4x4 leftMatrix, Matrix4x4 rightMatrix, Vector4 meshScale, Vector4 objectIndex, ref int vertexIndex, ref int triangleIndex, RenderGroup.MeshData data, ref bool requireSurfaceMaps );
    public static void PopulateGroupData( NetInfo info, NetInfo.Node nodeInfo, Matrix4x4 leftMatrix, Matrix4x4 rightMatrix, Matrix4x4 leftMatrixB, Matrix4x4 rightMatrixB, Vector4 meshScale, Vector4 centerPos, Vector4 sideScale, Vector4 objectIndex, ref int vertexIndex, ref int triangleIndex, RenderGroup.MeshData data, ref bool requireSurfaceMaps );
    public static void RenderLod( RenderManager.CameraInfo cameraInfo, NetInfo.LodValue lod );
    public bool AddSegment( ushort segment );
    public void AfterTerrainUpdate( ushort nodeID, float minX, float minZ, float maxX, float maxZ );
    public bool CalculateGroupData( ushort nodeID, int layer, ref int vertexCount, ref int triangleCount, ref int objectCount, ref RenderGroup.VertexArrays vertexArrays );
    public void CalculateNode( ushort nodeID );
    public void CountLanes( ushort nodeID, ushort ignoreSegment, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, bool onePerSegment, ref int forward, ref int backward );
    public void CountLanes( ushort nodeID, ushort ignoreSegment, NetInfo.Direction directions, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, Vector3 direction, ref int left, ref int forward, ref int right, ref int left2, ref int forward2, ref int right2 );
    public int CountSegments();
    public int CountSegments( NetSegment.Flags flags, ushort ignoreSegment );
    public ushort GetSegment( int index );
    public bool IsConnectedTo( ushort node );
    public bool IsConnectedTo( ushort node1, ushort node2 );
    public void PopulateGroupData( ushort nodeID, int groupX, int groupZ, int layer, ref int vertexIndex, ref int triangleIndex, Vector3 groupPosition, RenderGroup.MeshData data, ref Vector3 min, ref Vector3 max, ref float maxRenderDistance, ref float maxInstanceDistance, ref bool requireSurfaceMaps );
    public bool RayCast( Segment3 ray, float snapElevation, out float t, out float priority );
    public bool RemoveSegment( ushort segment );
    public void RenderInstance( RenderManager.CameraInfo cameraInfo, ushort nodeID, int layerMask );
    public void TerrainUpdated( ushort nodeID, float minX, float minZ, float maxX, float maxZ );
    public void UpdateBounds( ushort nodeID );
    public void UpdateBuilding( ushort nodeID, BuildingInfo newBuilding, float heightOffset );
    public void UpdateLaneConnection( ushort nodeID );
    public void UpdateNode( ushort nodeID );

    [Flags]
    public enum Flags
    {
        CustomTrafficLights = int.MinValue,
        All = -1,
        None = 0,
        Created = 1,
        Deleted = 2,
        Original = 4,
        Disabled = 8,
        End = 16,
        Middle = 32,
        Bend = 64,
        Junction = 128,
        Moveable = 256,
        Untouchable = 512,
        Outside = 1024,
        Temporary = 2048,
        Double = 4096,
        Fixed = 8192,
        OnGround = 16384,
        Ambiguous = 32768,
        Water = 65536,
        Sewage = 131072,
        ForbidLaneConnection = 262144,
        Underground = 524288,
        Transition = 1048576,
        UndergroundTransition = 1572864,
        LevelCrossing = 2097152,
        OneWayOut = 4194304,
        TrafficLights = 8388608,
        OneWayOutTrafficLights = 12582912,
        OneWayIn = 16777216,
        Heating = 33554432,
        Electricity = 67108864,
        Collapsed = 134217728,
        DisableOnlyMiddle = 268435456,
        AsymForward = 536870912,
        AsymBackward = 1073741824
    }
}
pardeike commented 6 years ago

Still cannot reproduce. This compiles and runs just fine:

using Harmony;
using System;

namespace HarmonyConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var harmony = HarmonyInstance.Create("test");
            harmony.PatchAll(typeof(Program).Assembly);

            var node = new NetNode();
            node.CalculateNode(123);
            Console.ReadKey();
        }
    }

    public struct NetNode
    {
        public void CalculateNode(ushort nodeID)
        {
            Console.WriteLine("CalculateNode " + nodeID);
        }
    }

    [HarmonyPatch(typeof(NetNode))]
    [HarmonyPatch("CalculateNode")]
    static class Patch
    {
        [HarmonyPrefix]
        public static void CalculateNode_Prefix(NetNode __instance, ushort nodeID)
        {
            Console.WriteLine("Patch with " + __instance + " #" + nodeID);
        }
    }
}
pardeike commented 6 years ago

Which .Net version are you using and also: are you testing in Debug or in Release compile mode? Are you sure you have the lates source code when you compile Harmony?

Leigon commented 6 years ago

.Net 4, Debug.

I got latest through github desktop on a new clone today and installed c#7 via Install-Package Microsoft.Net.Compilers

pardeike commented 6 years ago

What happens if you try to run my example?

Leigon commented 6 years ago

Your sample works.

pardeike commented 6 years ago

Then the question you might be able to answer better than me is: what is the difference between my example and the concrete use case you have.

Leigon commented 6 years ago

Humm, I just created a new console app and using the skylines dll (and your sample without the struct) it works fine.

There is either something to do with my project settings or how skylines calls the mod dll I guess?

Leigon commented 6 years ago

I have tried several iterations and they all work in the console app and not from the game...

Eventually I tried something simple and this didn't work in game but did in the app: ` public class Node { public static void Hook() { FileLog.logPath = "E:\error.txt";

            NetNode2 node2 = new NetNode2(); 
            node2.CalculateNode( 1234 );

            var harmony = HarmonyInstance.Create( "test" );
            harmony.PatchAll( typeof( Node ).Assembly );

            node2.CalculateNode( 5678 );
    }
}

public struct NetNode2
{
    public void CalculateNode( ushort nodeID )
    {
        FileLog.Log( "CalculateNode " + nodeID );
    }
}

[HarmonyPatch( typeof( NetNode2 ) )]
[HarmonyPatch( "CalculateNode" )]
static class Patch2
{
    [HarmonyPrefix]
    public static void CalculateNode_Prefix( NetNode2 __instance, ushort nodeID )
    {
        FileLog.Log( "CalculateNode Prefix " + nodeID );
    }
}

`

Same error. The project looks identical apart from one being a DLL and one being a EXE.

In morning I will create a new project and see if I can get that working, I can only assume its something I am doing (using a ThreadingExtension and hooking on OnCreated).

Thanks for the help, will get back to you tomorrow. -Adrian

Leigon commented 6 years ago

I started from scratch with a .net 4.5.2 debug dll mod simplest as possible with debug output: ` using ICities; using ColossalFramework.UI; using UnityEngine; using System; using System.Reflection; using Harmony; using System.Diagnostics;

namespace TollRoad { public class ThreadingExtension : ThreadingExtensionBase { public static ThreadingExtension Instance { get; private set; }

    private static UInt32 LastInstanceCount = 1;
    private UInt32 InstanceCount { get; set; }

    public ThreadingExtension()
    {
        FileLog.logPath = "E:\\error.txt";
        Instance = null;
        InstanceCount = LastInstanceCount++;
        FileLog.Log( "ThreadingExtension Created " + InstanceCount.ToString() );
    }

    public override void OnCreated( IThreading threading )
    {
        FileLog.Log( "OnCreated " + InstanceCount.ToString() );
        if( Instance != null )
        {
            UnHook();
        }

        base.OnCreated( threading );
        Hook();

        Instance = this;

        NetNode2 test = new NetNode2();
        test.CalculateNode( 12345 );
    }

    public static void Hook()
    {
        FileLog.Log( "Hook" );
        try
        {
            var harmony = HarmonyInstance.Create( "com.leigon.cities_skylines.toll_road" );
            HarmonyInstance.DEBUG = true;

            MethodInfo targetmethod = AccessTools.Method( typeof( NetNode2 ), "CalculateNode" );
            HarmonyMethod prefixmethod = new HarmonyMethod( typeof( ThreadingExtension ).GetMethod( "CalculateNode_Prefix" ) );
            LogStackTrace();
            harmony.Patch( targetmethod, prefixmethod, null );
        }
        catch( System.Exception ex )
        {
            FileLog.Log( ex.ToString() );
        }
    }

    public static void UnHook()
    {
        FileLog.Log( "UnHook" );
        try
        {
            var harmony = HarmonyInstance.Create( "com.leigon.cities_skylines.toll_road" );
            HarmonyInstance.DEBUG = true;

            MethodInfo targetmethod = AccessTools.Method( typeof( NetNode2 ), "CalculateNode" );
            MethodInfo prefixmethod = AccessTools.Method( typeof( ThreadingExtension ), "CalculateNode_Prefix" );
            LogStackTrace();
            harmony.RemovePatch( targetmethod, prefixmethod );
        }
        catch( System.Exception ex )
        {
            FileLog.Log( ex.ToString() );
        }
    }

    public static void CalculateNode_Prefix( NetNode2 __instance, ushort nodeID )
    {
        FileLog.Log( "CalculateNode Prefix " + nodeID );
    }

    public override void OnReleased()
    {
        FileLog.Log( "OnReleased " + InstanceCount.ToString() );
        UnHook();

        Instance = null;

        base.OnReleased();
    }

    public static void LogStackTrace()
    {
        FileLog.Log( "--------------- Stack Trace ---------------" );
        StackTrace st = new StackTrace( true );
        for( int i = 1; i < st.FrameCount; i++ )
        {
            StackFrame sf = st.GetFrame( i );
            FileLog.Log( i.ToString() + ": " + sf.GetMethod() );
        }
        FileLog.Log( "-------------------------------------------" );
    }
}

public struct NetNode2
{
    public void CalculateNode( ushort nodeID )
    {
        FileLog.Log( "CalculateNode " + nodeID );
    }
}

} ` Entering the game:

ThreadingExtension Created 1
OnCreated 1
Hook
--------------- Stack Trace ---------------
1: Void Hook()
2: Void OnCreated(IThreading)
3: Void OnThreadingExtensionsCreated()
4: Void GetImplementations()
5: Void .ctor(SimulationManager)
6: Void CreateRelay()
7: Void MetaDataLoaded()
8: Boolean MoveNext()
9: Void InvokeMoveNext(IEnumerator, IntPtr)
-------------------------------------------
### Patch TollRoad.NetNode2, Void CalculateNode(UInt16)
L_0000: ldarg.0
L_0001: ldarg 1
L_0007: call Void CalculateNode_Prefix(NetNode2, UInt16)
L_000c: nop
L_000d: ldstr "CalculateNode "
L_0012: ldarg.1
L_0013: box System.UInt16
L_0018: call System.String Concat(System.Object, System.Object)
L_001d: call Void Log(System.String)
L_0022: nop
L_0023: ret
DONE

System.InvalidProgramException: Invalid IL code in (wrapper dynamic-method) TollRoad.NetNode2:CalculateNode_Patch1 (object,uint16): IL_0007: call      0x00000001

  at (wrapper managed-to-native) System.RuntimeMethodHandle:GetFunctionPointer (intptr)
  at System.RuntimeMethodHandle.GetFunctionPointer () [0x00000] in <filename unknown>:0 
  at Harmony.ILCopying.Memory.GetMethodStart (System.Reflection.MethodBase method) [0x00000] in <filename unknown>:0 
  at Harmony.PatchFunctions.UpdateWrapper (System.Reflection.MethodBase original, Harmony.PatchInfo patchInfo, System.String instanceID) [0x00000] in <filename unknown>:0 
  at Harmony.PatchProcessor.Patch () [0x00000] in <filename unknown>:0 
  at Harmony.HarmonyInstance.Patch (System.Reflection.MethodBase original, Harmony.HarmonyMethod prefix, Harmony.HarmonyMethod postfix, Harmony.HarmonyMethod transpiler) [0x00000] in <filename unknown>:0 
  at TollRoad.ThreadingExtension.Hook () [0x00000] in <filename unknown>:0 
CalculateNode 12345

Exiting to main menu:

OnReleased 1
UnHook
--------------- Stack Trace ---------------
1: Void UnHook()
2: Void OnReleased()
3: Void OnThreadingExtensionsReleased()
4: Void Release()
5: Void ReleaseRelay()
6: Boolean MoveNext()
7: Void Update()
-------------------------------------------
### Patch TollRoad.NetNode2, Void CalculateNode(UInt16)
L_0000: nop
L_0001: ldstr "CalculateNode "
L_0006: ldarg.1
L_0007: box System.UInt16
L_000c: call System.String Concat(System.Object, System.Object)
L_0011: call Void Log(System.String)
L_0016: nop
L_0017: ret
DONE

Do you have Cities Skylines?

pardeike commented 6 years ago

Unfortunately, I don't have Cities Skylines. Can you try with simpler versions of the Prefix? Like this:

public static void CalculateNode_Prefix( ushort nodeID );
// or
public static void CalculateNode_Prefix(  );

I just cannot see why it fails ont the CALL at loc 0007. Maybe I have to add Boxing but I never had to do this so far.

Leigon commented 6 years ago

Looks like its because NetNode2 is a struct. It does not work in game but does in the console app. As you can see below the first 3 tests succeed.

If you need a copy of the game to test with I can get you one if that helps?

public static void CalculateNode_Prefix( );

ThreadingExtension Created 1
OnCreated 1
Hook
### Patch TollRoad.NetNode2, Void CalculateNode()
L_0000: call Void CalculateNode_Prefix()
L_0005: nop
L_0006: ldstr "CalculateNode"
L_000b: call Void Log(System.String)
L_0010: nop
L_0011: ret
DONE

CalculateNode Prefix
CalculateNode
OnReleased 1
UnHook
### Patch TollRoad.NetNode2, Void CalculateNode()
L_0000: nop
L_0001: ldstr "CalculateNode"
L_0006: call Void Log(System.String)
L_000b: nop
L_000c: ret
DONE

public static void CalculateNode_Prefix( ushort nodeID );

ThreadingExtension Created 1
OnCreated 1
Hook
### Patch TollRoad.NetNode2, Void CalculateNode(UInt16)
L_0000: ldarg 1
L_0006: call Void CalculateNode_Prefix(UInt16)
L_000b: nop
L_000c: ldstr "CalculateNode "
L_0011: ldarg.1
L_0012: box System.UInt16
L_0017: call System.String Concat(System.Object, System.Object)
L_001c: call Void Log(System.String)
L_0021: nop
L_0022: ret
DONE

CalculateNode Prefix 12345
CalculateNode 12345
OnReleased 1
UnHook
### Patch TollRoad.NetNode2, Void CalculateNode(UInt16)
L_0000: nop
L_0001: ldstr "CalculateNode "
L_0006: ldarg.1
L_0007: box System.UInt16
L_000c: call System.String Concat(System.Object, System.Object)
L_0011: call Void Log(System.String)
L_0016: nop
L_0017: ret
DONE

NetNode2 as a class public static void CalculateNode_Prefix( NetNode2 __instance, ushort nodeID );

ThreadingExtension Created 1
OnCreated 1
Hook
### Patch TollRoad.NetNode2, Void CalculateNode(UInt16)
L_0000: ldarg.0
L_0001: ldarg 1
L_0007: call Void CalculateNode_Prefix(TollRoad.NetNode2, UInt16)
L_000c: nop
L_000d: ldstr "CalculateNode "
L_0012: ldarg.1
L_0013: box System.UInt16
L_0018: call System.String Concat(System.Object, System.Object)
L_001d: call Void Log(System.String)
L_0022: nop
L_0023: ret
DONE

CalculateNode Prefix 12345
CalculateNode 12345
OnReleased 1
UnHook
### Patch TollRoad.NetNode2, Void CalculateNode(UInt16)
L_0000: nop
L_0001: ldstr "CalculateNode "
L_0006: ldarg.1
L_0007: box System.UInt16
L_000c: call System.String Concat(System.Object, System.Object)
L_0011: call Void Log(System.String)
L_0016: nop
L_0017: ret
DONE

NetNode2 as a struct public static void CalculateNode_Prefix( NetNode2 __instance, ushort nodeID );

ThreadingExtension Created 1
OnCreated 1
Hook
### Patch TollRoad.NetNode2, Void CalculateNode(UInt16)
L_0000: ldarg.0
L_0001: ldarg 1
L_0007: call Void CalculateNode_Prefix(NetNode2, UInt16)
L_000c: nop
L_000d: ldstr "CalculateNode "
L_0012: ldarg.1
L_0013: box System.UInt16
L_0018: call System.String Concat(System.Object, System.Object)
L_001d: call Void Log(System.String)
L_0022: nop
L_0023: ret
DONE

System.InvalidProgramException: Invalid IL code in (wrapper dynamic-method) TollRoad.NetNode2:CalculateNode_Patch1 (object,uint16): IL_0007: call      0x00000001

  at (wrapper managed-to-native) System.RuntimeMethodHandle:GetFunctionPointer (intptr)
  at System.RuntimeMethodHandle.GetFunctionPointer () [0x00000] in <filename unknown>:0 
  at Harmony.ILCopying.Memory.GetMethodStart (System.Reflection.MethodBase method) [0x00000] in <filename unknown>:0 
  at Harmony.PatchFunctions.UpdateWrapper (System.Reflection.MethodBase original, Harmony.PatchInfo patchInfo, System.String instanceID) [0x00000] in <filename unknown>:0 
  at Harmony.PatchProcessor.Patch () [0x00000] in <filename unknown>:0 
  at Harmony.HarmonyInstance.Patch (System.Reflection.MethodBase original, Harmony.HarmonyMethod prefix, Harmony.HarmonyMethod postfix, Harmony.HarmonyMethod transpiler) [0x00000] in <filename unknown>:0 
  at TollRoad.ThreadingExtension.Hook () [0x00000] in <filename unknown>:0 
CalculateNode 12345
OnReleased 1
UnHook
### Patch TollRoad.NetNode2, Void CalculateNode(UInt16)
L_0000: nop
L_0001: ldstr "CalculateNode "
L_0006: ldarg.1
L_0007: box System.UInt16
L_000c: call System.String Concat(System.Object, System.Object)
L_0011: call Void Log(System.String)
L_0016: nop
L_0017: ret
DONE
VictorPhilipp commented 6 years ago

I experience the same problem. Cities: Skylines utilizes mono to decompile and recompile mod DLLs on-the-fly to ensure compatibility with different operating systems. That could make the difference here.

D:\Games\Steam\steamapps\common\Cities_Skylines\Mono\bin>mono -V
Mono JIT compiler version 2.0 (Visual Studio built mono)
Copyright (C) 2002-2010 Novell, Inc and Contributors. www.mono-project.com
        TLS:           normal
        GC:            Included Boehm (with typed GC)
        SIGSEGV:       normal
        Notification:  Thread + polling
        Architecture:  x86
        Disabled:      none
pardeike commented 6 years ago

This could be a variation on #77

pardeike commented 5 years ago

I just fixed #77 - please verify if this is still an issue. I will close this for now.