Beispiel #1
0
        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());
        }
Beispiel #4
0
        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)
            });
Beispiel #7
0
 protected override MethodInfo?ResolveMethodInfo() => AccessTools.DeclaredPropertyGetter(Type, Name);
Beispiel #8
0
 static MethodBase TargetMethod()
 {
     return(AccessTools.DeclaredPropertyGetter(typeof(LoadedLanguage), "Worker"));
 }