public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions) { var originalInstructions = new List <CodeInstruction>(instructions); var netAiGetNodeBuildingMethod = typeof(NetAI).GetMethod("GetNodeBuilding"); var pillarPatcherGetActiveNodeBuildingMethod = typeof(ActivePillarPatcher).GetMethod("GetActiveNodeBuilding"); if (netAiGetNodeBuildingMethod == null || pillarPatcherGetActiveNodeBuildingMethod == null) { Debug.LogError("Necessary methods not found. Cancelling transpiler!"); return(originalInstructions); } var codes = new List <CodeInstruction>(originalInstructions); // Replace all GetNodeBuilding calls with GetActiveNodeBuilding for (var index = 0; index < codes.Count; index++) { if (codes[index].opcode == OpCodes.Callvirt) { if (codes[index].operand == netAiGetNodeBuildingMethod) { TranspilerUtils.LogDebug("Found GetNodeBuilding(ushort nodeID, ref NetNode data, out BuildingInfo building, out float heightOffset)"); codes[index] = new CodeInstruction(codes[index]) { opcode = OpCodes.Call, operand = pillarPatcherGetActiveNodeBuildingMethod }; } } } return(codes); }
static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, MethodBase original) { var codes = instructions.ToCodeList(); int iGetSegment1 = codes.Search(c => c.Calls(mGetSegment), count: 1); int iStSegmentID1 = codes.Search(c => c.IsStloc(), startIndex: iGetSegment1); var ldSegmentID1 = TranspilerUtils.BuildLdLocFromStLoc(codes[iStSegmentID1]); int iGetSegment2 = codes.Search(c => c.Calls(mGetSegment), count: 1); int iStSegmentID2 = codes.Search(c => c.IsStloc(), startIndex: iGetSegment2); var ldSegmentID2 = TranspilerUtils.BuildLdLocFromStLoc(codes[iStSegmentID2]); codes.InsertInstructions(iStSegmentID2 + 1, new[] { ldSegmentID1, ldSegmentID2, new CodeInstruction(OpCodes.Call, ShiftData.mPrefix), }); // DC part of the code is before m_requireSegmentRenderers int i_requireSegmentRenderers = codes.Search(c => c.LoadsField(f_requireSegmentRenderers)); codes.InsertInstructions(i_requireSegmentRenderers, new[] { new CodeInstruction(OpCodes.Call, ShiftData.mPostfix), }); return(codes); }
// code from: https://github.com/Strdate/SmartIntersections/blob/master/SmartIntersections/Patch/LoadPathsPatch.cs public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions) { var fTempNodeBuffer = AccessTools.DeclaredField(typeof(NetManager), nameof(NetManager.m_tempNodeBuffer)) ?? throw new Exception("cound not find NetManager.m_tempNodeBuffer"); var mClear = AccessTools.DeclaredMethod(fTempNodeBuffer.FieldType, nameof(FastList <ushort> .Clear)) ?? throw new Exception("cound not find m_tempNodeBuffer.Clear"); var mAfterIntersectionBuilt = AccessTools.DeclaredMethod( typeof(LoadPathsPatch), nameof(AfterIntersectionBuilt)) ?? throw new Exception("cound not find AfterIntersectionBuilt()"); List <CodeInstruction> codes = TranspilerUtils.ToCodeList(instructions); bool comp(int i) => codes[i].opcode == OpCodes.Ldfld && codes[i].operand == fTempNodeBuffer && codes[i + 1].opcode == OpCodes.Callvirt && codes[i + 1].operand == mClear; int index = codes.Search(comp, startIndex: 0, count: 2); index -= 1; // index to insert instructions. var newInstructions = new[] { new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Call, mAfterIntersectionBuilt), }; codes.InsertInstructions(index, newInstructions); return(codes); }
//static bool Prefix(ushort nodeID){} public static IEnumerable<CodeInstruction> Transpiler(MethodBase original, IEnumerable<CodeInstruction> instructions) { try { var codes = TranspilerUtils.ToCodeList(instructions); CheckMedianCommons.ApplyCheckMedian(codes, original, occurance: 1); return codes; } catch (Exception e) { e.Log(); throw e; } }
public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions) { var originalInstructions = new List <CodeInstruction>(instructions); var netAiGetNodeBuildingMethod = typeof(NetAI).GetMethod("GetNodeBuilding"); var netAiCheckBuildPositionMethod = typeof(NetAI).GetMethod("CheckBuildPosition"); var pillarPatcherGetActiveNodeBuildingMethod = typeof(ActivePillarPatcher).GetMethod("GetActiveNodeBuilding"); var patchCheckBuildPositionMethod = typeof(NetToolCreateNodePatch).GetMethod("CheckBuildPosition"); if (netAiGetNodeBuildingMethod == null || pillarPatcherGetActiveNodeBuildingMethod == null) { Debug.LogError("Necessary methods not found. Cancelling transpiler!"); return(originalInstructions); } var codes = new List <CodeInstruction>(originalInstructions); // Replace all GetNodeBuilding calls with GetActiveNodeBuilding for (var index = 0; index < codes.Count; index++) { if (codes[index].opcode == OpCodes.Callvirt) { if (codes[index].operand == netAiGetNodeBuildingMethod) { TranspilerUtils.LogDebug("Found GetNodeBuilding(ushort nodeID, ref NetNode data, out BuildingInfo building, out float heightOffset)"); codes[index] = new CodeInstruction(codes[index]) { opcode = OpCodes.Call, operand = pillarPatcherGetActiveNodeBuildingMethod }; } } } // Replace all CheckBuildPosition calls with Patcher.CheckBuildPosition for (var index = 0; index < codes.Count; index++) { if (codes[index].opcode == OpCodes.Callvirt) { if (codes[index].operand == netAiCheckBuildPositionMethod) { TranspilerUtils.LogDebug("Found CheckBuildPosition(bool test, bool visualize, bool overlay, bool autofix, ref NetTool.ControlPoint startPoint, ref NetTool.ControlPoint middlePoint, ref NetTool.ControlPoint endPoint, out BuildingInfo ownerBuilding, out Vector3 ownerPosition, out Vector3 ownerDirection, out int productionRate)"); codes[index] = new CodeInstruction(codes[index]) { opcode = OpCodes.Call, operand = patchCheckBuildPositionMethod }; } } } return(codes); }
public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, MethodBase original) { try { var codes = TranspilerUtils.ToCodeList(instructions); SegmentOverlay.Patch(codes, original); Log.Info($"{ReflectionHelpers.ThisMethod} patched {original} successfully!"); return(codes); } catch (Exception e) { Log.Error(e.ToString()); throw e; } }
public static IEnumerable<CodeInstruction> Transpiler(MethodBase original, IEnumerable<CodeInstruction> instructions) { try { var codes = TranspilerUtils.ToCodeList(instructions); CheckPropFlagsCommons.PatchCheckFlags(codes, original); Log.Info($"{ReflectionHelpers.ThisMethod} patched {original} successfully!"); return codes; } catch (Exception e) { Log.Error(e.ToString()); throw e; } }
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original) { try { var codes = TranspilerUtils.ToCodeList(instructions); CheckSegmentFlagsCommons.PatchCheckFlags(codes, original); Log.Info($"{ThisMethod} patched {original} successfully!"); return codes; } catch (Exception ex) { Log.Error(ex.ToString()); throw ex; } }
public static IEnumerable<CodeInstruction> Transpiler(ILGenerator il, IEnumerable<CodeInstruction> instructions) { try { var codes = TranspilerUtils.ToCodeList(instructions); CalculateMaterialCommons.PatchCheckFlags(codes, occurance: 2, Target); Log("successfully patched NetNode.RenderInstance"); return codes; }catch(Exception e) { KianCommons.Log.Error(e.ToString()); throw e; } }
//static bool Prefix(ushort nodeID){} public static IEnumerable<CodeInstruction> Transpiler(ILGenerator il, IEnumerable<CodeInstruction> instructions) { try { var codes = TranspilerUtils.ToCodeList(instructions); CheckTracksCommons.ApplyCheckTracks(codes, Target, occurance:1); Log("successfully patched NetNode.RenderInstance"); return codes; }catch(Exception e) { Log(e + "\n" + Environment.StackTrace); throw e; } }
public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions) { var originalInstructions = new List <CodeInstruction>(instructions); var netAiGetSegmentColorMethod = typeof(NetAI).GetMethod("GetColor", new[] { typeof(ushort), typeof(global::NetSegment).MakeByRefType(), typeof(InfoManager.InfoMode) }); var netAiGetNodeColorMethod = typeof(NetAI).GetMethod("GetColor", new[] { typeof(ushort), typeof(global::NetNode).MakeByRefType(), typeof(InfoManager.InfoMode) }); var colorPatcherGetSegmentColorMethod = typeof(ColorPatcher).GetMethod("GetSegmentColor"); var colorPatcherGetNodeColorMethod = typeof(ColorPatcher).GetMethod("GetNodeColor"); if (netAiGetSegmentColorMethod == null || netAiGetNodeColorMethod == null || colorPatcherGetSegmentColorMethod == null || colorPatcherGetNodeColorMethod == null) { Debug.LogError("Necessary methods not found. Cancelling transpiler!"); return(originalInstructions); } var codes = new List <CodeInstruction>(originalInstructions); // Replace all GetColor calls with GetSegmentColor/GetNodeColor for (var index = 0; index < codes.Count; index++) { if (codes[index].opcode == OpCodes.Callvirt) { if (codes[index].operand == netAiGetSegmentColorMethod) { TranspilerUtils.LogDebug("Found GetColor(ushort segmentID, ref NetSegment data, InfoManager.InfoMode infoMode)"); codes[index] = new CodeInstruction(codes[index]) { opcode = OpCodes.Call, operand = colorPatcherGetSegmentColorMethod }; } else if (codes[index].operand == netAiGetNodeColorMethod) { TranspilerUtils.LogDebug("Found GetColor(ushort nodeID, ref NetNode data, InfoManager.InfoMode infoMode)"); codes[index] = new CodeInstruction(codes[index]) { opcode = OpCodes.Call, operand = colorPatcherGetNodeColorMethod }; } } } return(codes); }
public static IEnumerable <CodeInstruction> Transpiler( IEnumerable <CodeInstruction> instructions, MethodBase original) { try { var codes = TranspilerUtils.ToCodeList(instructions); // (node.m_connectGroup == NetInfo.ConnectGroup.None || (node.m_connectGroup & info2.m_connectGroup & NetInfo.ConnectGroup.AllGroups) != NetInfo.ConnectGroup.None) // (node4.m_connectGroup == NetInfo.ConnectGroup.None || (node4.m_connectGroup & info.m_connectGroup & NetInfo.ConnectGroup.AllGroups) != NetInfo.ConnectGroup.None) CheckNodeConnectGroupNone.Patch(codes, original); // 2 CheckNodeConnectGroup.Patch(codes, original); // 2 Log.Info($"{ReflectionHelpers.ThisMethod} patched {original} successfully!"); return(codes); } catch (Exception e) { Log.Error(e.ToString()); throw e; } }
public static IEnumerable <CodeInstruction> Transpiler( IEnumerable <CodeInstruction> instructions, MethodBase original) { try { var codes = TranspilerUtils.ToCodeList(instructions); NodeOverlay.Patch(codes, original, occuranceDrawMesh: 1, counterGetSegment: 2); // DC NodeOverlay.Patch(codes, original, occuranceDrawMesh: 2, counterGetSegment: 1); // junction NodeOverlay.Patch(codes, original, occuranceDrawMesh: 3, counterGetSegment: 0); // end NodeOverlay.PatchBend(codes, original, occuranceDrawMesh: 4); // end NodeOverlay.Patch(codes, original, occuranceDrawMesh: 5, counterGetSegment: 0); // DC-bend Log.Info($"{ReflectionHelpers.ThisMethod} patched {original} successfully!"); return(codes); } catch (Exception e) { Log.Error(e.ToString()); throw e; } }
public static IEnumerable<CodeInstruction> Transpiler(MethodBase original, IEnumerable<CodeInstruction> instructions) { try { var codes = TranspilerUtils.ToCodeList(instructions); CheckNodeFlagsCommons.PatchCheckFlags(codes, original, occuranceCheckFlags: 1, counterGetSegment: 2); //DC CheckNodeFlagsCommons.PatchCheckFlags(codes, original, occuranceCheckFlags: 2, counterGetSegment: 2); //DC // CS has copy pasted code. CheckNodeFlagsCommons.PatchCheckFlags(codes, original, occuranceCheckFlags: 3, counterGetSegment: 1); //Junction CheckNodeFlagsCommons.PatchCheckFlags(codes, original, occuranceCheckFlags: 4, counterGetSegment: 0); //End // Bend node -> segment.Checkflags (does not use info flags.) CheckNodeFlagsCommons.PatchCheckFlags(codes, original, occuranceCheckFlags: 5, counterGetSegment: 0); //DC Bend Log.Info($"{ReflectionHelpers.ThisMethod} patched {original} successfully!"); return codes; } catch (Exception e) { Log.Error(e.ToString()); throw e; } }
public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions) { var netSegmentInfoGetter = typeof(global::NetSegment).GetProperty("Info")?.GetGetMethod(); if (netSegmentInfoGetter == null) { Debug.LogError("Necessary field not found. Cancelling transpiler!"); return(instructions); } var originalCodes = new List <CodeInstruction>(instructions); var codes = new List <CodeInstruction>(originalCodes); var index = 0; CodeInstruction infoLocalVarLdloc = null; for (; index < codes.Count; index++) { // IL_0003: call instance class NetInfo NetSegment::get_Info() if (codes[index].opcode == OpCodes.Call && codes[index].operand == netSegmentInfoGetter && TranspilerUtils.IsStLoc(codes[index + 1])) { infoLocalVarLdloc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 1]); index += 2; break; } } if (infoLocalVarLdloc == null) { Debug.LogError("NetSegmentCalculateGroupDataPatch: info local variable not found. Cancelling transpiler!"); return(originalCodes); } var segmentIdLdInstruction = new CodeInstruction(OpCodes.Ldarg_1); // segmentID is first argument if (!NetSegmentRenderPatch.PatchLanesAndSegments(il, codes, infoLocalVarLdloc, segmentIdLdInstruction, ref index)) { Debug.LogError("NetSegmentCalculateGroupDataPatch: Could not apply NetSegmentRenderPatch. Cancelling transpiler!"); return(originalCodes); } return(codes); }
public static IEnumerable<CodeInstruction> Transpiler(MethodBase original, IEnumerable<CodeInstruction> instructions) { try { var codes = TranspilerUtils.ToCodeList(instructions); CheckNodeFlagsCommons.PatchCheckFlags(codes, original, occuranceCheckFlags: 1, counterGetSegment: 2, true); //DC CheckNodeFlagsCommons.PatchCheckFlags(codes, original, occuranceCheckFlags: 2, counterGetSegment: 2, true); //DC // Unlike RenderInstance and CalculateGroupData, counterGetSegment for PopulateGroupData Junction is 2: CheckNodeFlagsCommons.PatchCheckFlags(codes, original, occuranceCheckFlags: 3, counterGetSegment: 2); //Junction CheckNodeFlagsCommons.PatchCheckFlags(codes, original, occuranceCheckFlags: 4, counterGetSegment: 0); // End // End - BEND -> segment.Checkflags (does not use info flags.) // Bend node -> segment.Checkflags (does not use info flags.) CheckNodeFlagsCommons.PatchCheckFlags(codes, original, occuranceCheckFlags: 5, counterGetSegment: 0, true); //DC Bend Log.Info($"{ReflectionHelpers.ThisMethod} patched {original} successfully!"); return codes; } catch (Exception e) { Log.Error(e.ToString()); throw e; } }
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, MethodBase original, IEnumerable <CodeInstruction> instructions) { var originalInstructions = new List <CodeInstruction>(instructions); var allowedCallersField = original.DeclaringType?.GetField("AllowedCallers", BindingFlags.Static | BindingFlags.NonPublic); var isAllowedCallerMethod = typeof(NetManagerDetourPatch).GetMethod("IsAllowedCaller", BindingFlags.Static | BindingFlags.Public); if (allowedCallersField == null || isAllowedCallerMethod == null) { Debug.LogError("Necessary members not found. Cancelling transpiler!"); return(originalInstructions); } var codes = new List <CodeInstruction>(originalInstructions); for (var index = 0; index < codes.Count; index++) { if (codes[index].opcode == OpCodes.Ldsfld && codes[index].operand == allowedCallersField) { if (TranspilerUtils.IsLdLoc(codes[index + 1])) { if (codes[index + 2].opcode == OpCodes.Call && (codes[index + 2].operand as MethodBase).Name == "Contains") { codes[index + 2] = new CodeInstruction(codes[index + 2]) { opcode = OpCodes.Call, operand = isAllowedCallerMethod }; Debug.Log("Patched ParallelRoadTool to work with NS2!"); break; } } } } return(codes); }
static MethodBase TargetMethod() { return(TranspilerUtils.GetCoroutineMoveNext( typeof(AssetImporterAssetTemplate), nameof(AssetImporterAssetTemplate.RefreshCoroutine))); }
public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions) { var netNodeRefreshEndDataMethod = typeof(global::NetNode).GetMethod("RefreshEndData", BindingFlags.NonPublic | BindingFlags.Instance); var netNodeGetSegmentMethod = typeof(global::NetNode).GetMethod("GetSegment"); var netInfoNodesField = typeof(NetInfo).GetField("m_nodes"); var netNodeRenderPatchShouldRenderJunctionNodeMethod = typeof(NetNodeRenderPatch).GetMethod("ShouldRenderJunctionNode"); var netNodeRenderPatchShouldRenderBendNodeMethod = typeof(NetNodeRenderPatch).GetMethod("ShouldRenderBendNode"); if (netNodeRefreshEndDataMethod == null || netNodeGetSegmentMethod == null || netInfoNodesField == null || netNodeRenderPatchShouldRenderJunctionNodeMethod == null || netNodeRenderPatchShouldRenderBendNodeMethod == null) { Debug.LogError("NetNodeRenderInstancePatch: Necessary methods and field not found. Cancelling transpiler!"); return(instructions); } var index = 0; var originalCodes = new List <CodeInstruction>(instructions); var codes = new List <CodeInstruction>(originalCodes); var refreshEndDataCallFound = false; for (; index < codes.Count; index++) { // IL_0066: call instance void NetNode::RefreshEndData(uint16, class NetInfo, uint32, valuetype RenderManager/Instance&) if (codes[index].opcode == OpCodes.Call && codes[index].operand == netNodeRefreshEndDataMethod) { refreshEndDataCallFound = true; break; } } if (!refreshEndDataCallFound) { Debug.LogError("NetNodeRenderInstancePatch: RefreshEndData call not found. Cancelling transpiler!"); return(originalCodes); } var junctionFlagCheckFound = false; for (; index < codes.Count; index++) { // if ((flags & Flags.Junction) != 0) // IL_0077: ldarg.s 'flags' // IL_0079: ldc.i4 128 if (codes[index].opcode == OpCodes.Ldarg_S && (byte)codes[index].operand == FlagsArgIndex && codes[index + 1].opcode == OpCodes.Ldc_I4 && (int)codes[index + 1].operand == (int)global::NetNode.Flags.Junction) { junctionFlagCheckFound = true; break; } } if (!junctionFlagCheckFound) { Debug.LogError("NetNodeRenderInstancePatch: junctionFlagCheck not found. Cancelling transpiler!"); return(originalCodes); } CodeInstruction segmentLocalVarLdloc = null; CodeInstruction segment2LocalVarLdloc = null; CodeInstruction nodeLocalVarLdLoc = null; for (; index < codes.Count; index++) { // IL_009c: call instance uint16 NetNode::GetSegment(int32) if (codes[index].opcode == OpCodes.Call && codes[index].operand == netNodeGetSegmentMethod && TranspilerUtils.IsStLoc(codes[index + 1])) { // IL_00a1: stloc.0 segmentLocalVarLdloc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 1]); index += 2; break; } } for (; index < codes.Count; index++) { // IL_00ac: call instance uint16 NetNode::GetSegment(int32) if (codes[index].opcode == OpCodes.Call && codes[index].operand == netNodeGetSegmentMethod && TranspilerUtils.IsStLoc(codes[index + 1])) { // IL_00b1: stloc.1 segment2LocalVarLdloc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 1]); index += 2; break; } } for (; index < codes.Count; index++) { // IL_013e: ldfld class NetInfo/Node[] NetInfo::m_nodes if (codes[index].opcode == OpCodes.Ldfld && codes[index].operand == netInfoNodesField && TranspilerUtils.IsStLoc(codes[index + 3])) { // IL_0146: stloc.s 6 nodeLocalVarLdLoc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 3]); index += 4; break; } } if (segmentLocalVarLdloc == null || segment2LocalVarLdloc == null || nodeLocalVarLdLoc == null) { Debug.LogError("NetNodeRenderInstancePatch: Necessary field for junction not found. Cancelling transpiler!"); Debug.LogError($"{segmentLocalVarLdloc}, {segment2LocalVarLdloc}, {nodeLocalVarLdLoc}"); return(originalCodes); } var junctionRenderCheckInserted = false; for (; index < codes.Count; index++) { // IL_017c: ldc.i4 987135 // IL_0181: and // IL_0182: brfalse IL_0570 if (codes[index].opcode == OpCodes.Ldc_I4 && (int)codes[index].operand == (int)NetInfo.ConnectGroup.AllGroups && codes[index + 1].opcode == OpCodes.And && codes[index + 2].opcode == OpCodes.Brfalse) { var labelIfFalse = codes[index + 2].operand; var insertionPosition = index + 3; // && NetNodeRenderPatch.NetNodeRenderPatch(node, segment, segment2) // IL_01FD: ldloc.s V_6 // IL_01FF: ldloc.0 // IL_0200: ldloc.1 // IL_0201: call bool[NetworkSkins] NetworkSkins.Patches.NetNodeRenderPatch::ShouldRenderJunctionNode(class NetInfo/Node, uint16, uint16) // IL_0206: brfalse.s IL_024A var renderCheckInstructions = new[] { new CodeInstruction(nodeLocalVarLdLoc), new CodeInstruction(segmentLocalVarLdloc), new CodeInstruction(segment2LocalVarLdloc), new CodeInstruction(OpCodes.Call, netNodeRenderPatchShouldRenderJunctionNodeMethod), new CodeInstruction(OpCodes.Brfalse, labelIfFalse), }; renderCheckInstructions[0].labels.AddRange(codes[insertionPosition].labels); codes[insertionPosition].labels.Clear(); codes.InsertRange(insertionPosition, renderCheckInstructions); TranspilerUtils.LogDebug("Junction render check inserted"); index = insertionPosition + renderCheckInstructions.Length; junctionRenderCheckInserted = true; break; } } if (!junctionRenderCheckInserted) { Debug.LogError("NetNodeRenderInstancePatch: Render check 1 not inserted. Cancelling transpiler!"); return(originalCodes); } var bendFlagCheckFound = false; for (; index < codes.Count; index++) { // else if ((flags & Flags.Bend) != 0) // IL_0e28: ldarg.s 'flags' // IL_0e2a: ldc.i4.s 64 if (codes[index].opcode == OpCodes.Ldarg_S && (byte)codes[index].operand == FlagsArgIndex && codes[index + 1].opcode == OpCodes.Ldc_I4_S && (sbyte)codes[index + 1].operand == (sbyte)global::NetNode.Flags.Bend) { bendFlagCheckFound = true; break; } } if (!bendFlagCheckFound) { Debug.LogError("NetNodeRenderInstancePatch: bendFlagCheck not found. Cancelling transpiler!"); return(originalCodes); } CodeInstruction segment5LocalVarLdloc = null; CodeInstruction segment6LocalVarLdloc = null; CodeInstruction node4LocalVarLdLoc = null; for (; index < codes.Count; index++) { // IL_11ae: call instance uint16 NetNode::GetSegment(int32) if (codes[index].opcode == OpCodes.Call && codes[index].operand == netNodeGetSegmentMethod && TranspilerUtils.IsStLoc(codes[index + 1])) { // IL_00a1: stloc.s 32 segment5LocalVarLdloc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 1]); index += 2; break; } } for (; index < codes.Count; index++) { // IL_11bf: call instance uint16 NetNode::GetSegment(int32) if (codes[index].opcode == OpCodes.Call && codes[index].operand == netNodeGetSegmentMethod && TranspilerUtils.IsStLoc(codes[index + 1])) { // IL_11c4: stloc.s 33 segment6LocalVarLdloc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 1]); index += 2; break; } } for (; index < codes.Count; index++) { // IL_120d: ldfld class NetInfo/Node[] NetInfo::m_nodes if (codes[index].opcode == OpCodes.Ldfld && codes[index].operand == netInfoNodesField && TranspilerUtils.IsStLoc(codes[index + 3])) { // IL_1215: stloc.s 35 node4LocalVarLdLoc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 3]); index += 4; break; } } if (segment5LocalVarLdloc == null || segment6LocalVarLdloc == null || node4LocalVarLdLoc == null) { Debug.LogError("NetNodeRenderInstancePatch: Necessary field for bend not found. Cancelling transpiler!"); Debug.LogError($"{segment5LocalVarLdloc} {segment6LocalVarLdloc} {node4LocalVarLdLoc}"); return(originalCodes); } var bendRenderCheckInserted = false; for (; index < codes.Count; index++) { // IL_124b: ldc.i4 987135 // IL_1250: and // IL_1251: brfalse IL_1637 if (codes[index].opcode == OpCodes.Ldc_I4 && (int)codes[index].operand == (int)NetInfo.ConnectGroup.AllGroups && codes[index + 1].opcode == OpCodes.And && codes[index + 2].opcode == OpCodes.Brfalse) { var labelIfFalse = codes[index + 2].operand; var insertionPosition = index + 3; // ldloc.s 35 // ldloc.s 32 // ldloc.s 33 // call bool[NetworkSkins] NetworkSkins.Patches.NetNodeRenderPatch::ShouldRenderJunctionNode(class NetInfo/Node, uint16, uint16) // brfalse.s IL_1637 var renderCheckInstructions = new[] { new CodeInstruction(node4LocalVarLdLoc), new CodeInstruction(segment5LocalVarLdloc), new CodeInstruction(segment6LocalVarLdloc), new CodeInstruction(OpCodes.Call, netNodeRenderPatchShouldRenderBendNodeMethod), new CodeInstruction(OpCodes.Brfalse, labelIfFalse), }; renderCheckInstructions[0].labels.AddRange(codes[insertionPosition].labels); codes[insertionPosition].labels.Clear(); codes.InsertRange(insertionPosition, renderCheckInstructions); TranspilerUtils.LogDebug("Bend render check inserted"); index = insertionPosition + renderCheckInstructions.Length; bendRenderCheckInserted = true; break; } } if (!bendRenderCheckInserted) { Debug.LogError("NetNodeRenderInstancePatch: Bend render check not inserted. Cancelling transpiler!"); return(originalCodes); } return(codes); }
static MethodBase TargetMethod() => TranspilerUtils.DeclaredMethod <CheckOverlap>(typeof(PassengerCarAI));
public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions) { var netNodeFlagsField = typeof(global::NetNode).GetField("m_flags"); var netNodeGetSegmentMethod = typeof(global::NetNode).GetMethod("GetSegment"); var netInfoNodesField = typeof(NetInfo).GetField("m_nodes"); var netInfoNodeDirectConnectField = typeof(NetInfo.Node).GetField("m_directConnect"); var netNodeRenderPatchShouldRenderJunctionNodeMethod = typeof(NetNodeRenderPatch).GetMethod("ShouldRenderJunctionNode"); var netNodeRenderPatchShouldRenderBendNodeLodMethod = typeof(NetNodeRenderPatch).GetMethod("ShouldRenderBendNodeLod"); if (netNodeFlagsField == null || netNodeGetSegmentMethod == null || netInfoNodesField == null || netInfoNodeDirectConnectField == null || netNodeRenderPatchShouldRenderJunctionNodeMethod == null || netNodeRenderPatchShouldRenderBendNodeLodMethod == null) { Debug.LogError("Necessary methods and field not found. Cancelling transpiler!"); return(instructions); } var index = 0; var originalCodes = new List <CodeInstruction>(instructions); var codes = new List <CodeInstruction>(originalCodes); var junctionFlagCheckFound = false; for (; index < codes.Count; index++) { // if ((m_flags & Flags.Junction) != 0) // IL_004b: ldfld valuetype NetNode/Flags NetNode::m_flags // IL_0079: ldc.i4 128 if (codes[index].opcode == OpCodes.Ldfld && codes[index].operand == netNodeFlagsField && codes[index + 1].opcode == OpCodes.Ldc_I4 && (int)codes[index + 1].operand == (int)global::NetNode.Flags.Junction) { junctionFlagCheckFound = true; break; } } if (!junctionFlagCheckFound) { Debug.LogError("NetNodeGroupDataPatch: junctionFlagCheck not found. Cancelling transpiler!"); return(originalCodes); } CodeInstruction segmentLocalVarLdloc = null; CodeInstruction segment2LocalVarLdloc = null; CodeInstruction nodeLocalVarLdLoc = null; // ushort segment = GetSegment(i); for (; index < codes.Count; index++) { // IL_0073: call instance uint16 NetNode::GetSegment(int32) if (codes[index].opcode == OpCodes.Call && codes[index].operand == netNodeGetSegmentMethod && TranspilerUtils.IsStLoc(codes[index + 1])) { // IL_0078: stloc.s 5 segmentLocalVarLdloc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 1]); index += 2; break; } } // ushort segment2 = GetSegment(j); for (; index < codes.Count; index++) { // IL_0107: call instance uint16 NetNode::GetSegment(int32) if (codes[index].opcode == OpCodes.Call && codes[index].operand == netNodeGetSegmentMethod && TranspilerUtils.IsStLoc(codes[index + 1])) { // IL_010c: stloc.s 11 segment2LocalVarLdloc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 1]); index += 2; break; } } // NetInfo.Node node = info2.m_nodes[k]; for (; index < codes.Count; index++) { // IL_0359: ldfld class NetInfo/Node[] NetInfo::m_nodes // IL_035e: ldloc.s 21 // IL_0360: ldelem.ref // IL_0361: stloc.s 22 if (codes[index].opcode == OpCodes.Ldfld && codes[index].operand == netInfoNodesField && TranspilerUtils.IsLdLoc(codes[index + 1]) && codes[index + 2].opcode == OpCodes.Ldelem_Ref && TranspilerUtils.IsStLoc(codes[index + 3])) { // IL_0361: stloc.s 22 nodeLocalVarLdLoc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 3]); index += 4; break; } } if (segmentLocalVarLdloc == null || segment2LocalVarLdloc == null || nodeLocalVarLdLoc == null) { Debug.LogError("NetNodeGroupDataPatch: Necessary field for junction not found. Cancelling transpiler!"); Debug.LogError($"{segmentLocalVarLdloc}, {segment2LocalVarLdloc}, {nodeLocalVarLdLoc}"); return(originalCodes); } var junctionRenderCheckInserted = false; for (; index < codes.Count; index++) { // IL_017c: ldloc.s 22 // IL_0181: ldfld bool NetInfo/Node::m_directConnect // IL_0182: brfalse IL_04c3 if (TranspilerUtils.IsSameInstruction(codes[index], nodeLocalVarLdLoc, true) && codes[index + 1].opcode == OpCodes.Ldfld && codes[index + 1].operand == netInfoNodeDirectConnectField && codes[index + 2].opcode == OpCodes.Brfalse) { var labelIfFalse = codes[index + 2].operand; var insertionPosition = index + 3; // && ShouldRenderJunctionNode(node, segment, segment2) // IL_01FD: ldloc.s 22 // IL_01FF: ldloc.s 11 // IL_0200: ldloc.s 22 // IL_0201: call bool[NetworkSkins] NetworkSkins.Patches.NetNodeRenderPatch::ShouldRenderJunctionNode(class NetInfo/Node, uint16, uint16) // IL_0206: brfalse.s IL_04c3 var renderCheckInstructions = new[] { new CodeInstruction(nodeLocalVarLdLoc), new CodeInstruction(segmentLocalVarLdloc), new CodeInstruction(segment2LocalVarLdloc), new CodeInstruction(OpCodes.Call, netNodeRenderPatchShouldRenderJunctionNodeMethod), new CodeInstruction(OpCodes.Brfalse, labelIfFalse), }; renderCheckInstructions[0].labels.AddRange(codes[insertionPosition].labels); codes[insertionPosition].labels.Clear(); codes.InsertRange(insertionPosition, renderCheckInstructions); TranspilerUtils.LogDebug("Junction render check inserted"); index = insertionPosition + renderCheckInstructions.Length; junctionRenderCheckInserted = true; break; } } if (!junctionRenderCheckInserted) { Debug.LogError("NetNodeGroupDataPatch: Junction render check not inserted. Cancelling transpiler!"); return(originalCodes); } var bendFlagCheckFound = false; for (; index < codes.Count; index++) { // else if ((m_flags & Flags.Bend) != 0) // IL_0e28: ldarg.s 'flags' // IL_0e2a: ldc.i4.s 64 if (codes[index].opcode == OpCodes.Ldfld && codes[index].operand == netNodeFlagsField && codes[index + 1].opcode == OpCodes.Ldc_I4_S && (sbyte)codes[index + 1].operand == (sbyte)global::NetNode.Flags.Bend) { bendFlagCheckFound = true; break; } } if (!bendFlagCheckFound) { Debug.LogError("NetNodeGroupDataPatch: bendFlagCheck not found. Cancelling transpiler!"); return(originalCodes); } CodeInstruction node5LocalVarLdLoc = null; for (; index < codes.Count; index++) { // IL_0359: ldfld class NetInfo/Node[] NetInfo::m_nodes // IL_05ed: ldloc.s 44 // IL_05ef: ldelem.ref // IL_05f0: stloc.s 45 if (codes[index].opcode == OpCodes.Ldfld && codes[index].operand == netInfoNodesField && TranspilerUtils.IsLdLoc(codes[index + 1]) && codes[index + 2].opcode == OpCodes.Ldelem_Ref && TranspilerUtils.IsStLoc(codes[index + 3])) { // IL_0361: stloc.s 22 node5LocalVarLdLoc = TranspilerUtils.BuildLdLocFromStLoc(codes[index + 3]); index += 4; break; } } if (node5LocalVarLdLoc == null) { Debug.LogError("NetNodeGroupDataPatch: node5 local var for bend not found. Cancelling transpiler!"); return(originalCodes); } var bendRenderCheckInserted = false; for (; index < codes.Count; index++) { // IL_0990: ldloc.s 40 // IL_0992: ldfld bool NetInfo/Node::m_directConnect // IL_0997: brfalse IL_0b19 if (codes[index].opcode == OpCodes.Ldc_I4 && (int)codes[index].operand == (int)NetInfo.ConnectGroup.AllGroups && codes[index + 1].opcode == OpCodes.And && codes[index + 2].opcode == OpCodes.Brfalse) { var labelIfFalse = codes[index + 2].operand; var insertionPosition = index + 3; // && NetNodeRenderPatch.ShouldRenderBendNodeLod(nodeID, node5) var renderCheckInstructions = new[] { new CodeInstruction(OpCodes.Ldarg_1), // nodeID new CodeInstruction(node5LocalVarLdLoc), new CodeInstruction(OpCodes.Call, netNodeRenderPatchShouldRenderBendNodeLodMethod), new CodeInstruction(OpCodes.Brfalse, labelIfFalse), }; renderCheckInstructions[0].labels.AddRange(codes[insertionPosition].labels); codes[insertionPosition].labels.Clear(); codes.InsertRange(insertionPosition, renderCheckInstructions); TranspilerUtils.LogDebug("Bend render check inserted"); index = insertionPosition + renderCheckInstructions.Length; bendRenderCheckInserted = true; break; } } if (!bendRenderCheckInserted) { Debug.LogError("NetNodeGroupDataPatch: Bend render check not inserted. Cancelling transpiler!"); return(originalCodes); } return(codes); }
public static bool PatchLanesAndSegments(ILGenerator il, List <CodeInstruction> codes, CodeInstruction infoLdInstruction, CodeInstruction segmentIdLdInstruction, ref int index) { var netInfoLanesField = typeof(NetInfo).GetField("m_lanes"); var netInfoSegmentsField = typeof(NetInfo).GetField("m_segments"); var segmentSkinsField = typeof(NetworkSkinManager).GetField("SegmentSkins", BindingFlags.Static | BindingFlags.Public); var networkSkinLanesField = typeof(NetworkSkin).GetField("m_lanes"); var networkSkinSegmentsField = typeof(NetworkSkin).GetField("m_segments"); if (netInfoLanesField == null || netInfoSegmentsField == null || segmentSkinsField == null || networkSkinLanesField == null || networkSkinSegmentsField == null) { Debug.LogError("Necessary field not found. Cancelling transpiler!"); return(false); } var beginLabel = il.DefineLabel(); codes[index].labels.Add(beginLabel); var customLanesLocalVar = il.DeclareLocal(typeof(NetInfo.Lane[])); customLanesLocalVar.SetLocalSymInfo("customLanes"); var customSegmentsLocalVar = il.DeclareLocal(typeof(NetInfo.Segment[])); customSegmentsLocalVar.SetLocalSymInfo("customSegments"); var customLanesInstructions = new[] { // NetInfo.Lane[] customLanes = info.m_lanes; new CodeInstruction(infoLdInstruction), // info new CodeInstruction(OpCodes.Ldfld, netInfoLanesField), new CodeInstruction(OpCodes.Stloc, customLanesLocalVar), // NetInfo.Segment[] customSegments = info.m_segments; new CodeInstruction(infoLdInstruction), // info new CodeInstruction(OpCodes.Ldfld, netInfoSegmentsField), new CodeInstruction(OpCodes.Stloc, customSegmentsLocalVar), // if (SegmentSkinManager.SegmentSkins[segmentID] != null) { new CodeInstruction(OpCodes.Ldsfld, segmentSkinsField), new CodeInstruction(segmentIdLdInstruction), // segmentID new CodeInstruction(OpCodes.Ldelem_Ref), new CodeInstruction(OpCodes.Brfalse_S, beginLabel), // customLanes = SegmentSkinManager.SegmentSkins[segmentID].m_lanes; new CodeInstruction(OpCodes.Ldsfld, segmentSkinsField), new CodeInstruction(segmentIdLdInstruction), // segmentID new CodeInstruction(OpCodes.Ldelem_Ref), new CodeInstruction(OpCodes.Ldfld, networkSkinLanesField), new CodeInstruction(OpCodes.Stloc, customLanesLocalVar), // customSegments = SegmentSkinManager.SegmentSkins[segmentID].m:segments; new CodeInstruction(OpCodes.Ldsfld, segmentSkinsField), new CodeInstruction(segmentIdLdInstruction), // segmentID new CodeInstruction(OpCodes.Ldelem_Ref), new CodeInstruction(OpCodes.Ldfld, networkSkinSegmentsField), new CodeInstruction(OpCodes.Stloc, customSegmentsLocalVar), // } }; codes.InsertRange(index, customLanesInstructions); index += customLanesInstructions.Length; // Replace all occurences of: // // info.m_lanes // -- with -- // customLanes // // info.m_segments // -- with -- // customSegments for (; index < codes.Count; index++) { if (TranspilerUtils.IsSameInstruction(codes[index], infoLdInstruction) && codes[index + 1].opcode == OpCodes.Ldfld) { if (codes[index + 1].operand == netInfoLanesField) { // It is important that we copy the labels from the existing instruction! // Otherwise "Label not marked" exception codes[index] = new CodeInstruction(codes[index]) { opcode = OpCodes.Ldloc, operand = customLanesLocalVar }; codes.RemoveAt(index + 1); } else if (codes[index + 1].operand == netInfoSegmentsField) { // It is important that we copy the labels from the existing instruction! // Otherwise "Label not marked" exception codes[index] = new CodeInstruction(codes[index]) { opcode = OpCodes.Ldloc, operand = customSegmentsLocalVar }; codes.RemoveAt(index + 1); } } } return(true); }
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); }