public static IEnumerable <CodeInstruction> GetDataToUseTranspiler(IEnumerable <CodeInstruction> instructions, ILGenerator ilGenerator) { var list = instructions.ToList(); var firstReturnNull = ilGenerator.DefineLabel(); var secondExpressionStart = ilGenerator.DefineLabel(); var originalEntry = ilGenerator.DefineLabel(); list[0].labels.Add(originalEntry); // if (SavedMemberType == SavedMemberType.Enum && (_typeDefinition == null || _typeDefinition.Type == typeof(object))) return null; list.InsertRange(0, new[] { new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "SavedMemberType")), new CodeInstruction(OpCodes.Ldc_I4_5), new CodeInstruction(OpCodes.Bne_Un_S, secondExpressionStart), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "_typeDefinition")), new CodeInstruction(OpCodes.Brfalse_S, firstReturnNull), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "_typeDefinition")), new CodeInstruction(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(TypeDefinitionBase), "Type")), new CodeInstruction(OpCodes.Ldtoken, typeof(object)), new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Type), nameof(Type.GetTypeFromHandle))), new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Type), "op_Equality")), new CodeInstruction(OpCodes.Brfalse_S, secondExpressionStart), new CodeInstruction(OpCodes.Ldnull) { labels = { firstReturnNull } }, new CodeInstruction(OpCodes.Ret), }); // // if (_typeDefinition is NullTypeDefinition) return null; list.InsertRange(16, new[] { new CodeInstruction(OpCodes.Ldarg_0) { labels = { secondExpressionStart } }, new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "_typeDefinition")), new CodeInstruction(OpCodes.Isinst, typeof(NullTypeDefinition)), // Basic new CodeInstruction(OpCodes.Brfalse_S, originalEntry), new CodeInstruction(OpCodes.Ldnull), new CodeInstruction(OpCodes.Ret) }); // return(list); }
public static IEnumerable <CodeInstruction> GetObjectWithIdTranspiler(IEnumerable <CodeInstruction> instructions, ILGenerator ilGenerator) { var list = instructions.ToList(); // if (result?.TypeDefinition is NullTypeDefinition) return null; var label0 = ilGenerator.DefineLabel(); var label1 = ilGenerator.DefineLabel(); var label2 = ilGenerator.DefineLabel(); var label3 = ilGenerator.DefineLabel(); list.InsertRange(10, new[] { new CodeInstruction(OpCodes.Ldloc_0) { labels = { label0 } }, new CodeInstruction(OpCodes.Brtrue_S, label1), new CodeInstruction(OpCodes.Ldnull), new CodeInstruction(OpCodes.Br_S, label2), new CodeInstruction(OpCodes.Ldloc_0) { labels = { label1 } }, new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(ObjectHeaderLoadData), "TypeDefinition")), new CodeInstruction(OpCodes.Isinst, typeof(NullTypeDefinition)) { labels = { label2 } }, // Basic new CodeInstruction(OpCodes.Brfalse_S, label3), new CodeInstruction(OpCodes.Ldnull), new CodeInstruction(OpCodes.Ret), /* * new CodeInstruction(OpCodes.Ldloc_0), * new CodeInstruction(OpCodes.Brfalse_S, label), * * new CodeInstruction(OpCodes.Ldloc_0), * new CodeInstruction(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(ObjectHeaderLoadData), "TypeDefinition")), * new CodeInstruction(OpCodes.Isinst, typeof(NullTypeDefinition)), // Basic * new CodeInstruction(OpCodes.Brfalse_S, label), * * new CodeInstruction(OpCodes.Ldnull), * new CodeInstruction(OpCodes.Ret), */ }); list[4].labels.Add(label0); list[list.Count - 2].labels.Add(label3); // return(list); }
private static IEnumerable <CodeInstruction> FixedUpdate_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator iL) { CodeMatcher codeMatcher = new CodeMatcher(instructions, iL) .MatchForward(true, new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(Player), "ApplyGamePauseState")), new CodeMatch(OpCodes.Ldarg_0), new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameMain), "_paused")), new CodeMatch(OpCodes.Brtrue) ); if (codeMatcher.IsInvalid) { NebulaModel.Logger.Log.Error("GameMain.FixedUpdate_Transpiler failed. Mod version not compatible with game version."); return(instructions); } object skipLabel1 = codeMatcher.Instruction.operand; codeMatcher .CreateLabelAt(codeMatcher.Pos + 1, out Label nextLabel1) .InsertAndAdvance( new CodeInstruction(OpCodes.Brfalse_S, nextLabel1), //_paused== false => enter loop new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))), new CodeInstruction(OpCodes.Brfalse_S, skipLabel1), //_paused== true && Multiplayer.Session == null => can pause, skip loop new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))), new CodeInstruction(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(MultiplayerSession), nameof(MultiplayerSession.CanPause))) ) .MatchForward(true, new CodeMatch(OpCodes.Ldarg_0), new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameMain), "_fullscreenPaused")), new CodeMatch(OpCodes.Brfalse) ); if (codeMatcher.IsInvalid) { NebulaModel.Logger.Log.Error("GameMain.FixedUpdate_Transpiler 2 failed. Mod version not compatible with game version."); return(instructions); } object skipLabel2 = codeMatcher.Instruction.operand; return(codeMatcher .Advance(1) .CreateLabel(out Label nextLabel2) //position of checking _fullscreenPausedUnlockOneFrame .InsertAndAdvance( new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))), new CodeInstruction(OpCodes.Brfalse_S, nextLabel2), //_fullscreenPaused && Multiplayer.Session == null => can pause, jump to next check new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(typeof(Multiplayer), nameof(Multiplayer.Session))), new CodeInstruction(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(MultiplayerSession), nameof(MultiplayerSession.CanPause))), new CodeInstruction(OpCodes.Brfalse_S, skipLabel2) //_fullscreenPaused && Multiplayer.Session.CanPause == fasle => can't pause, skip ) .InstructionEnumeration()); }
private static IEnumerable <CodeInstruction> RefreshAstroBox_Transpiler(IEnumerable <CodeInstruction> instructions) { //Change: this.gameData.factoryCount //To: GetFactoryCount() //Change: this.gameData.factories[i].planetId //To: GetPlanetData(i).id //Change: this.gameData.factories[i].planet //To: GetPlanetData(i) try { instructions = ReplaceFactoryCount(instructions); CodeMatcher matcher = new CodeMatcher(instructions) .MatchForward(false, new CodeMatch(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(PlanetFactory), nameof(PlanetFactory.planetId))) ) .Advance(-5); OpCode factoryIndexOp = matcher.InstructionAt(3).opcode; matcher.SetAndAdvance(factoryIndexOp, null) .InsertAndAdvance( new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(UIStatisticsWindow_Transpiler), nameof(UIStatisticsWindow_Transpiler.GetPlanetData))), new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PlanetData), nameof(PlanetData.id))) ) .RemoveInstructions(5) .MatchForward(false, new CodeMatch(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(PlanetFactory), nameof(PlanetFactory.planet))) ) .Advance(-5); factoryIndexOp = matcher.InstructionAt(3).opcode; matcher.SetAndAdvance(factoryIndexOp, null) .InsertAndAdvance( new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(UIStatisticsWindow_Transpiler), nameof(UIStatisticsWindow_Transpiler.GetPlanetData))) ) .RemoveInstructions(5); return(matcher.InstructionEnumeration()); } catch { NebulaModel.Logger.Log.Error("RefreshAstroBox_Transpiler failed. Mod version not compatible with game version."); return(instructions); } }
public void CampaignDescriptor_Test() { using var harmony = new HarmonyDisposable($"{nameof(DependencyInjectionTests)}.{nameof(CampaignDescriptor_Test)}"); harmony.Patch(AccessTools.DeclaredPropertyGetter(typeof(CampaignTime), "CurrentTicks"), prefix: new HarmonyMethod(DelegateHelper.GetMethodInfo(MockedCurrentTicks))); harmony.Patch(SymbolExtensions.GetMethodInfo(() => CharacterCode.CreateFrom((BasicCharacterObject)null !)), prefix: new HarmonyMethod(DelegateHelper.GetMethodInfo(MockedCreateFrom))); var hero = (Hero)FormatterServices.GetUninitializedObject(typeof(Hero)); #if e143 || e150 || e151 || e152 || e153 || e154 || e155 || e156 || e157 || e158 || e159 AccessTools.Field(typeof(Hero), "Name").SetValue(hero, new TextObject("TestHero")); #elif e1510 || e160 AccessTools.Property(typeof(Hero), "Name").SetValue(hero, new TextObject("TestHero")); #else #error ConstGameVersionWithPrefix is not handled! #endif AccessTools.Field(typeof(Hero), "_birthDay").SetValue(hero, CampaignTime.YearsFromNow(18)); var campaignDescriptor = CampaignDescriptor.Create(hero); Assert.NotNull(campaignDescriptor); Assert.True(campaignDescriptor is CampaignDescriptorImplementation); }
private static IEnumerable <CodeInstruction> InitializeTranspiler(IEnumerable <CodeInstruction> instructions, MethodBase method) { var instructionsList = instructions.ToList(); IEnumerable <CodeInstruction> ReturnDefault(string place) { Utils.DisplayUserWarning("Failed to patch WidgetPrefab.LoadFrom! {0}", place); return(instructionsList.AsEnumerable()); } var locals = method.GetMethodBody()?.LocalVariables; var typeLocal = locals?.FirstOrDefault(x => x.LocalType == typeof(Type)); if (typeLocal is null) { return(ReturnDefault("Local not found")); } var startIndex = -1; var endIndex = -1; for (var i = 0; i < instructionsList.Count - 5; i++) { if (!instructionsList[i + 0].IsLdarg(0)) { continue; } if (!instructionsList[i + 1].LoadsField(AccessTools.DeclaredField(typeof(WidgetFactory), "_builtinTypes"))) { continue; } if (!instructionsList[i + 2].IsLdloc()) { continue; } if (!instructionsList[i + 3].Calls(AccessTools.DeclaredPropertyGetter(typeof(MemberInfo), nameof(MemberInfo.Name)))) { continue; } if (!instructionsList[i + 4].IsLdloc()) { continue; } if (!instructionsList[i + 5].Calls(SymbolExtensions.GetMethodInfo((Dictionary <string, Type> d) => d.Add(null !, null !)))) { continue; } startIndex = i; endIndex = i + 5; break; } if (startIndex == -1) { return(ReturnDefault("Pattern not found")); } if (instructionsList[endIndex + 1].labels.Count == 0) { return(ReturnDefault("Jmp was not found")); } var jmpEnumerator = instructionsList[endIndex + 1].labels.FirstOrDefault(); // if (!this._builtinTypes.ContainsKey(type.Name)) instructionsList.InsertRange(startIndex, new List <CodeInstruction> { new(OpCodes.Ldarg_0), new(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(WidgetFactory), "_builtinTypes")), new(OpCodes.Ldloc, typeLocal.LocalIndex), new(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(MemberInfo), nameof(MemberInfo.Name))), new(OpCodes.Callvirt, SymbolExtensions.GetMethodInfo((Dictionary <string, Type> d) => d.ContainsKey(null !))), new(OpCodes.Brtrue_S, jmpEnumerator) });
protected override MethodInfo?ResolveMethodInfo() => AccessTools.DeclaredPropertyGetter(Type, Name);
static MethodBase TargetMethod() { return(AccessTools.DeclaredPropertyGetter(typeof(LoadedLanguage), "Worker")); }