static IEnumerable <CodeInstruction> PatchTranspile(IEnumerable <CodeInstruction> instructions)
        {
            var codes = new List <CodeInstruction>(instructions);

            var searchCode  = new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(StationaryWeapon), "get_OperatorPosition"));
            int searchIndex = -1;

            for (var i = 0; i < codes.Count; i++)
            {
                if (codes[i].opcode == searchCode.opcode && codes[i].operand == searchCode.operand)
                {
                    searchIndex = i;
                    break;
                }
            }

            // Patch failed
            if (searchIndex == -1)
            {
                PatchLogger.LogTranspileSearchError(MethodBase.GetCurrentMethod());
                return(instructions);
            }

            // Look ahead and search for a bgt instruction (should be within the next 10 lines) and get its operand. We want the same label to jump to
            // for our code below.
            Label jumpToLabel = default(Label);
            bool  labelFound  = false;

            for (var i = searchIndex; i < codes.Count; i++)
            {
                if (codes[i].opcode == OpCodes.Bgt_S)
                {
                    jumpToLabel = (Label)codes[i].operand;
                    break;
                }
                labelFound = true;
            }

            if (!labelFound)
            {
                Debug.LogError("Label not found.");
                return(instructions);
            }

            // This is start of the instruction that we are interested in.
            searchIndex -= 2;

            List <CodeInstruction> newCodes = CodeGenerator.GenerateInstructions(new List <Code>()
            {
                new Code(OpCodes.Ldloc_3),
                new Code(OpCodes.Ldfld, typeof(StationaryWeaponLink), "Weapon"),
                new Code(OpCodes.Ldnull),
                new Code(OpCodes.Ceq),
                new Code(OpCodes.Brtrue_S, jumpToLabel)
            });

            codes.InsertRange(searchIndex, newCodes);

            return(codes.AsEnumerable());
        }
예제 #2
0
        //Define the event handlers.
        private static void OnChanged(object source, FileSystemEventArgs e)
        {
            var logger        = new PatchLogger(SERVICE_NAME);
            var deploymentSet = new DeploymentSet(Directory.GetFiles(Constants.POLL_DIRECTORY));

            if (deploymentSet.IsValid())
            {
                //Move files from POLL to PROCESSING directory
                FileMover.MoveFiles(Constants.POLL_DIRECTORY, Constants.INPROCESS_DIRECTORY);

                //Create FilesToProcess.txt
                FileWriter.WriteFilesToProcess(deploymentSet.AllFiles);

                //Run PatchBuilder.NET to create package
                RunPatchBuilder(@"C:\PRODUCTION\", "ServiceDeployment");

                //Move files from PROCESSING directory to patchfile
                FileMover.MoveFiles(Constants.INPROCESS_DIRECTORY, Constants.PATCH_FILES_DIRECTORY);

                //Execute DeployPatch.bat
                if (System.IO.File.Exists(Constants.BATCH_FILE_NAME))
                {
                    RunBatchFile(@"C:\PRODUCTION\");
                }
            }
            else
            {
                logger.EventLog.WriteEntry("Deployment set is invalid. Nothing deployed.", EventLogEntryType.Error);
            }
        }
예제 #3
0
        static IEnumerable <CodeInstruction> PatchTranspile(ILGenerator generator, IEnumerable <CodeInstruction> instructions)
        {
            var codes = new List <CodeInstruction>(instructions);

            // Search for code where backend.Session.getProfile() is called.
            var searchCode  = new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(PatcherConstants.SessionInterfaceType, "get_Profile"));
            int searchIndex = -1;

            for (var i = 0; i < codes.Count; i++)
            {
                if (codes[i].opcode == searchCode.opcode && codes[i].operand == searchCode.operand)
                {
                    searchIndex = i;
                    break;
                }
            }

            // Patch failed.
            if (searchIndex == -1)
            {
                PatchLogger.LogTranspileSearchError(MethodBase.GetCurrentMethod());
                return(instructions);
            }

            // Move back by 4. This is the start of this method call.
            // Note that we don't actually want to replace the code at searchIndex (which is a Ldloc0) since there is a branch
            // instruction prior to this instruction that leads to it and we can reuse a Ldloc0 instruction here.
            searchIndex -= 4;

            Label brFalseLabel = generator.DefineLabel();
            Label brLabel      = generator.DefineLabel();

            List <CodeInstruction> newCodes = CodeGenerator.GenerateInstructions(new List <Code>()
            {
                new Code(OpCodes.Ldarg_0),
                new Code(OpCodes.Ldfld, typeof(ClientApplication), "_backEnd"),
                new Code(OpCodes.Callvirt, PatcherConstants.BackendInterfaceType, "get_Session"),
                new Code(OpCodes.Ldarg_0),
                new Code(OpCodes.Ldfld, typeof(MainApplication), "esideType_0"),
                new Code(OpCodes.Ldc_I4_0),
                new Code(OpCodes.Ceq),
                new Code(OpCodes.Brfalse, brFalseLabel),
                new Code(OpCodes.Callvirt, PatcherConstants.SessionInterfaceType, "get_Profile"),
                new Code(OpCodes.Br, brLabel),
                new CodeWithLabel(OpCodes.Callvirt, brFalseLabel, PatcherConstants.SessionInterfaceType, "get_ProfileOfPet"),
                new CodeWithLabel(OpCodes.Stfld, brLabel, typeof(MainApplication).GetNestedTypes(BindingFlags.NonPublic).Single(IsTargetNestedType), "profile")
            });

            codes.RemoveRange(searchIndex + 1, 5);
            codes.InsertRange(searchIndex + 1, newCodes);

            return(codes.AsEnumerable());
        }
예제 #4
0
        static IEnumerable <CodeInstruction> PatchTranspile(ILGenerator generator, IEnumerable <CodeInstruction> instructions)
        {
            var codes = new List <CodeInstruction>(instructions);

            // Search for code where backend.Session.getProfile() is called.
            var searchCode  = new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(PatcherConstants.SessionInterfaceType, "get_Profile"));
            int searchIndex = -1;

            for (var i = 0; i < codes.Count; i++)
            {
                if (codes[i].opcode == searchCode.opcode && codes[i].operand == searchCode.operand)
                {
                    searchIndex = i;
                    break;
                }
            }

            // Patch failed.
            if (searchIndex == -1)
            {
                PatchLogger.LogTranspileSearchError(MethodBase.GetCurrentMethod());
                return(instructions);
            }

            // Move back by 3. This is the start of IL chain that we're interested in.
            searchIndex -= 3;

            Label brFalseLabel = generator.DefineLabel();
            Label brLabel      = generator.DefineLabel();

            List <CodeInstruction> newCodes = CodeGenerator.GenerateInstructions(new List <Code>()
            {
                new Code(OpCodes.Ldloc_1),
                new Code(OpCodes.Ldfld, typeof(ClientApplication), "_backEnd"),
                new Code(OpCodes.Callvirt, PatcherConstants.BackendInterfaceType, "get_Session"),
                new Code(OpCodes.Ldloc_1),
                new Code(OpCodes.Ldfld, typeof(MainApplication), "esideType_0"),
                new Code(OpCodes.Ldc_I4_0),
                new Code(OpCodes.Ceq),
                new Code(OpCodes.Brfalse, brFalseLabel),
                new Code(OpCodes.Callvirt, PatcherConstants.SessionInterfaceType, "get_Profile"),
                new Code(OpCodes.Br, brLabel),
                new CodeWithLabel(OpCodes.Callvirt, brFalseLabel, PatcherConstants.SessionInterfaceType, "get_ProfileOfPet"),
                new CodeWithLabel(OpCodes.Ldc_I4_1, brLabel)
            });

            codes.RemoveRange(searchIndex, 5);
            codes.InsertRange(searchIndex, newCodes);

            return(codes.AsEnumerable());
        }
예제 #5
0
        static IEnumerable <CodeInstruction> PatchTranspile(ILGenerator generator, IEnumerable <CodeInstruction> instructions)
        {
            var codes = new List <CodeInstruction>(instructions);

            var searchCode  = new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(PatcherConstants.ExfilPointManagerType, "EligiblePoints", new System.Type[] { typeof(Profile) }));
            int searchIndex = -1;

            for (var i = 0; i < codes.Count; i++)
            {
                if (codes[i].opcode == searchCode.opcode && codes[i].operand == searchCode.operand)
                {
                    searchIndex = i;
                    break;
                }
            }

            // Patch failed.
            if (searchIndex == -1)
            {
                PatchLogger.LogTranspileSearchError(MethodBase.GetCurrentMethod());
                return(instructions);
            }

            searchIndex -= 3;

            Label brFalseLabel = generator.DefineLabel();
            Label brLabel      = generator.DefineLabel();
            List <CodeInstruction> newCodes = CodeGenerator.GenerateInstructions(new List <Code>()
            {
                new Code(OpCodes.Ldarg_0),
                new Code(OpCodes.Call, PatcherConstants.LocalGameType.BaseType, "get_Profile_0"),
                new Code(OpCodes.Ldfld, typeof(Profile), "Info"),
                new Code(OpCodes.Ldfld, PatcherConstants.ProfileInfoType, "Side"),
                new Code(OpCodes.Ldc_I4_4),
                new Code(OpCodes.Ceq),
                new Code(OpCodes.Brfalse, brFalseLabel),
                new Code(OpCodes.Call, PatcherConstants.ExfilPointManagerType, "get_Instance"),
                new Code(OpCodes.Ldarg_0),
                new Code(OpCodes.Ldfld, PatcherConstants.LocalGameType.BaseType, "gparam_0"),
                new Code(OpCodes.Box, typeof(PlayerOwner)),
                new Code(OpCodes.Callvirt, typeof(PlayerOwner), "get_Player"),
                new Code(OpCodes.Callvirt, typeof(Player), "get_Position"),
                new Code(OpCodes.Ldarg_0),
                new Code(OpCodes.Call, PatcherConstants.LocalGameType.BaseType, "get_Profile_0"),
                new Code(OpCodes.Ldfld, typeof(Profile), "Id"),
                new Code(OpCodes.Callvirt, PatcherConstants.ExfilPointManagerType, "ScavExfiltrationClaim", new System.Type[] { typeof(Vector3), typeof(string) }),
                new Code(OpCodes.Call, PatcherConstants.ExfilPointManagerType, "get_Instance"),
                new Code(OpCodes.Call, PatcherConstants.ExfilPointManagerType, "get_Instance"),
                new Code(OpCodes.Ldarg_0),
                new Code(OpCodes.Call, PatcherConstants.LocalGameType.BaseType, "get_Profile_0"),
                new Code(OpCodes.Ldfld, typeof(Profile), "Id"),
                new Code(OpCodes.Callvirt, PatcherConstants.ExfilPointManagerType, "GetScavExfiltrationMask"),
                new Code(OpCodes.Ldarg_0),
                new Code(OpCodes.Call, PatcherConstants.LocalGameType.BaseType, "get_Profile_0"),
                new Code(OpCodes.Ldfld, typeof(Profile), "Id"),
                new Code(OpCodes.Callvirt, PatcherConstants.ExfilPointManagerType, "ScavExfiltrationClaim", new System.Type[] { typeof(int), typeof(string) }),
                new Code(OpCodes.Br, brLabel),
                new CodeWithLabel(OpCodes.Call, brFalseLabel, PatcherConstants.ExfilPointManagerType, "get_Instance"),
                new Code(OpCodes.Ldarg_0),
                new Code(OpCodes.Call, PatcherConstants.LocalGameType.BaseType, "get_Profile_0"),
                new Code(OpCodes.Callvirt, PatcherConstants.ExfilPointManagerType, "EligiblePoints", new System.Type[] { typeof(Profile) }),
                new CodeWithLabel(OpCodes.Stloc_0, brLabel)
            });

            codes.RemoveRange(searchIndex, 5);
            codes.InsertRange(searchIndex, newCodes);

            return(codes.AsEnumerable());
        }
예제 #6
0
        static IEnumerable <CodeInstruction> PatchTranspile(ILGenerator generator, IEnumerable <CodeInstruction> instructions)
        {
            var codes = new List <CodeInstruction>(instructions);

            // Search for code where this.Speaker is called for the first time.
            var searchCode  = new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(Player), "Speaker"));
            int searchIndex = -1;

            for (var i = 0; i < codes.Count; i++)
            {
                if (codes[i].opcode == searchCode.opcode && codes[i].operand == searchCode.operand)
                {
                    searchIndex = i;
                    break;
                }
            }

            // Patch failed
            if (searchIndex == -1)
            {
                PatchLogger.LogTranspileSearchError(MethodBase.GetCurrentMethod());
                return(instructions);
            }

            // We expected the next three callvirt instructions are the following.
            // TagBank Play
            // TaggedClip Match
            // Speaker Shut
            // We are interested in each.
            int callVirtCount = 0;
            int playIndex = -1, matchIndex = -1, lastCallIndex = -1;

            for (var i = searchIndex; i < codes.Count; i++)
            {
                if (codes[i].opcode == OpCodes.Callvirt)
                {
                    switch (callVirtCount)
                    {
                    case 0:
                        playIndex = i;
                        break;

                    case 1:
                        matchIndex = i;
                        break;

                    case 2:
                        lastCallIndex = i;
                        break;

                    default:
                        Debug.LogError("Mismatched callvirt instruction count.");
                        break;
                    }
                    searchIndex = i;
                    callVirtCount++;
                    if (callVirtCount > 2)
                    {
                        break;
                    }
                }
            }

            if (playIndex == -1 || matchIndex == -1 || lastCallIndex == -1)
            {
                PatchLogger.LogPatchErrorWithMessage(MethodBase.GetCurrentMethod(), "Could not callvirt instructions.");
                return(instructions);
            }

            Label skipLabel      = generator.DefineLabel();
            Label playPostLabel  = generator.DefineLabel();
            Label matchPostLabel = generator.DefineLabel();

            List <CodeInstruction> playCodes  = GetCodes(ref playPostLabel, ref skipLabel);
            List <CodeInstruction> matchCodes = GetCodes(ref matchPostLabel, ref skipLabel);

            // If either of the first two calls returns null, we want to skip to the instruction after Speak Shut instruction.
            codes[playIndex + 1].labels.Add(playPostLabel);
            codes[matchIndex + 1].labels.Add(matchPostLabel);
            codes[lastCallIndex + 1].labels.Add(skipLabel);

            codes.InsertRange(playIndex + 1, playCodes);
            codes.InsertRange(matchIndex + playCodes.Count + 1, matchCodes);

            return(codes.AsEnumerable());
        }