예제 #1
0
        private bool Inject(Actions action, ModuleDefMD assembly = null, bool save = true)
        {
            var assemblyPath = Path.Combine(currentManagedPath, selectedGame.AssemblyName);
            var backupAssemblyPath = $"{assemblyPath}.backup_";
            var originalAssemblyPath = $"{assemblyPath}.original_";

            if (File.Exists(assemblyPath))
            {
                if (assembly == null)
                {
                    try
                    {
                        assembly = ModuleDefMD.Load(File.ReadAllBytes(assemblyPath));
                    }
                    catch (Exception e)
                    {
                        Log.Print(e.Message);
                        return false;
                    }
                }

                var modManagerType = typeof(UnityModManager);

                switch (action)
                {
                    case Actions.Install:
                        try
                        {
                            if (!Utils.ParsePatchTarget(assembly, selectedGame.PatchTarget, out var targetMethod, out var insertionPlace))
                            {
                                return false;
                            }

                            Log.Print($"Backup for '{selectedGame.AssemblyName}'.");
                            File.Copy(assemblyPath, backupAssemblyPath, true);

                            if (!IsDirty(assembly))
                            {
                                File.Copy(assemblyPath, originalAssemblyPath, true);
                            }

                            CopyLibraries();

                            var modsPath = Path.Combine(currentGamePath, selectedGame.ModsDirectory);
                            if (!Directory.Exists(modsPath))
                            {
                                Directory.CreateDirectory(modsPath);
                            }

                            var typeInjectorInstalled = assembly.Types.FirstOrDefault(x => x.Name == modManagerType.Name);
                            if (typeInjectorInstalled != null)
                            {
                                if (!Inject(Actions.Remove, assembly, false))
                                {
                                    Log.Print("Installation failed. Can't uninstall the previous version.");
                                    return false;
                                }
                            }

                            Log.Print("Applying patch...");

                            if (!IsDirty(assembly))
                            {
                                MakeDirty(assembly);
                            }
                            
                            var modManagerDef = ModuleDefMD.Load(modManagerType.Module);
                            var modManager = modManagerDef.Types.First(x => x.Name == modManagerType.Name);
                            var modManagerModsDir = modManager.Fields.First(x => x.Name == nameof(UnityModManager.modsDirname));
                            modManagerModsDir.Constant.Value = selectedGame.ModsDirectory;
                            var modManagerModInfo = modManager.Fields.First(x => x.Name == nameof(UnityModManager.infoFilename));
                            modManagerModInfo.Constant.Value = selectedGame.ModInfo;
                            var modManagerPatchTarget = modManager.Fields.First(x => x.Name == nameof(UnityModManager.patchTarget));
                            modManagerPatchTarget.Constant.Value = selectedGame.PatchTarget;
                            modManagerDef.Types.Remove(modManager);
                            assembly.Types.Add(modManager);

                            var instr = OpCodes.Call.ToInstruction(modManager.Methods.First(x => x.Name == nameof(UnityModManager.Start)));
                            if (string.IsNullOrEmpty(insertionPlace) || insertionPlace == "after")
                            {
                                targetMethod.Body.Instructions.Insert(targetMethod.Body.Instructions.Count - 1, instr);
                            }
                            else if (insertionPlace == "before")
                            {
                                targetMethod.Body.Instructions.Insert(0, instr);
                            }

                            if (save)
                            {
                                assembly.Write(assemblyPath);
                                Log.Print("Installation was successful.");
                            }

                            installedVersion.Text = currentVersion.Text;
                            btnInstall.Enabled = false;
                            btnRemove.Enabled = true;
                            btnRestore.Enabled = File.Exists(originalAssemblyPath);

                            return true;
                        }
                        catch (Exception e)
                        {
                            Log.Print(e.Message);
                            if (!File.Exists(assemblyPath))
                                RestoreBackup();
                        }

                        break;

                    case Actions.Remove:
                        try
                        {
                            var modManagerInjected = assembly.Types.FirstOrDefault(x => x.Name == modManagerType.Name);
                            if (modManagerInjected != null)
                            {
                                Log.Print("Removing patch...");
                                var patchTarget = selectedGame.PatchTarget;
                                var modManagerPatchTarget = modManagerInjected.Fields.FirstOrDefault(x => x.Name == nameof(UnityModManager.patchTarget));
                                if (modManagerPatchTarget != null && !string.IsNullOrEmpty((string)modManagerPatchTarget.Constant.Value))
                                {
                                    patchTarget = (string)modManagerPatchTarget.Constant.Value;
                                }
                                if (!Utils.ParsePatchTarget(assembly, patchTarget, out var targetMethod, out var insertionPlace))
                                {
                                    return false;
                                }

                                var instr = OpCodes.Call.ToInstruction(modManagerInjected.Methods.First(x => x.Name == nameof(UnityModManager.Start)));
                                for (int i = 0; i < targetMethod.Body.Instructions.Count; i++)
                                {
                                    if (targetMethod.Body.Instructions[i].OpCode == instr.OpCode
                                        && targetMethod.Body.Instructions[i].Operand == instr.Operand)
                                    {
                                        targetMethod.Body.Instructions.RemoveAt(i);
                                        break;
                                    }
                                }

                                assembly.Types.Remove(modManagerInjected);

                                if (!IsDirty(assembly))
                                {
                                    MakeDirty(assembly);
                                }

                                if (save)
                                {
                                    assembly.Write(assemblyPath);
                                    Log.Print("Removal was successful.");
                                }

                                installedVersion.Text = "-";
                                btnInstall.Enabled = true;
                                btnRemove.Enabled = false;
                            }

                            return true;
                        }
                        catch (Exception e)
                        {
                            Log.Print(e.Message);
                            if (!File.Exists(assemblyPath))
                                RestoreBackup();
                        }

                        break;
                }
            }
            else
            {
                Log.Print($"'{assemblyPath}' not found.");
                return false;
            }

            return false;
        }
예제 #2
0
        private void CheckState()
        {
            if (!IsValid(selectedGame))
            {
                InactiveForm();
                return;
            }

            btnInstall.Text = "Install";

            currentGamePath = "";
            if (!param.ExtractGamePath(selectedGame.Name, out var result) || !Directory.Exists(result))
            {
                result = FindGameFolder(selectedGame.Folder);
                if (string.IsNullOrEmpty(result))
                {
                    InactiveForm();
                    btnOpenFolder.ForeColor = System.Drawing.Color.FromArgb(192, 0, 0);
                    btnOpenFolder.Text = "Select Game Folder";
                    folderBrowserDialog.SelectedPath = null;
                    Log.Print($"Game folder '{selectedGame.Folder}' not found.");
                    return;
                }
                Log.Print($"Game folder detected as '{result}'.");
                param.SaveGamePath(selectedGame.Name, result);
            }
            else
            {
                Log.Print($"Game folder set as '{result}'.");
            }
            currentGamePath = result;
            btnOpenFolder.ForeColor = System.Drawing.Color.Black;
            btnOpenFolder.Text = new DirectoryInfo(result).Name;
            folderBrowserDialog.SelectedPath = currentGamePath;
            currentManagedPath = FindManagedFolder(currentGamePath);

            var assemblyPath = Path.Combine(currentManagedPath, selectedGame.AssemblyName);
            ModuleDefMD assembly = null;

            var originalAssemblyPath = $"{assemblyPath}.original_";
            btnRestore.Enabled = File.Exists(originalAssemblyPath);

            if (File.Exists(assemblyPath))
            {
                try
                {
                    assembly = ModuleDefMD.Load(File.ReadAllBytes(assemblyPath));
                }
                catch (Exception e)
                {
                    InactiveForm();
                    Log.Print(e.Message);
                    return;
                }
            }
            else
            {
                InactiveForm();
                Log.Print($"'{selectedGame.AssemblyName}' not found.");
                return;
            }

            tabControl.TabPages[1].Enabled = true;

            var modManagerType = typeof(UnityModManager);
            var modManagerDefInjected = assembly.Types.FirstOrDefault(x => x.Name == modManagerType.Name);
            if (modManagerDefInjected != null)
            {
                btnInstall.Text = "Update";
                btnInstall.Enabled = false;
                btnRemove.Enabled = true;

                var versionString = modManagerDefInjected.Fields.First(x => x.Name == nameof(UnityModManager.version)).Constant.Value.ToString();
                var version2 = Utils.ParseVersion(versionString);
                installedVersion.Text = versionString;
                if (version != version2)
                { 
                    btnInstall.Enabled = true;
                }
            }
            else
            {
                installedVersion.Text = "-";
                btnInstall.Enabled = true;
                btnRemove.Enabled = false;
            }

            btnRestore.Enabled = IsDirty(assembly) && btnRestore.Enabled;
        }