private static CodeInstruction FindNum6LocalVar(List <CodeInstruction> codes, CodeInstruction netInfoLocalVarStLoc, ref int index, int endIndex) { if (!TranspilerUtils.IsStLoc(netInfoLocalVarStLoc)) { Debug.LogError("netInfoLocalVarStLoc is not stloc! Cancelling transpiler!"); return(null); } // NetSegment netSegment5 = Singleton<NetManager>.instance.m_segments.m_buffer[num6]; // IL_07cc: call !0 class [ColossalManaged] ColossalFramework.Singleton`1<class NetManager>::get_instance() // IL_07d1: ldfld class Array16`1<valuetype NetSegment> NetManager::m_segments // IL_07d6: ldfld !0[] class Array16`1<valuetype NetSegment>::m_buffer // IL_07db: ldloc.s 51 // IL_07dd: ldelema NetSegment // IL_07e2: ldobj NetSegment // IL_07e7: stloc.s 61 // netInfo = netSegment5.Info; // IL_07e9: ldloca.s 61 // IL_07eb: call instance class NetInfo NetSegment::get_Info() // IL_07f0: stloc.s 48 for (; index < endIndex; index++) { // IL_07f0: stloc.s 48 if (TranspilerUtils.IsSameInstruction(codes[index], netInfoLocalVarStLoc)) { TranspilerUtils.LogDebug("Found netInfo = ..."); // IL_07db: ldloc.s 51 if (TranspilerUtils.IsLdLoc(codes[index - 6])) { TranspilerUtils.LogDebug("Found num6"); return(TranspilerUtils.BuildLdLocFromLdLoc(codes[index - 6])); } } } Debug.LogError("Unable to find num6. Cancelling transpiler!"); return(null); }
private static CodeInstruction FindSegment7LocalVar(List <CodeInstruction> codes, CodeInstruction info4LocalVarStLoc, ref int index, int endIndex) { if (!TranspilerUtils.IsStLoc(info4LocalVarStLoc)) { Debug.LogError("info4LocalVarStLoc is not stloc! Cancelling transpiler!"); return(null); } // NetSegment netSegment3 = Singleton<NetManager>.instance.m_segments.m_buffer[segment7]; // IL_05a9: call !0 class [ColossalManaged]ColossalFramework.Singleton`1<class NetManager>::get_instance() // IL_05ae: ldfld class Array16`1<valuetype NetSegment> NetManager::m_segments // IL_05b3: ldfld !0[] class Array16`1<valuetype NetSegment>::m_buffer // IL_05b8: ldloc.s 38 // IL_05ba: ldelema NetSegment // IL_05bf: ldobj NetSegment // IL_05c4: stloc.s 39 // NetInfo info4 = netSegment3.Info; // IL_05c6: ldloca.s 39 // IL_05c8: call instance class NetInfo NetSegment::get_Info() // IL_05cd: stloc.s 40 for (; index < endIndex; index++) { // IL_05cd: stloc.s 40 if (TranspilerUtils.IsSameInstruction(codes[index], info4LocalVarStLoc)) { TranspilerUtils.LogDebug("Found info4 = ..."); // // IL_05b8: ldloc.s 38 if (TranspilerUtils.IsLdLoc(codes[index - 6])) { TranspilerUtils.LogDebug("Found segment7"); return(TranspilerUtils.BuildLdLocFromLdLoc(codes[index - 6])); } } } Debug.LogError("Unable to find segment7. Cancelling transpiler!"); return(null); }
public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions) { var originalInstructions = new List <CodeInstruction>(instructions); var netInfoCreatePavementField = typeof(NetInfo).GetField("m_createPavement"); var netInfoFlattenTerrainField = typeof(NetInfo).GetField("m_flattenTerrain"); var segmentSkinsField = typeof(NetworkSkinManager).GetField("SegmentSkins", BindingFlags.Static | BindingFlags.Public); var terrainSurfacePatcherApplyMethod = typeof(TerrainSurfacePatcher).GetMethod("Apply"); var terrainSurfacePatcherRevertMethod = typeof(TerrainSurfacePatcher).GetMethod("Revert"); if (netInfoCreatePavementField == null || netInfoFlattenTerrainField == null || segmentSkinsField == null || terrainSurfacePatcherApplyMethod == null || terrainSurfacePatcherRevertMethod == null) { Debug.LogError("NetNodeTerrainUpdatedPatch: Necessary field and methods not found. Cancelling transpiler!"); return(originalInstructions); } var codes = new List <CodeInstruction>(originalInstructions); var patcherStateLocalVar = il.DeclareLocal(typeof(TerrainSurfacePatcherState)); patcherStateLocalVar.SetLocalSymInfo("patcherState"); int index = 0; CodeInstruction num14LocalVarLdLoc = null; CodeInstruction num13LocalVarLdLoc = null; CodeInstruction info4LocalVarLdLoc = null; CodeInstruction netInfo2LocalVarLdLoc = null; CodeInstruction segment7LocalVarLdLoc = null; CodeInstruction num6LocalVarLdLoc = null; for (; index < codes.Count; index++) { // NetInfo netInfo2 = (num14 > num13 >> 1) ? netInfo : info4; //IL_0a41: ldloc.s 74 (num14) //IL_0a43: ldloc.s 71 (num13) //IL_0a45: ldc.i4.1 //IL_0a46: shr //IL_0a47: bgt IL_0a53 //IL_0a4c: ldloc.s 40 (info4) //IL_0a4e: br IL_0a55 //IL_0a53: ldloc.s 48 (netInfo) //IL_0a55: stloc.s 75 (netInfo2) if (codes[index].opcode == OpCodes.Shr && TranspilerUtils.IsLdLoc(codes[index - 3]) && TranspilerUtils.IsLdLoc(codes[index - 2]) && codes[index - 1].opcode == OpCodes.Ldc_I4_1 // shr && codes[index + 1].opcode == OpCodes.Bgt && TranspilerUtils.IsLdLoc(codes[index + 2]) && codes[index + 3].opcode == OpCodes.Br && TranspilerUtils.IsLdLoc(codes[index + 4]) && TranspilerUtils.IsStLoc(codes[index + 5]) ) { TranspilerUtils.LogDebug("Found NetInfo netInfo2 = (num14 > num13 >> 1) ? netInfo : info4;"); num14LocalVarLdLoc = TranspilerUtils.BuildLdLocFromLdLoc(codes[index - 3]); num13LocalVarLdLoc = TranspilerUtils.BuildLdLocFromLdLoc(codes[index - 2]); info4LocalVarLdLoc = TranspilerUtils.BuildLdLocFromLdLoc(codes[index + 2]); // 40 var netInfoLocalVarLdLoc = TranspilerUtils.BuildLdLocFromLdLoc(codes[index + 4]); // 48 netInfo2LocalVarLdLoc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 5]); // 75 var findIndex = 0; segment7LocalVarLdLoc = FindSegment7LocalVar(codes, TranspilerUtils.BuildStLocFromLdLoc(info4LocalVarLdLoc), ref findIndex, index - 3); // 38 num6LocalVarLdLoc = FindNum6LocalVar(codes, TranspilerUtils.BuildStLocFromLdLoc(netInfoLocalVarLdLoc), ref findIndex, index - 3); // 51 break; } } if (num14LocalVarLdLoc == null || num13LocalVarLdLoc == null || info4LocalVarLdLoc == null || netInfo2LocalVarLdLoc == null || segment7LocalVarLdLoc == null || num6LocalVarLdLoc == null) { Debug.LogError("NetNodeTerrainUpdatedPatch: Some local variables not found! Cancelling transpiler!"); Debug.LogError($"num14: {num14LocalVarLdLoc}, num13: {num13LocalVarLdLoc}, info4: {info4LocalVarLdLoc}, netInfo2: {netInfo2LocalVarLdLoc}, segment7: {segment7LocalVarLdLoc}, num6: {num6LocalVarLdLoc}"); return(originalInstructions); } // segment7 is the segmentID of info4 // num6 is the segmentID of netInfo // TerrainSurfacePatcherState patcherState = TerrainSurfacePatcher.Apply(netInfo, NetworkSkinManager.SegmentSkins[(int)((num14 > num13 >> 1) ? num6 : segment7)]); // bool flag8 = netInfo2.m_createPavement && (!netInfo2.m_lowerTerrain || (m_flags & Flags.OnGround) != Flags.None); var apply1Inserted = false; for (; index < codes.Count; index++) { // bool flag8 = netInfo2.m_createPavement && (!netInfo2.m_lowerTerrain || (m_flags & Flags.OnGround) != Flags.None); if (TranspilerUtils.IsSameInstruction(codes[index], netInfo2LocalVarLdLoc) && codes[index + 1].opcode == OpCodes.Ldfld && codes[index + 1].operand == netInfoCreatePavementField) { TranspilerUtils.LogDebug("Found info4.m_createPavement"); var ldLocSegment7Label = il.DefineLabel(); var ldElemtRefLabel = il.DefineLabel(); // TerrainSurfacePatcherState patcherState = TerrainSurfacePatcher.Apply(netInfo, NetworkSkinManager.SegmentSkins[(int)((num14 > num13 >> 1) ? num6 : segment7)]); var apply1Instructions = new[] { new CodeInstruction(netInfo2LocalVarLdLoc), new CodeInstruction(OpCodes.Ldsfld, segmentSkinsField), new CodeInstruction(num14LocalVarLdLoc), new CodeInstruction(num13LocalVarLdLoc), new CodeInstruction(OpCodes.Ldc_I4_1), new CodeInstruction(OpCodes.Shr), new CodeInstruction(OpCodes.Bgt, ldLocSegment7Label), new CodeInstruction(segment7LocalVarLdLoc), new CodeInstruction(OpCodes.Br, ldElemtRefLabel), new CodeInstruction(num6LocalVarLdLoc), // ldLocSegment7Label new CodeInstruction(OpCodes.Ldelem_Ref), // ldElemtRefLabel new CodeInstruction(OpCodes.Call, terrainSurfacePatcherApplyMethod), new CodeInstruction(OpCodes.Stloc, patcherStateLocalVar) }; apply1Instructions[0].labels.AddRange(codes[index].labels); codes[index].labels.Clear(); apply1Instructions[9].labels.Add(ldLocSegment7Label); apply1Instructions[10].labels.Add(ldElemtRefLabel); codes.InsertRange(index, apply1Instructions); TranspilerUtils.LogDebug("Apply 1 inserted"); apply1Inserted = true; index += apply1Instructions.Length; break; } } if (!apply1Inserted) { Debug.LogError("NetNodeTerrainUpdatedPatch: Apply Insertion 1 failed! Cancelling transpiler!"); return(originalInstructions); } // NetworkSkins.TerrainSurfacePatcher.Revert(netInfo2, patcherState); // bool flag12 = netInfo2.m_flattenTerrain || (netInfo2.m_netAI.FlattenGroundNodes() && (m_flags & Flags.OnGround) != Flags.None); var revert1Inserted = false; for (; index < codes.Count; index++) { // bool flag12 = netInfo2.m_flattenTerrain || (netInfo2.m_netAI.FlattenGroundNodes() && (m_flags & Flags.OnGround) != Flags.None); if (TranspilerUtils.IsSameInstruction(codes[index], netInfo2LocalVarLdLoc) && codes[index + 1].opcode == OpCodes.Ldfld && codes[index + 1].operand == netInfoFlattenTerrainField) { TranspilerUtils.LogDebug("Found info4.m_flattenTerrain"); var revert1Instructions = new[] { new CodeInstruction(netInfo2LocalVarLdLoc), new CodeInstruction(OpCodes.Ldloc, patcherStateLocalVar), new CodeInstruction(OpCodes.Call, terrainSurfacePatcherRevertMethod), }; revert1Instructions[0].labels.AddRange(codes[index].labels); codes[index].labels.Clear(); codes.InsertRange(index, revert1Instructions); TranspilerUtils.LogDebug("Revert 1 inserted"); revert1Inserted = true; index += revert1Instructions.Length; break; } } if (!revert1Inserted) { Debug.LogError("NetNodeTerrainUpdatedPatch: Revert Insertion 1 failed! Cancelling transpiler!"); return(originalInstructions); } // patcherState = NetworkSkins.TerrainSurfacePatcher.Apply(info4, NetworkSkins.Skins.NetworkSkinManager.SegmentSkins[segment7]); // bool flag13 = info4.m_createPavement && (!info4.m_lowerTerrain || (m_flags & Flags.OnGround) != Flags.None); var apply2Inserted = false; for (; index < codes.Count; index++) { // bool flag13 = info4.m_createPavement && (!info4.m_lowerTerrain || (m_flags & Flags.OnGround) != Flags.None); if (TranspilerUtils.IsSameInstruction(codes[index], info4LocalVarLdLoc) && codes[index + 1].opcode == OpCodes.Ldfld && codes[index + 1].operand == netInfoCreatePavementField) { TranspilerUtils.LogDebug("Found info4.m_createPavement"); // patcherState = NetworkSkins.TerrainSurfacePatcher.Apply(info4, NetworkSkins.Skins.NetworkSkinManager.SegmentSkins[segment7]); var apply2Instructions = new[] { new CodeInstruction(info4LocalVarLdLoc), new CodeInstruction(OpCodes.Ldsfld, segmentSkinsField), new CodeInstruction(segment7LocalVarLdLoc), new CodeInstruction(OpCodes.Ldelem_Ref), new CodeInstruction(OpCodes.Call, terrainSurfacePatcherApplyMethod), new CodeInstruction(OpCodes.Stloc, patcherStateLocalVar) }; apply2Instructions[0].labels.AddRange(codes[index].labels); codes[index].labels.Clear(); codes.InsertRange(index, apply2Instructions); TranspilerUtils.LogDebug("Apply 2 inserted"); apply2Inserted = true; index += apply2Instructions.Length; break; } } if (!apply2Inserted) { Debug.LogError("NetNodeTerrainUpdatedPatch: Apply Insertion 2 failed! Cancelling transpiler!"); return(originalInstructions); } // NetworkSkins.TerrainSurfacePatcher.Revert(info4, patcherState); // bool flag17 = info4.m_flattenTerrain || (info4.m_netAI.FlattenGroundNodes() && (m_flags & Flags.OnGround) != Flags.None); var revert2Inserted = false; for (; index < codes.Count; index++) { // bool flag17 = info4.m_flattenTerrain || (info4.m_netAI.FlattenGroundNodes() && (m_flags & Flags.OnGround) != Flags.None); if (TranspilerUtils.IsSameInstruction(codes[index], info4LocalVarLdLoc) && codes[index + 1].opcode == OpCodes.Ldfld && codes[index + 1].operand == netInfoFlattenTerrainField) { TranspilerUtils.LogDebug("Found info4.m_flattenTerrain"); // NetworkSkins.TerrainSurfacePatcher.Revert(info4, patcherState); var revert2Instructions = new[] { new CodeInstruction(info4LocalVarLdLoc), new CodeInstruction(OpCodes.Ldloc, patcherStateLocalVar), new CodeInstruction(OpCodes.Call, terrainSurfacePatcherRevertMethod), }; revert2Instructions[0].labels.AddRange(codes[index].labels); codes[index].labels.Clear(); codes.InsertRange(index, revert2Instructions); TranspilerUtils.LogDebug("Revert 2 inserted"); revert2Inserted = true; index += revert2Instructions.Length; break; } } if (!revert2Inserted) { Debug.LogError("NetNodeTerrainUpdatedPatch: Revert Insertion 2 failed! Cancelling transpiler!"); return(originalInstructions); } return(codes); }