예제 #1
0
        public bool InstallSelectedMods(string _gameFolder, List <string> modsToInstall)
        {
            //LLBMM Paths
            string llbmm_rootDir = Directory.GetCurrentDirectory();
            string llbmm_modsDir = Path.Combine(llbmm_rootDir, "mods");

            //Game Folder Paths
            string game_managedDir  = PathHelper.Get().GetLLBGameManagedDirPath(_gameFolder);
            string game_tempDir     = Path.Combine(game_managedDir, "temp");
            string game_mainAsmFile = Path.Combine(game_managedDir, "Assembly-CSharp.dll");

            List <string> modsToInstallPaths = new List <string>(); //Will hold the file paths for the mods we recieved from the pendingMods ListBox.

            var i        = 0;
            var _modList = modsToInstall;

            foreach (var mod in _modList) //Checks if a mods file exists and adds its path to a list if it does.
            {
                string modPath = Path.Combine(llbmm_modsDir, mod.ToString(), mod.ToString() + ".dll");
                if (File.Exists(modPath))
                {
                    modsToInstallPaths.Add(modPath);
                }
                else
                {
                    MessageBox.Show("Skipping " + mod + ". Can't find mod file at" + modPath + ". Please ensure that the file path matches the one in this window", "Error");
                    modsToInstall.Remove(mod);
                }
                i++;
            }

            Directory.CreateDirectory(game_tempDir);
            try { File.Copy(game_mainAsmFile, Path.Combine(game_tempDir, "Assembly-CSharp.dll")); }
            catch
            {
                MessageBox.Show("Could not copy the main Assembly-CSharp.dll to temp folder. Terminating modding attempt. Make sure you've set the correct gamefolder in LLBMM, if it's correct then please verify your gamefiles through steam", "Error");
                return(false);
            }

            foreach (var path in modsToInstallPaths)
            {
                try { File.Copy(path, Path.Combine(game_tempDir, Path.GetFileName(path))); }
                catch
                {
                    MessageBox.Show("Skipping mod " + Path.GetFileNameWithoutExtension(path) + ". Could not copy mod file at" + path + " to temp folder", "Error");
                    modsToInstall.Remove(Path.GetFileNameWithoutExtension(path));
                }
            }
            if (!File.Exists(Path.Combine(game_managedDir, "ModMenu.dll")))
            {
                File.Copy(Path.Combine(llbmm_rootDir, "ModMenu", "ModMenu.dll"), Path.Combine(game_tempDir, "ModMenu.dll"));                                                             //If modmenu isn't installed try to install it
            }
            else
            {
                byte[] past    = File.ReadAllBytes(Path.Combine(game_managedDir, "ModMenu.dll"));
                byte[] present = File.ReadAllBytes(Path.Combine(llbmm_rootDir, "ModMenu", "ModMenu.dll"));

                if (past.Length != present.Length)
                {
                    CleanerHelper ch = new CleanerHelper();
                    ch.RemoveMod(_gameFolder, "ModMenu");
                    File.Copy(Path.Combine(llbmm_rootDir, "ModMenu", "ModMenu.dll"), Path.Combine(game_tempDir, "ModMenu.dll"));
                }
            }


            List <string> tempFiles = Directory.EnumerateFiles(game_tempDir, "*", SearchOption.AllDirectories).Where(s => s.EndsWith(".dll") && s.Count(c => c == '.') == 1).ToList();

            //Injection information
            string injectTypeName   = "LLScreen.ScreenIntroTitle"; // What type to inject into in Assemby-CSharp
            string injectMethodName = "CShowTitle";                // Method name in the type
            string modMethodNames   = "Initialize";

            //Init Resolver
            DefaultAssemblyResolver defaultAssemblyResolver = new DefaultAssemblyResolver();

            defaultAssemblyResolver.AddSearchDirectory(game_managedDir);
            defaultAssemblyResolver.AddSearchDirectory(game_tempDir);
            defaultAssemblyResolver.AddSearchDirectory(llbmm_rootDir); //Test om e kan fjærn den hær og den over
            ReaderParameters parameters = new ReaderParameters {
                AssemblyResolver = defaultAssemblyResolver
            };

            //Get the assembly definitions of the main file
            AssemblyDefinition _mainFileAssemblyDef = AssemblyDefinition.ReadAssembly(Path.Combine(game_tempDir, "Assembly-CSharp.dll"), parameters);
            ModuleDefinition   _mainFileMainModule  = _mainFileAssemblyDef.MainModule;

            //Get the assembly definitions of the mod files
            List <AssemblyDefinition> _modAssemblyList = new List <AssemblyDefinition>();

            foreach (string path in tempFiles)
            {
                if (path != Path.Combine(game_tempDir, "Assembly-CSharp.dll"))
                {
                    try { _modAssemblyList.Add(AssemblyDefinition.ReadAssembly(path)); }
                    catch
                    {
                        MessageBox.Show("Skipping mod " + Path.GetFileNameWithoutExtension(path) + ". Mod file " + path + " can't be injected", "Error");
                        modsToInstall.Remove(Path.GetFileNameWithoutExtension(path));
                    }
                }
            }

            TypeDefinition moddedClass = null;

            foreach (TypeDefinition type in _mainFileMainModule.Types)
            {
                if (type.Name == "Mods")
                {
                    moddedClass = type;
                }
            }
            if (moddedClass == null)
            {
                //create custom class that holds mod names
                moddedClass = new TypeDefinition("", "Mods", TypeAttributes.Public | TypeAttributes.Class, _mainFileMainModule.TypeSystem.Object);
                //insert custom class into assembly
                _mainFileMainModule.Types.Add(moddedClass);
                moddedClass.Methods.Add(new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, _mainFileMainModule.TypeSystem.Void));
            }

            foreach (var mod in modsToInstall)
            {
                moddedClass.Fields.Add(new FieldDefinition(mod.ToString(), FieldAttributes.Public, _mainFileMainModule.TypeSystem.String));
            }

            TypeDefinition injectPointType = _mainFileAssemblyDef.MainModule.GetType(injectTypeName);

            if (injectPointType == null || injectPointType.Methods == null)
            {
                MessageBox.Show("Bad inject point (Terminating modding session)");
                return(false);
            }

            foreach (MethodDefinition method in injectPointType.Methods)
            {
                if (method.Name == injectMethodName)
                {
                    try
                    {
                        ILProcessor ilproc = method.Body.GetILProcessor();
                        if (ilproc.Body.Instructions.Count > 0)
                        {
                            var modCount = 0;
                            //Create the instructions to inject
                            Instruction codePosition = ilproc.Body.Instructions[ilproc.Body.Instructions.Count - 1];
                            foreach (AssemblyDefinition modArrayDef in _modAssemblyList)
                            {
                                foreach (TypeDefinition modTypeDef in modArrayDef.MainModule.Types)
                                {
                                    foreach (MethodDefinition modMethodDef in modTypeDef.Methods)
                                    {
                                        if (modMethodDef.Name == modMethodNames)
                                        {
                                            Debug.WriteLine("Found " + modMethodDef.Name + " function");
                                            MethodReference callRef = _mainFileAssemblyDef.MainModule.ImportReference(modMethodDef);
                                            Debug.WriteLine("Found call reference " + callRef.ToString());
                                            ilproc.InsertBefore(codePosition, ilproc.Create(OpCodes.Call, callRef));
                                            modCount++;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    catch
                    {
                        MessageBox.Show("Can't get method or insert instructions. Try narrowing down what modfile is breaking the insertion (Terminating modding attempt)");
                        return(false);
                    }
                }
            }

            //save Assembly
            try { _mainFileAssemblyDef.Write(Path.Combine(game_tempDir, "Assembly-CSharp-modded.dll")); }
            catch
            {
                MessageBox.Show("Could not write assembly! Is the game running?", "Error");
                return(false);
            }

            _mainFileAssemblyDef.Dispose();
            foreach (var asm in _modAssemblyList)
            {
                asm.Dispose();
            }

            foreach (var mod in modsToInstall)
            {
                var path = Path.Combine(game_tempDir, mod + ".dll");
                if (path != Path.Combine(game_tempDir, "Assembly-CSharp.dll"))
                {
                    try { File.Copy(path, Path.Combine(game_managedDir, Path.GetFileName(path))); }
                    catch
                    {
                        File.Delete(Path.Combine(game_managedDir, Path.GetFileName(path)));
                        File.Copy(path, Path.Combine(game_managedDir, Path.GetFileName(path)));
                    }
                }

                var modResourcesDir = Path.Combine(llbmm_modsDir, mod, mod + "Resources");
                if (Directory.Exists(modResourcesDir))
                {
                    Directory.CreateDirectory(Path.Combine(game_managedDir, mod + "Resources"));

                    foreach (string dirPath in Directory.GetDirectories(modResourcesDir, "*", SearchOption.AllDirectories))
                    {
                        Directory.CreateDirectory(dirPath.Replace(modResourcesDir, Path.Combine(game_managedDir, mod + "Resources")));
                    }
                    foreach (string newPath in Directory.GetFiles(modResourcesDir, "*.*", SearchOption.AllDirectories))
                    {
                        File.Copy(newPath, newPath.Replace(modResourcesDir, Path.Combine(game_managedDir, mod + "Resources")), true);
                    }
                }
            }


            if (File.Exists(game_mainAsmFile))
            {
                File.Delete(game_mainAsmFile);
                File.Copy(Path.Combine(game_tempDir, "Assembly-CSharp-modded.dll"), game_mainAsmFile);
            }

            foreach (var mod in modsToInstall)
            {
                if (File.Exists(Path.Combine(game_managedDir, mod + "Resources", "ASMRewriter.exe")))
                {
                    RunRewriter(_gameFolder, Path.Combine(game_managedDir, mod + "Resources", "ASMRewriter.exe"));
                }
            }
            try
            {
                File.Copy(Path.Combine(game_tempDir, "ModMenu.dll"), Path.Combine(game_managedDir, "ModMenu.dll"));
                RunRewriter(_gameFolder, Path.Combine(llbmm_rootDir, "ModMenu", "ASMRewriter.exe"));
            }
            catch { }

            if (Directory.Exists(game_tempDir))
            {
                DirectoryInfo di = new DirectoryInfo(game_tempDir);
                foreach (DirectoryInfo dir in di.GetDirectories())
                {
                    dir.Delete(true);
                }
                foreach (FileInfo file in di.GetFiles())
                {
                    file.Delete();
                }
                Directory.Delete(game_tempDir);
            }

            Debug.WriteLine("Modding complete!");
            return(true);
        }