Example #1
0
        /// <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);
        }