Example #1
0
        public static bool Mod(this InstallerWindow ins, string file)
        {
            string     inPath  = Path.Combine(ins.MainModDir, file);
            string     outPath = Path.Combine(ins.MainModDir, file + ".tmp.dll");
            MonoModder monomod = new MonoModder()
            {
                InputPath  = inPath,
                OutputPath = outPath
            };

            monomod.SetupETGModder();
            using (FileStream fileStream = File.Open(LogPath, FileMode.Append)) {
                using (StreamWriter streamWriter = new StreamWriter(fileStream)) {
                    monomod.Logger  = (string s) => ins.OnActivity();
                    monomod.Logger += (string s) => streamWriter.WriteLine(s);
                    // Unity wants .mdbs
                    // monomod.WriterParameters.SymbolWriterProvider = new Mono.Cecil.Mdb.MdbWriterProvider();
                    string db    = Path.ChangeExtension(inPath, "pdb");
                    string dbTmp = Path.ChangeExtension(outPath, "pdb");
                    if (!File.Exists(db))
                    {
                        db    = inPath + ".mdb";
                        dbTmp = outPath + ".mdb";
                    }
#if !DEBUG
RETRY:
                    try {
#endif
                    monomod.Read();                                        // Read main module first
                    monomod.ReadMod(Directory.GetParent(inPath).FullName); // ... then mods
                    monomod.MapDependencies();                             // ... then all dependencies
                    monomod.AutoPatch();                                   // Patch,
                    monomod.Write();                                       // and write.
                    monomod.Dispose();                                     // Finally, dispose, because file access happens now.

                    File.Delete(inPath);
                    File.Move(outPath, inPath);
                    if (File.Exists(db))
                    {
                        File.Delete(db);
                    }
                    if (File.Exists(dbTmp))
                    {
                        File.Move(dbTmp, db);
                    }
                    return(true);

#if !DEBUG
                } catch (ArgumentException e) {
                    monomod.Dispose();
                    if (File.Exists(db))
                    {
                        File.Delete(db);
                        if (File.Exists(dbTmp))
                        {
                            File.Delete(dbTmp);
                        }
                        goto RETRY;
                    }
                    ins.LogLine(e.ToString());
                    throw;
                    return(false);
                } catch (Exception e) {
                    monomod.Dispose();
                    ins.LogLine(e.ToString());
                    throw;
                    return(false);
                }
#endif
                }
            }
        }
Example #2
0
            public void Install(Installer installer, bool leave_mmdlls = false)
            {
                var managed = installer.ManagedDir;

                if (HasPluginsDir)
                {
                    _InstallPlugins(installer.PluginsDir);
                }
                if (RequiresPatchedExe)
                {
                    installer.PatchExe();
                }

                using (StreamWriter patches_info_writer = new StreamWriter(File.OpenWrite(installer.PatchesInfoFile))) {
                    patches_info_writer.WriteLine($"{Name} {VersionName}");
                }

                _Install("assembly", Assemblies, managed);
                _Install("MonoMod patch DLL", PatchDLLs, managed);
                _Install("file", OtherFiles, managed, subdir: true);
                _Install("directory", Dirs, managed, subdir: true);

                foreach (var patch_target in Metadata?.OrderedTargets ?? installer.Downloader.GungeonMetadata.ViablePatchTargets)
                {
                    var patch_target_dll = Path.Combine(managed, $"{patch_target}.dll");
                    var patch_target_tmp = Path.Combine(managed, $"{patch_target}{TMP_PATCH_SUFFIX}");

                    var modder = new MonoModder {
                        InputPath  = patch_target_dll,
                        OutputPath = patch_target_tmp
                    };

                    if (Metadata != null && Metadata.RelinkMap != null)
                    {
                        Dictionary <string, string> rmap;
                        if (Metadata.RelinkMap.TryGetValue(patch_target, out rmap))
                        {
                            _Logger.Info($"Reading component relink map for target {patch_target}");
                            foreach (var pair in rmap)
                            {
                                ModuleDefinition module;
                                if (!modder.DependencyCache.TryGetValue(pair.Value, out module))
                                {
                                    var path = Path.Combine(managed, pair.Value);
                                    _Logger.Debug($"Dependency not in cache: {pair.Value} ({path})");
                                    module = modder.DependencyCache[pair.Value] = ModuleDefinition.ReadModule(path);
                                }

                                _Logger.Debug($"Mapping {pair.Key} => {pair.Value}");
                                modder.RelinkModuleMap[pair.Key] = module;
                            }
                        }
                    }

                    modder.Read();

                    var found_mods = false;

                    foreach (var dll in PatchDLLs)
                    {
                        if (File.Exists(Path.Combine(managed, dll)) && dll.StartsWith($"{patch_target}.", StringComparison.InvariantCulture))
                        {
                            found_mods = true;
                            _Logger.Debug($"Using patch DLL: {dll}");

                            modder.ReadMod(Path.Combine(managed, dll));
                        }
                    }

                    if (!found_mods)
                    {
                        _Logger.Info($"Not patching {patch_target} because this component has no patches for it");
                        continue;
                    }

                    _Logger.Info($"Patching target: {patch_target}");

                    modder.MapDependencies();
                    modder.AutoPatch();
                    modder.Write();
                    modder.Dispose();

                    _Logger.Debug($"Replacing original ({patch_target_tmp} => {patch_target_dll})");
                    if (File.Exists(patch_target_dll))
                    {
                        File.Delete(patch_target_dll);
                    }
                    File.Move(patch_target_tmp, patch_target_dll);
                }

                if (!leave_mmdlls)
                {
                    foreach (var dll in PatchDLLs)
                    {
                        if (!File.Exists(Path.Combine(managed, dll)))
                        {
                            continue;
                        }

                        _Logger.Debug($"Cleaning up patch DLL {dll}");
                        File.Delete(Path.Combine(managed, dll));
                    }
                }

                _Logger.Debug($"Cleaning up patched DLL MDB/PDBs");
                foreach (var ent in Directory.GetFileSystemEntries(managed))
                {
                    if (ent.EndsWith($"{TMP_PATCH_SUFFIX}.mdb", StringComparison.InvariantCulture))
                    {
                        File.Delete(ent);
                    }
                }
            }