/// <summary> /// Initializes the singleton intances of the mod manager. /// </summary> /// <param name="p_gmdGameMode">The current game mode.</param> /// <param name="p_eifEnvironmentInfo">The application's envrionment info.</param> /// <param name="p_mrpModRepository">The mod repository from which to get mods and mod metadata.</param> /// <param name="p_dmrMonitor">The download monitor to use to track task progress.</param> /// <param name="p_frgFormatRegistry">The <see cref="IModFormatRegistry"/> that contains the list /// of supported <see cref="IModFormat"/>s.</param> /// <param name="p_mrgModRegistry">The <see cref="ModRegistry"/> that contains the list /// of managed <see cref="IMod"/>s.</param> /// <param name="p_futFileUtility">The file utility class.</param> /// <param name="p_scxUIContext">The <see cref="SynchronizationContext"/> to use to marshall UI interactions to the UI thread.</param> /// <param name="p_ilgInstallLog">The install log tracking mod activations for the current game mode.</param> /// <param name="p_pmgPluginManager">The plugin manager to use to work with plugins.</param> /// <returns>The initialized mod manager.</returns> /// <exception cref="InvalidOperationException">Thrown if the mod manager has already /// been initialized.</exception> public static ModManager Initialize(IGameMode p_gmdGameMode, IEnvironmentInfo p_eifEnvironmentInfo, IModRepository p_mrpModRepository, DownloadMonitor p_dmrMonitor, ActivateModsMonitor p_ammMonitor, IModFormatRegistry p_frgFormatRegistry, ModRegistry p_mrgModRegistry, FileUtil p_futFileUtility, SynchronizationContext p_scxUIContext, IInstallLog p_ilgInstallLog, IPluginManager p_pmgPluginManager) { if (m_mmgCurrent != null) throw new InvalidOperationException("The Mod Manager has already been initialized."); m_mmgCurrent = new ModManager(p_gmdGameMode, p_eifEnvironmentInfo, p_mrpModRepository, p_dmrMonitor, p_ammMonitor, p_frgFormatRegistry, p_mrgModRegistry, p_futFileUtility, p_scxUIContext, p_ilgInstallLog, p_pmgPluginManager); return m_mmgCurrent; }
/// <summary> /// Creates a mod of the appropriate type from the specified file. /// Code copy&pasted from class ModRegistry /// </summary> /// <param name="p_strModPath">The path to the mod file.</param> /// <returns>A mod of the appropriate type from the specified file, if the type of hte mod /// can be determined; <c>null</c> otherwise.</returns> private static IMod CreateMod(string modPath, IModFormatRegistry formatRegistry, IGameMode gameMode) { List<KeyValuePair<FormatConfidence, IModFormat>> lstFormats = new List<KeyValuePair<FormatConfidence, IModFormat>>(); foreach (IModFormat mftFormat in formatRegistry.Formats) lstFormats.Add(new KeyValuePair<FormatConfidence, IModFormat>(mftFormat.CheckFormatCompliance(modPath), mftFormat)); lstFormats.Sort((x, y) => -x.Key.CompareTo(y.Key)); if (lstFormats[0].Key <= FormatConfidence.Convertible) { Console.WriteLine("failed to determine format for " + modPath); return null; } return lstFormats[0].Value.CreateMod(modPath, gameMode); }
/// <summary> /// A simple constructor that initializes the object with its dependencies. /// </summary> /// <param name="p_gmdGameMode">The current game mode.</param> /// <param name="p_eifEnvironmentInfo">The application's envrionment info.</param> /// <param name="p_mrpModRepository">The mod repository from which to get mods and mod metadata.</param> /// <param name="p_dmrMonitor">The download monitor to use to track task progress.</param> /// <param name="p_frgFormatRegistry">The <see cref="IModFormatRegistry"/> that contains the list /// of supported <see cref="IModFormat"/>s.</param> /// <param name="p_mdrManagedModRegistry">The <see cref="ModRegistry"/> that contains the list /// of managed <see cref="IMod"/>s.</param> /// <param name="p_futFileUtility">The file utility class.</param> /// <param name="p_scxUIContext">The <see cref="SynchronizationContext"/> to use to marshall UI interactions to the UI thread.</param> /// <param name="p_ilgInstallLog">The install log tracking mod activations for the current game mode.</param> /// <param name="p_pmgPluginManager">The plugin manager to use to work with plugins.</param> private ModManager(IGameMode p_gmdGameMode, IEnvironmentInfo p_eifEnvironmentInfo, IModRepository p_mrpModRepository, DownloadMonitor p_dmrMonitor, ActivateModsMonitor p_ammMonitor, IModFormatRegistry p_frgFormatRegistry, ModRegistry p_mdrManagedModRegistry, FileUtil p_futFileUtility, SynchronizationContext p_scxUIContext, IInstallLog p_ilgInstallLog, IPluginManager p_pmgPluginManager) { GameMode = p_gmdGameMode; EnvironmentInfo = p_eifEnvironmentInfo; m_rmmReadMeManager = new ReadMeManager(EnvironmentInfo.Settings.ModFolder[GameMode.ModeId]); ModRepository = p_mrpModRepository; FormatRegistry = p_frgFormatRegistry; ManagedModRegistry = p_mdrManagedModRegistry; InstallationLog = p_ilgInstallLog; InstallerFactory = new ModInstallerFactory(p_gmdGameMode, p_eifEnvironmentInfo, p_futFileUtility, p_scxUIContext, p_ilgInstallLog, p_pmgPluginManager, this); DownloadMonitor = p_dmrMonitor; ActivateModsMonitor = p_ammMonitor; ModAdditionQueue = new AddModQueue(p_eifEnvironmentInfo, this); AutoUpdater = new AutoUpdater(p_mrpModRepository, p_mdrManagedModRegistry, p_eifEnvironmentInfo); LoginTask = new LoginFormTask(this); }
/// <summary> /// Creates a mod of the appropriate type from the specified file. /// Code copy&pasted from class ModRegistry /// </summary> /// <param name="p_strModPath">The path to the mod file.</param> /// <returns>A mod of the appropriate type from the specified file, if the type of hte mod /// can be determined; <c>null</c> otherwise.</returns> private static IMod CreateMod(string modPath, IModFormatRegistry formatRegistry, IGameMode gameMode) { List <KeyValuePair <FormatConfidence, IModFormat> > lstFormats = new List <KeyValuePair <FormatConfidence, IModFormat> >(); foreach (IModFormat mftFormat in formatRegistry.Formats) { lstFormats.Add(new KeyValuePair <FormatConfidence, IModFormat>(mftFormat.CheckFormatCompliance(modPath), mftFormat)); } lstFormats.Sort((x, y) => - x.Key.CompareTo(y.Key)); if (lstFormats[0].Key <= FormatConfidence.Convertible) { Console.WriteLine("failed to determine format for " + modPath); return(null); } return(lstFormats[0].Value.CreateMod(modPath, gameMode)); }
/// <summary> /// Builds mods from a file. /// </summary> /// <remarks> /// This detects the type of file and takes appropriate action. /// </remarks> /// <param name="p_mfrFormats">The registry of supported mod formats.</param> /// <param name="p_strFilePath">The archive to build into a mod.</param> /// <param name="p_dlgConfirmOverwrite">The delegate to call to resolve conflicts with existing files.</param> /// <exception cref="ArgumentException">Thrown if the specified path is not an archive.</exception> public void BuildFromFile(IModFormatRegistry p_mfrFormats, string p_strFilePath, ConfirmOverwriteCallback p_dlgConfirmOverwrite) { ShowItemProgress = true; OverallProgressStepSize = 1; ItemProgressStepSize = 1; OverallProgressMaximum = 4; OverallMessage = "Building Mod..."; Sources srcModSource = Sources.Archive; if (String.IsNullOrEmpty(p_strFilePath) || !File.Exists(p_strFilePath)) { throw new ArgumentException("The given file path does not exist: " + p_strFilePath); } if (!Archive.IsArchive(p_strFilePath)) { Status = TaskStatus.Error; OnTaskEnded(String.Format("Cannot add {0}. File format is not recognized.", Path.GetFileName(p_strFilePath)), null); return; } Start(srcModSource, p_mfrFormats, p_strFilePath, p_dlgConfirmOverwrite); }
/// <summary> /// Searches for mods in the specified path, and loads /// any mods that are found into a registry. /// </summary> /// <param name="p_frgFormatRegistry">The <see cref="IModFormatRegistry"/> that contains the list /// of supported <see cref="IModFormat"/>s.</param> /// <param name="p_strSearchPath">The path in which to search for mod format assemblies.</param> /// <param name="p_booRecurse">Whether to check sub folders of <paramref name="p_strSearchPath"/> for mods.</param> /// <param name="p_gmdGameMode">The game mode for which to discover mods.</param> /// <param name="p_strExcludedSubDirectories">The list of subdirectories not to examine for mods.</param> /// <returns>A registry containing all of the discovered mods.</returns> public static ModRegistry DiscoverManagedMods(IModFormatRegistry p_frgFormatRegistry, IModCacheManager p_frgCacheManager, string p_strSearchPath, bool p_booRecurse, IEnvironmentInfo p_eiEnvironmentInfo, IGameMode p_gmdGameMode, params string[] p_strExcludedSubDirectories) { Trace.TraceInformation("Discovering Managed Mods..."); Trace.Indent(); Trace.TraceInformation("Looking in: {0}", p_strSearchPath); List <string> lstExludedPaths = new List <string>(); for (Int32 i = 0; i < p_strExcludedSubDirectories.Length; i++) { lstExludedPaths.Add((p_strExcludedSubDirectories[i].Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar).ToLower()); } ModRegistry mdrRegistry = new ModRegistry(p_frgFormatRegistry, p_gmdGameMode); string[] strMods = Directory.GetFiles(p_strSearchPath, "*", p_booRecurse ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); IMod modMod = null; List <string> modList = new List <String>(); bool booExcluded = false; foreach (string strMod in strMods) { string strModPath = strMod.ToLower(); booExcluded = false; if (strModPath.EndsWith(".meta")) { continue; } foreach (string strExclusion in lstExludedPaths) { if (strModPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar).StartsWith(strExclusion)) { booExcluded = true; break; } } if (booExcluded) { continue; } Trace.TraceInformation("Found: {0}", strMod); try { string strCachePath = p_frgCacheManager.GetCacheFilePath(strMod); modMod = mdrRegistry.CreateMod(strMod, strCachePath, p_gmdGameMode, p_eiEnvironmentInfo); } catch { modList.Add(strMod); modMod = null; } if (modMod == null) { continue; } mdrRegistry.m_oclRegisteredMods.Add(modMod); Trace.Indent(); Trace.TraceInformation("Registered."); Trace.Unindent(); } p_eiEnvironmentInfo.Settings.CacheOverhaulSetup = true; p_eiEnvironmentInfo.Settings.Save(); if (modList.Count > 0) { string strErrorMessage = "Error loading the following mods: " + Environment.NewLine; foreach (string modstr in modList) { strErrorMessage += modstr + Environment.NewLine; } MessageBox.Show(strErrorMessage, "Mod loading error", MessageBoxButtons.OK, MessageBoxIcon.Information); } Trace.Unindent(); return(mdrRegistry); }
/// <summary> /// A simple constructor that initializes the object with its dependencies. /// </summary> /// <param name="p_frgFormatRegistry">The <see cref="IModFormatRegistry"/> that contains the list /// of supported <see cref="IModFormat"/>s.</param> /// <param name="p_gmdGameMode">The <see cref="IGameMode"/> for which mods are to be registered.</param> public ModRegistry(IModFormatRegistry p_frgFormatRegistry, IGameMode p_gmdGameMode) { GameMode = p_gmdGameMode; FormatRegistry = p_frgFormatRegistry; RegisteredMods = new ReadOnlyObservableList <IMod>(m_oclRegisteredMods); }
/// <summary> /// A simple constructor that initializes the object with the given values. /// </summary> /// <param name="p_gmdGameMode">The game mode for which mods are being managed.</param> /// <param name="p_rmmReadMeManager">The ReadMe Manager info.</param> /// <param name="p_eifEnvironmentInfo">The application's envrionment info.</param> /// <param name="p_mrgModRegistry">The <see cref="ModRegistry"/> that contains the list of managed <see cref="IMod"/>s.</param> /// <param name="p_frgFormatRegistry">The <see cref="IModFormatRegistry"/> that contains the list /// of supported <see cref="IModFormat"/>s.</param> /// <param name="p_mrpModRepository">The mod repository from which to get mods and mod metadata.</param> /// <param name="p_uriPath">The path to the mod to add.</param> /// <param name="p_cocConfirmOverwrite">The delegate to call to resolve conflicts with existing files.</param> public AddModTask(IGameMode p_gmdGameMode, ReadMeManager p_rmmReadMeManager, IEnvironmentInfo p_eifEnvironmentInfo, ModRegistry p_mrgModRegistry, IModFormatRegistry p_frgFormatRegistry, IModRepository p_mrpModRepository, Uri p_uriPath, ConfirmOverwriteCallback p_cocConfirmOverwrite) { m_gmdGameMode = p_gmdGameMode; m_eifEnvironmentInfo = p_eifEnvironmentInfo; m_mrgModRegistry = p_mrgModRegistry; m_mfrModFormatRegistry = p_frgFormatRegistry; m_mrpModRepository = p_mrpModRepository; m_uriPath = p_uriPath; m_cocConfirmOverwrite = p_cocConfirmOverwrite; m_rmmReadMeManager = p_rmmReadMeManager; m_intLocalID = m_intCounter++; }
/// <summary> /// Initializes the singleton intances of the mod manager. /// </summary> /// <param name="p_gmdGameMode">The current game mode.</param> /// <param name="p_eifEnvironmentInfo">The application's envrionment info.</param> /// <param name="p_mrpModRepository">The mod repository from which to get mods and mod metadata.</param> /// <param name="p_dmrMonitor">The download monitor to use to track task progress.</param> /// <param name="p_mamMonitor">The mod activation monitor to use to track task progress.</param> /// <param name="p_frgFormatRegistry">The <see cref="IModFormatRegistry"/> that contains the list /// of supported <see cref="IModFormat"/>s.</param> /// <param name="p_mrgModRegistry">The <see cref="ModRegistry"/> that contains the list /// of managed <see cref="IMod"/>s.</param> /// <param name="p_futFileUtility">The file utility class.</param> /// <param name="p_scxUIContext">The <see cref="SynchronizationContext"/> to use to marshall UI interactions to the UI thread.</param> /// <param name="p_ilgInstallLog">The install log tracking mod activations for the current game mode.</param> /// <param name="p_pmgPluginManager">The plugin manager to use to work with plugins.</param> /// <returns>The initialized mod manager.</returns> /// <exception cref="InvalidOperationException">Thrown if the mod manager has already /// been initialized.</exception> public static ModManager Initialize(IGameMode p_gmdGameMode, IEnvironmentInfo p_eifEnvironmentInfo, IModRepository p_mrpModRepository, DownloadMonitor p_dmrMonitor, ModActivationMonitor p_mamMonitor, IModFormatRegistry p_frgFormatRegistry, ModRegistry p_mrgModRegistry, FileUtil p_futFileUtility, SynchronizationContext p_scxUIContext, IInstallLog p_ilgInstallLog, IPluginManager p_pmgPluginManager) { if (m_mmgCurrent != null) { throw new InvalidOperationException("The Mod Manager has already been initialized."); } m_mmgCurrent = new ModManager(p_gmdGameMode, p_eifEnvironmentInfo, p_mrpModRepository, p_dmrMonitor, p_mamMonitor, p_frgFormatRegistry, p_mrgModRegistry, p_futFileUtility, p_scxUIContext, p_ilgInstallLog, p_pmgPluginManager); return(m_mmgCurrent); }
/// <summary> /// Searches for mods in the specified path, and loads /// any mods that are found into a registry. /// </summary> /// <param name="p_frgFormatRegistry">The <see cref="IModFormatRegistry"/> that contains the list /// of supported <see cref="IModFormat"/>s.</param> /// <param name="p_strSearchPath">The path in which to search for mod format assemblies.</param> /// <param name="p_booRecurse">Whether to check sub folders of <paramref name="p_strSearchPath"/> for mods.</param> /// <param name="p_gmdGameMode">The game mode for which to discover mods.</param> /// <param name="p_strExcludedSubDirectories">The list of subdirectories not to examine for mods.</param> /// <returns>A registry containing all of the discovered mods.</returns> public static ModRegistry DiscoverManagedMods(IModFormatRegistry p_frgFormatRegistry, IModCacheManager p_frgCacheManager, string p_strSearchPath, bool p_booRecurse, IGameMode p_gmdGameMode, params string[] p_strExcludedSubDirectories) { Trace.TraceInformation("Discovering Managed Mods..."); Trace.Indent(); Trace.TraceInformation("Looking in: {0}", p_strSearchPath); List<string> lstExludedPaths = new List<string>(); for (Int32 i = 0; i < p_strExcludedSubDirectories.Length; i++) lstExludedPaths.Add((p_strExcludedSubDirectories[i].Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar).Trim(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar).ToLower()); ModRegistry mdrRegistry = new ModRegistry(p_frgFormatRegistry, p_gmdGameMode); string[] strMods = Directory.GetFiles(p_strSearchPath, "*", p_booRecurse ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); IMod modMod = null; List<string> modList = new List<String>(); bool booExcluded = false; foreach (string strMod in strMods) { string strModPath = strMod.ToLower(); booExcluded = false; foreach (string strExclusion in lstExludedPaths) if (strModPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar).StartsWith(strExclusion)) { booExcluded = true; break; } if (booExcluded) continue; Trace.TraceInformation("Found: {0}", strMod); try { string strCachePath = p_frgCacheManager.GetCacheFilePath(strMod); modMod = mdrRegistry.CreateMod(strMod, strCachePath, p_gmdGameMode); } catch { modList.Add(strMod); modMod = null; } if (modMod == null) continue; mdrRegistry.m_oclRegisteredMods.Add(modMod); Trace.Indent(); Trace.TraceInformation("Registered."); Trace.Unindent(); } if (modList.Count > 0) { string strErrorMessage = "Error loading the following mods: " + Environment.NewLine; foreach (string modstr in modList) { strErrorMessage += modstr + Environment.NewLine; } MessageBox.Show(strErrorMessage, "Mod loading error", MessageBoxButtons.OK, MessageBoxIcon.Information); } Trace.Unindent(); return mdrRegistry; }
/// <summary> /// A simple constructor that initializes the object with its dependencies. /// </summary> /// <param name="p_frgFormatRegistry">The <see cref="IModFormatRegistry"/> that contains the list /// of supported <see cref="IModFormat"/>s.</param> /// <param name="p_gmdGameMode">The <see cref="IGameMode"/> for which mods are to be registered.</param> public ModRegistry(IModFormatRegistry p_frgFormatRegistry, IGameMode p_gmdGameMode) { GameMode = p_gmdGameMode; FormatRegistry = p_frgFormatRegistry; RegisteredMods = new ReadOnlyObservableList<IMod>(m_oclRegisteredMods); }
/// <summary> /// Builds mods from an archive. /// </summary> /// <remarks> /// If the specified archive contains mods, they are simply extracted. Otherwise, the archive /// is examined to determine if it is already in a recognized format. If not, or if the archive /// spans multiple volumes, then the archive is repackaged. /// </remarks> /// <param name="p_mfrFormats">The registry of supported mod formats.</param> /// <param name="p_strArchivePath">The archive to build into a mod.</param> /// <param name="p_dlgConfirmOverwrite">The delegate to call to resolve conflicts with existing files.</param> /// <param name="p_strMessage">The message describing the state of the task.</param> /// <returns>The paths to the new mods.</returns> /// <exception cref="ArgumentException">Thrown if the specified path is not an archive.</exception> private IList <string> DoFromArchive(IModFormatRegistry p_mfrFormats, string p_strArchivePath, ConfirmOverwriteCallback p_dlgConfirmOverwrite, out string p_strMessage) { p_strMessage = null; Trace.TraceInformation(String.Format("[{0}] Adding mod from archive.", p_strArchivePath)); if (String.IsNullOrEmpty(p_strArchivePath) || !File.Exists(p_strArchivePath) || !Archive.IsArchive(p_strArchivePath)) { throw new ArgumentException("The specified path is not an archive file.", "p_strArchivePath"); } List <string> lstFoundMods = new List <string>(); List <string> lstModsInArchive = new List <string>(); ItemMessage = "Examining archive..."; ItemProgress = 0; ItemProgressMaximum = p_mfrFormats.Formats.Count; IModFormat mftDestFormat = null; try { using (SevenZipExtractor szeExtractor = Archive.GetExtractor(p_strArchivePath)) { if (Status == TaskStatus.Cancelling) { return(lstFoundMods); } ReadOnlyCollection <string> lstArchiveFiles = szeExtractor.ArchiveFileNames; foreach (IModFormat mftFormat in p_mfrFormats.Formats) { ItemMessage = String.Format("Examining archive for {0} mods...", mftFormat.Name); lstModsInArchive.AddRange(lstArchiveFiles.Where(x => mftFormat.Extension.Equals(Path.GetExtension(x), StringComparison.OrdinalIgnoreCase))); StepItemProgress(); if (Status == TaskStatus.Cancelling) { return(lstFoundMods); } } StepOverallProgress(); } if (lstModsInArchive.Count == 0) { ItemMessage = "Determining archive format..."; ItemProgress = 0; ItemProgressMaximum = p_mfrFormats.Formats.Count; List <KeyValuePair <FormatConfidence, IModFormat> > lstFormats = new List <KeyValuePair <FormatConfidence, IModFormat> >(); foreach (IModFormat mftFormat in p_mfrFormats.Formats) { lstFormats.Add(new KeyValuePair <FormatConfidence, IModFormat>(mftFormat.CheckFormatCompliance(p_strArchivePath), mftFormat)); StepItemProgress(); if (Status == TaskStatus.Cancelling) { return(lstFoundMods); } } lstFormats.Sort((x, y) => y.Key.CompareTo(x.Key)); if ((lstFormats.Count == 0) || (lstFormats[0].Key <= FormatConfidence.Convertible)) { return(lstFoundMods); } mftDestFormat = lstFormats[0].Value; } StepOverallProgress(); } catch (Exception ex) { MessageBox.Show("An error has occured with the following archive: " + p_strArchivePath + "\n\n ERROR: " + ex.Message); return(lstFoundMods); } string strTmpPath = null; try { using (SevenZipExtractor szeExtractor = Archive.GetExtractor(p_strArchivePath)) { if ((mftDestFormat != null) && (szeExtractor.VolumeFileNames.Count > 1) || (lstModsInArchive.Count > 0)) { ItemMessage = "Extracting archive..."; ItemProgress = 0; ItemProgressMaximum = szeExtractor.ArchiveFileNames.Count; strTmpPath = FileUtility.CreateTempDirectory(); szeExtractor.FileExtractionStarted += new EventHandler <FileInfoEventArgs>(Extractor_FileExtractionStarted); szeExtractor.FileExtractionFinished += new EventHandler <FileInfoEventArgs>(Extractor_FileExtractionFinished); try { szeExtractor.ExtractArchive(strTmpPath); } catch (FileNotFoundException ex) { Status = TaskStatus.Error; p_strMessage = ex.Message; return(lstFoundMods); } for (Int32 i = 0; i < lstModsInArchive.Count; i++) { lstModsInArchive[i] = Path.Combine(strTmpPath, lstModsInArchive[i]); } } else { lstModsInArchive.Add(p_strArchivePath); } } StepOverallProgress(); if (!String.IsNullOrEmpty(strTmpPath) && (mftDestFormat != null)) { //if we have extracted the file to do format shifting if (!mftDestFormat.SupportsModCompression) { return(lstFoundMods); } ItemMessage = "Compressing mod..."; ItemProgress = 0; ItemProgressMaximum = Directory.GetFiles(strTmpPath, "*", SearchOption.AllDirectories).Length; IModCompressor mcpCompressor = mftDestFormat.GetModCompressor(EnvironmentInfo); mcpCompressor.FileCompressionFinished += new CancelEventHandler(Compressor_FileCompressionFinished); string strDest = Path.Combine(GameModeInfo.ModDirectory, Path.GetFileName(p_strArchivePath)); strDest = Path.ChangeExtension(strDest, mftDestFormat.Extension); strDest = ConfirmOverwrite(p_dlgConfirmOverwrite, strDest); if (!String.IsNullOrEmpty(strDest)) { mcpCompressor.Compress(strTmpPath, strDest); lstFoundMods.Add(strDest); } } else { ItemMessage = "Copying mods..."; ItemProgress = 0; ItemProgressMaximum = lstModsInArchive.Count; foreach (string strMod in lstModsInArchive) { if (Status == TaskStatus.Cancelling) { return(lstFoundMods); } ItemMessage = String.Format("Copying mod {0}...", Path.GetFileName(strMod)); string strDest = Path.Combine(GameModeInfo.ModDirectory, Path.GetFileName(strMod)); strDest = ConfirmOverwrite(p_dlgConfirmOverwrite, strDest); if (!String.IsNullOrEmpty(strDest)) { if (string.Equals(strMod, strDest, StringComparison.OrdinalIgnoreCase)) { throw new FileNotFoundException("You can't add a mod directly from the NMM Mods folder, please move it somewhere else before adding it to the manager!"); } File.Copy(strMod, strDest, true); lstFoundMods.Add(strDest); } StepItemProgress(); } } StepOverallProgress(); } catch (FileNotFoundException ex) { MessageBox.Show("Archive: " + p_strArchivePath + "\n\n ERROR: " + ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); return(lstFoundMods); } finally { if (!String.IsNullOrEmpty(strTmpPath)) { FileUtil.ForceDelete(strTmpPath); } } return(lstFoundMods); }
static int DoInstall(string game, string filename, string installationPath, string profilePath, string gamePath, List <string> additionalSearchPaths, string seVersion, ref string errorString) { if (game == null) { errorString = "no game specified"; return(1); } if (filename == null) { errorString = "no file specified"; return(1); } if (profilePath == null) { errorString = "no profile path specified"; return(1); } if (gamePath == null) { errorString = "no game path specified"; return(1); } try { EnvironmentInfo environmentInfo = new EnvironmentInfo(Properties.Settings.Default); string exeLocation = Assembly.GetExecutingAssembly().Location; string exePath = System.IO.Path.GetDirectoryName(exeLocation); string[] gameModes = Directory.GetFiles(Path.Combine(exePath, "GameModes"), String.Format("{0}.dll", game)); if (gameModes.Count() == 0) { errorString = "unknown game"; return(1); } Assembly gameAssembly = Assembly.LoadFrom(gameModes[0]); IGameModeFactory gameModeFactory = null; Type[] exportedTypes = gameAssembly.GetExportedTypes(); foreach (Type type in exportedTypes) { if (typeof(IGameModeFactory).IsAssignableFrom(type) && !type.IsAbstract) { ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(EnvironmentInfo) }); gameModeFactory = (IGameModeFactory)constructor.Invoke(new Object[] { environmentInfo }); } } if (gameModeFactory == null) { errorString = "invalid game"; return(1); } string str7zPath = Path.Combine(environmentInfo.ProgrammeInfoDirectory, environmentInfo.Is64BitProcess ? "7z-64bit.dll" : "7z-32bit.dll"); SevenZipCompressor.SetLibraryPath(str7zPath); FileUtil fileUtil = new NexusFileUtil(environmentInfo); environmentInfo.Settings.InstallationPaths[gameModeFactory.GameModeDescriptor.ModeId] = installationPath; environmentInfo.Settings.ModFolder[gameModeFactory.GameModeDescriptor.ModeId] = installationPath; // environmentInfo.Settings.InstallInfoFolder[gameModeFactory.GameModeDescriptor.ModeId] = environmentInfo.TemporaryPath; environmentInfo.Settings.InstallInfoFolder[gameModeFactory.GameModeDescriptor.ModeId] = Path.Combine(installationPath, "temp"); if (environmentInfo.Settings.DelayedSettings[gameModeFactory.GameModeDescriptor.ModeId] == null) { environmentInfo.Settings.DelayedSettings[gameModeFactory.GameModeDescriptor.ModeId] = new KeyedSettings <string>(); } if (environmentInfo.Settings.DelayedSettings["ALL"] == null) { environmentInfo.Settings.DelayedSettings["ALL"] = new KeyedSettings <string>(); } ViewMessage warning = null; IGameMode gameMode = gameModeFactory.BuildGameMode(fileUtil, out warning); IModCacheManager cacheManager = new NexusModCacheManager(environmentInfo.TemporaryPath, gameMode.GameModeEnvironmentInfo.ModDirectory, fileUtil); IScriptTypeRegistry scriptTypeRegistry = ScriptTypeRegistry.DiscoverScriptTypes(Path.Combine(Path.GetDirectoryName(exeLocation), "ScriptTypes"), gameMode, new List <string>()); if (scriptTypeRegistry.Types.Count == 0) { errorString = "No script types were found."; return(2); } // use a proxy so we can intercept accesses to the IGameMode interface. This allows us to make the additional search paths accessible from // the sandbox and feed in the script extender version even though the nmm lib won't find it. // This has to happen after DiscoverScriptTypes becaus that function tries to localize the assembly which fails for the dynamic assembly // of the proxy. Fortunately DiscoverScriptTypes has no side-effects on the gameMode. // This recreates the gamemode object so it's important no code above modifies gameMode ProxyGenerator generator = new ProxyGenerator(); GameModeInterceptor interceptor = new GameModeInterceptor(additionalSearchPaths, seVersion != null ? new Version(seVersion) : null); gameMode = (IGameMode)generator.CreateClassProxy(gameMode.GetType(), new object[] { environmentInfo, fileUtil }, new IInterceptor[] { interceptor }); IModFormatRegistry formatRegistry = ModFormatRegistry.DiscoverFormats(cacheManager, gameMode.SupportedFormats, scriptTypeRegistry, Path.Combine(Path.GetDirectoryName(exeLocation), "ModFormats")); if (formatRegistry.Formats.Count == 0) { errorString = "No formats were found."; return(2); } // we install the mod from the temporary path. Unfortunately this requires the archive to be copied, otherwise the sandbox will // prevent the installer script from accessing the archive in its original location string fileNameTemporary = Path.Combine(environmentInfo.TemporaryPath, Path.GetFileName(filename)); File.Copy(filename, fileNameTemporary); IMod mod = CreateMod(fileNameTemporary, formatRegistry, gameMode); if (mod == null) { errorString = "failed to initialize mod"; return(3); } System.IO.File.WriteAllText(installationPath + "/__installInfo.txt", mod.ModName + "\n" + mod.HumanReadableVersion + "\n" + mod.Id); if (mod.HasInstallScript) { DummyDataFileUtilFactory dummyFactory = null; IDataFileUtil dataFileUtility; Logger.Info("Detected C# script that relies on files in the actual data folder"); string modlistFile = Path.Combine(profilePath, "modlist.txt"); // ASSUMED mods path is the parent directory of the gameMode.InstallationPath string modsPath = Directory.GetParent(gameMode.InstallationPath).FullName; // Prepare dummy data directory dummyFactory = new DummyDataFileUtilFactory(gameMode.GameModeEnvironmentInfo.InstallationPath, modlistFile, modsPath, gamePath, additionalSearchPaths); dataFileUtility = dummyFactory.CreateDummyDataFileUtil(); TxFileManager fileManager = new TxFileManager(); IInstallLog installLog = new DummyInstallLog(); IIniInstaller iniIniInstaller = new IniInstaller(mod, installLog, fileManager, delegate { return(OverwriteResult.No); }); IPluginManager pluginManager = new DummyPluginManager(Path.Combine(profilePath, "plugins.txt"), gameMode, mod); IGameSpecificValueInstaller gameSpecificValueInstaller = gameMode.GetGameSpecificValueInstaller(mod, installLog, fileManager, new NexusFileUtil(environmentInfo), delegate { return(OverwriteResult.No); }); IModFileInstaller fileInstaller = new ModFileInstaller(gameMode.GameModeEnvironmentInfo, mod, installLog, pluginManager, dataFileUtility, fileManager, delegate { return(OverwriteResult.No); }, false); InstallerGroup installers = new InstallerGroup(dataFileUtility, fileInstaller, iniIniInstaller, gameSpecificValueInstaller, pluginManager); IVirtualModActivator modActivator = new DummyVirtualModActivator(gameMode, environmentInfo); IScriptExecutor executor = mod.InstallScript.Type.CreateExecutor(mod, gameMode, environmentInfo, modActivator, installers, SynchronizationContext.Current); // run the script in a second thread and start the main loop in the main thread to ensure we can handle message boxes and the like ScriptRunner runner = new ScriptRunner(executor, mod.InstallScript); runner.Execute(); runner.TaskEnded += delegate { iniIniInstaller.FinalizeInstall(); gameSpecificValueInstaller.FinalizeInstall(); mod.EndReadOnlyTransaction(); Application.Exit(); }; Application.Run(); switch (runner.Status) { case BackgroundTasks.TaskStatus.Cancelled: return(11); case BackgroundTasks.TaskStatus.Error: return(6); case BackgroundTasks.TaskStatus.Incomplete: return(10); default: return(0); } } else { errorString = "no install script"; return(4); } } catch (Exception e) { Console.WriteLine("exception: " + e.Message); MessageBox.Show(e.Message, "Installation failed", MessageBoxButtons.OK, MessageBoxIcon.Error); return(5); } }
/// <summary> /// Builds mods from an archive. /// </summary> /// <remarks> /// If the specified archive contains mods, they are simply extracted. Otherwise, the archive /// is examined to determine if it is already in a recognized format. If not, or if the archive /// spans multiple volumes, then the archive is repackaged. /// </remarks> /// <param name="p_mfrFormats">The registry of supported mod formats.</param> /// <param name="p_strArchivePath">The archive to build into a mod.</param> /// <param name="p_dlgConfirmOverwrite">The delegate to call to resolve conflicts with existing files.</param> /// <param name="p_strMessage">The message describing the state of the task.</param> /// <returns>The paths to the new mods.</returns> /// <exception cref="ArgumentException">Thrown if the specified path is not an archive.</exception> private IList<string> DoFromArchive(IModFormatRegistry p_mfrFormats, string p_strArchivePath, ConfirmOverwriteCallback p_dlgConfirmOverwrite, out string p_strMessage) { p_strMessage = null; Trace.TraceInformation(String.Format("[{0}] Adding mod from archive.", p_strArchivePath)); if (String.IsNullOrEmpty(p_strArchivePath) || !File.Exists(p_strArchivePath) || !Archive.IsArchive(p_strArchivePath)) throw new ArgumentException("The specified path is not an archive file.", "p_strArchivePath"); List<string> lstFoundMods = new List<string>(); List<string> lstModsInArchive = new List<string>(); ItemMessage = "Examining archive..."; ItemProgress = 0; ItemProgressMaximum = p_mfrFormats.Formats.Count; IModFormat mftDestFormat = null; try { using (SevenZipExtractor szeExtractor = Archive.GetExtractor(p_strArchivePath)) { if (Status == TaskStatus.Cancelling) return lstFoundMods; ReadOnlyCollection<string> lstArchiveFiles = szeExtractor.ArchiveFileNames; foreach (IModFormat mftFormat in p_mfrFormats.Formats) { ItemMessage = String.Format("Examining archive for {0} mods...", mftFormat.Name); lstModsInArchive.AddRange(lstArchiveFiles.Where(x => mftFormat.Extension.Equals(Path.GetExtension(x), StringComparison.OrdinalIgnoreCase))); StepItemProgress(); if (Status == TaskStatus.Cancelling) return lstFoundMods; } StepOverallProgress(); } if (lstModsInArchive.Count == 0) { ItemMessage = "Determining archive format..."; ItemProgress = 0; ItemProgressMaximum = p_mfrFormats.Formats.Count; List<KeyValuePair<FormatConfidence, IModFormat>> lstFormats = new List<KeyValuePair<FormatConfidence, IModFormat>>(); foreach (IModFormat mftFormat in p_mfrFormats.Formats) { lstFormats.Add(new KeyValuePair<FormatConfidence, IModFormat>(mftFormat.CheckFormatCompliance(p_strArchivePath), mftFormat)); StepItemProgress(); if (Status == TaskStatus.Cancelling) return lstFoundMods; } lstFormats.Sort((x, y) => y.Key.CompareTo(x.Key)); if ((lstFormats.Count == 0) || (lstFormats[0].Key <= FormatConfidence.Convertible)) return lstFoundMods; mftDestFormat = lstFormats[0].Value; } StepOverallProgress(); } catch (Exception ex) { MessageBox.Show("An error has occured with the following archive: " + p_strArchivePath + "\n\n ERROR: " + ex.Message); return lstFoundMods; } string strTmpPath = null; try { using (SevenZipExtractor szeExtractor = Archive.GetExtractor(p_strArchivePath)) { if ((mftDestFormat != null) && (szeExtractor.VolumeFileNames.Count > 1) || (lstModsInArchive.Count > 0)) { ItemMessage = "Extracting archive..."; ItemProgress = 0; ItemProgressMaximum = szeExtractor.ArchiveFileNames.Count; strTmpPath = FileUtility.CreateTempDirectory(); szeExtractor.FileExtractionStarted += new EventHandler<FileInfoEventArgs>(Extractor_FileExtractionStarted); szeExtractor.FileExtractionFinished += new EventHandler<FileInfoEventArgs>(Extractor_FileExtractionFinished); try { szeExtractor.ExtractArchive(strTmpPath); } catch (FileNotFoundException ex) { Status = TaskStatus.Error; p_strMessage = ex.Message; return lstFoundMods; } for (Int32 i = 0; i < lstModsInArchive.Count; i++) lstModsInArchive[i] = Path.Combine(strTmpPath, lstModsInArchive[i]); } else lstModsInArchive.Add(p_strArchivePath); } StepOverallProgress(); if (!String.IsNullOrEmpty(strTmpPath) && (mftDestFormat != null)) { //if we have extracted the file to do format shifting if (!mftDestFormat.SupportsModCompression) return lstFoundMods; ItemMessage = "Compressing mod..."; ItemProgress = 0; ItemProgressMaximum = Directory.GetFiles(strTmpPath, "*", SearchOption.AllDirectories).Length; IModCompressor mcpCompressor = mftDestFormat.GetModCompressor(EnvironmentInfo); mcpCompressor.FileCompressionFinished += new CancelEventHandler(Compressor_FileCompressionFinished); string strDest = Path.Combine(GameModeInfo.ModDirectory, Path.GetFileName(p_strArchivePath)); strDest = Path.ChangeExtension(strDest, mftDestFormat.Extension); strDest = ConfirmOverwrite(p_dlgConfirmOverwrite, strDest); if (!String.IsNullOrEmpty(strDest)) { mcpCompressor.Compress(strTmpPath, strDest); lstFoundMods.Add(strDest); } } else { ItemMessage = "Copying mods..."; ItemProgress = 0; ItemProgressMaximum = lstModsInArchive.Count; foreach (string strMod in lstModsInArchive) { if (Status == TaskStatus.Cancelling) return lstFoundMods; ItemMessage = String.Format("Copying mod {0}...", Path.GetFileName(strMod)); string strDest = Path.Combine(GameModeInfo.ModDirectory, Path.GetFileName(strMod)); strDest = ConfirmOverwrite(p_dlgConfirmOverwrite, strDest); if (!String.IsNullOrEmpty(strDest)) { File.Copy(strMod, strDest, true); lstFoundMods.Add(strDest); } StepItemProgress(); } } StepOverallProgress(); } finally { if (!String.IsNullOrEmpty(strTmpPath)) FileUtil.ForceDelete(strTmpPath); } return lstFoundMods; }
/// <summary> /// Builds mods from a file. /// </summary> /// <remarks> /// This detects the type of file and takes appropriate action. /// </remarks> /// <param name="p_mfrFormats">The registry of supported mod formats.</param> /// <param name="p_strFilePath">The archive to build into a mod.</param> /// <param name="p_dlgConfirmOverwrite">The delegate to call to resolve conflicts with existing files.</param> /// <exception cref="ArgumentException">Thrown if the specified path is not an archive.</exception> public void BuildFromFile(IModFormatRegistry p_mfrFormats, string p_strFilePath, ConfirmOverwriteCallback p_dlgConfirmOverwrite) { ShowItemProgress = true; OverallProgressStepSize = 1; ItemProgressStepSize = 1; OverallProgressMaximum = 4; OverallMessage = "Building Mod..."; Sources srcModSource = Sources.Archive; if (String.IsNullOrEmpty(p_strFilePath) || !File.Exists(p_strFilePath)) throw new ArgumentException("The given file path does not exist: " + p_strFilePath); if (!Archive.IsArchive(p_strFilePath)) { Status = TaskStatus.Error; OnTaskEnded(String.Format("Cannot add {0}. File format is not recognized.", Path.GetFileName(p_strFilePath)), null); return; } Start(srcModSource, p_mfrFormats, p_strFilePath, p_dlgConfirmOverwrite); }