/// <summary>
        /// Creates a directory for the ModNodes destination.
        /// </summary>
        /// <param name="node">The ModNode to get the destination of.</param>
        /// <param name="silent">Determines if info messages should be added displayed.</param>
        private static void CreateDirectory(ModNode node, bool silent)
        {
            string destination = node.Destination;

            if (!string.IsNullOrEmpty(destination))
            {
                destination = KSPPathHelper.GetAbsolutePath(destination);
            }

            node.IsInstalled = false;
            if (!Directory.Exists(destination))
            {
                try
                {
                    Directory.CreateDirectory(destination);
                    node.IsInstalled = true;

                    if (!silent)
                    {
                        Messenger.AddInfo(string.Format(Messages.MSG_DIR_CREATED_0, destination));
                    }
                }
                catch
                {
                    Messenger.AddInfo(string.Format(Messages.MSG_DIR_CREATED_ERROR_0, destination));
                }
            }

            node.NodeType = (node.IsKSPFolder) ? NodeType.KSPFolderInstalled : NodeType.UnknownFolderInstalled;
        }
        /// <summary>
        /// Removes the file the ModNodes destination points to.
        /// </summary>
        /// <param name="node">The ModNode to get the destination of.</param>
        /// <param name="silent">Determines if info messages should be added displayed.</param>
        private static void RemoveFile(ModNode node, bool silent)
        {
            string destination = node.Destination;

            if (!string.IsNullOrEmpty(destination))
            {
                destination = KSPPathHelper.GetAbsolutePath(destination);
            }

            node.IsInstalled = false;
            bool installedByOtherMod = ModRegister.GetCollisionModFiles(node).Any(n => n.IsInstalled);

            if (File.Exists(destination) && !installedByOtherMod)
            {
                try
                {
                    File.Delete(destination);
                    node.IsInstalled = false;
                    if (!silent)
                    {
                        Messenger.AddInfo(string.Format(Messages.MSG_FILE_DELETED_0, destination));
                    }
                }
                catch (Exception ex)
                {
                    Messenger.AddError(string.Format(Messages.MSG_FILE_DELETED_ERROR_0, destination), ex);
                }
            }

            node.NodeType = NodeType.UnknownFile;
        }
        /// <summary>
        /// Returns the destination path of the craft.
        /// </summary>
        /// <param name="craftNode">The craft to get the destination for.</param>
        public static void SetCraftDestination(ModNode craftNode)
        {
            string zipPath = craftNode.ZipRoot.Key;

            using (IArchive archive = ArchiveFactory.Open(zipPath))
            {
                foreach (IArchiveEntry entry in archive.Entries)
                {
                    if (!entry.FilePath.EndsWith(craftNode.Text, StringComparison.CurrentCultureIgnoreCase))
                    {
                        continue;
                    }

                    using (MemoryStream ms = new MemoryStream())
                    {
                        entry.WriteTo(ms);
                        ms.Position = 0;
                        using (StreamReader sr = new StreamReader(ms))
                        {
                            string fullText = sr.ReadToEnd();
                            int    index    = fullText.IndexOf(TYPE);
                            if (index == -1)
                            {
                                continue;
                            }

                            string filename = Path.GetFileName(entry.FilePath);
                            if (string.IsNullOrEmpty(filename))
                            {
                                continue;
                            }

                            string shipType = fullText.Substring(index + 7, 3);
                            if (shipType.Equals(Constants.SPH, StringComparison.CurrentCultureIgnoreCase))
                            {
                                craftNode.Destination = Path.Combine(KSPPathHelper.GetPath(KSPPaths.SPH), filename);
                            }
                            else
                            {
                                craftNode.Destination = Path.Combine(KSPPathHelper.GetPath(KSPPaths.VAB), filename);
                            }

                            if (!string.IsNullOrEmpty(craftNode.Destination))
                            {
                                craftNode.Destination = KSPPathHelper.GetRelativePath(craftNode.Destination);
                            }

                            SetToolTips(craftNode);

                            break;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Finds the root folder of the mod that can be installed to the KSP install folder.
        /// </summary>
        /// <param name="node">Node to start the search from.</param>
        /// <returns>The root folder of the mod that can be installed to the KSP install folder.</returns>
        private static bool FindAndSetDestinationPaths(ModNode node)
        {
            List <ModNode> kspFolders = new List <ModNode>();
            List <ModNode> craftFiles = new List <ModNode>();

            ModSelectionTreeModel.GetAllKSPFolders(node, ref kspFolders, ref craftFiles);
            if (kspFolders.Count == 1)
            {
                SetDestinationPaths(kspFolders[0], false);
            }
            else if (kspFolders.Count > 1)
            {
                kspFolders.Sort((node1, node2) =>
                {
                    if (node2.Depth == node1.Depth)
                    {
                        return(node1.Text.CompareTo(node2.Text));
                    }
                    else
                    {
                        return(node2.Depth - node1.Depth);
                    }
                });

                bool lastResult = false;
                foreach (ModNode kspFolder in kspFolders)
                {
                    lastResult = SetDestinationPaths(kspFolder, lastResult);
                }
            }

            if (craftFiles.Count > 0)
            {
                foreach (ModNode craftNode in craftFiles)
                {
                    string vab = KSPPathHelper.GetPath(KSPPaths.VAB);
                    string sph = KSPPathHelper.GetPath(KSPPaths.SPH);
                    if (!craftNode.HasDestination || (!craftNode.Destination.StartsWith(vab, StringComparison.CurrentCultureIgnoreCase) &&
                                                      !craftNode.Destination.StartsWith(sph, StringComparison.CurrentCultureIgnoreCase)))
                    {
                        SetCraftDestination(craftNode);
                    }
                }
            }

            if (node.HasDestination || node.HasDestinationForChilds)
            {
                node.SetChecked(true);
            }

            return((kspFolders.Count > 0) || (craftFiles.Count > 0));
        }
        /// <summary>
        /// Try to delete all not processed directories.
        /// </summary>
        /// <param name="node">The dir node to delete.</param>
        /// <param name="silent">Determines if info messages should be added displayed.</param>
        /// <returns>True on success.</returns>
        private static bool DeleteDirectory(ModNode node, bool silent = false)
        {
            string destination = node.Destination;

            if (!string.IsNullOrEmpty(destination))
            {
                destination = KSPPathHelper.GetAbsolutePath(destination);
            }

            try
            {
                if (!Directory.Exists(destination))
                {
                    Messenger.AddInfo(string.Format(Messages.MSG_DIR_0_NOT_EXISTS, destination));
                    return(false);
                }

                if (KSPPathHelper.IsKSPDir(destination))
                {
                    Messenger.AddInfo(string.Format(Messages.MSG_DIR_0_IS_KSPDIR, destination));
                    return(false);
                }

                if (Directory.GetDirectories(destination).Any() ||
                    Directory.GetFiles(destination).Any())
                {
                    Messenger.AddInfo(string.Format(Messages.MSG_DIR_0_IS_NOT_EMPTY, destination));
                    return(false);
                }

                Directory.Delete(destination, true);
                if (!silent)
                {
                    Messenger.AddInfo(string.Format(Messages.MSG_DIR_DELETED_0, destination));
                }

                return(true);
            }
            catch (Exception ex)
            {
                Messenger.AddError(string.Format(Messages.MSG_DIR_DELETED_ERROR_0, destination), ex);
            }

            return(false);
        }
Пример #6
0
        /// <summary>
        /// Creates a ZipEntry of the passed node and its childs to the passed zip file.
        /// </summary>
        /// <param name="zip">The zip file to add the new zip entry to.</param>
        /// <param name="node">The node to create a zip entry for.</param>
        /// <param name="processedNodeCount">Count of the processed nodes (for recursive calls only).</param>
        /// <returns>Count of the processed nodes.</returns>
        private static int CreateZipEntry(ZipArchive zip, ModNode node, int processedNodeCount = 0)
        {
            string absPath      = KSPPathHelper.GetAbsolutePath(node.Destination);
            string gameDataPath = KSPPathHelper.GetPath(KSPPaths.GameData);
            string path         = absPath.Replace(gameDataPath + Path.DirectorySeparatorChar, string.Empty);

            if (node.IsFile && node.IsInstalled)
            {
                zip.AddEntry(path, absPath);
            }

            foreach (ModNode child in node.Nodes)
            {
                processedNodeCount = CreateZipEntry(zip, child, processedNodeCount);
            }

            return(processedNodeCount);
        }
        /// <summary>
        /// Creates a directory entry for the TreeView.
        /// </summary>
        /// <param name="dirName">Name of the directory.</param>
        /// <param name="parent">The parent node where the created node will be attached attach to.</param>
        /// <returns>The new created ModNode.</returns>
        private static ModNode CreateDirListEntry(string dirName, ModNode parent)
        {
            // dir already created?
            ModNode dirNode = ModSelectionTreeModel.SearchNodeByPath(parent.Text + "/" + dirName, parent, '/');

            if (null == dirNode)
            {
                dirNode = new ModNode(dirName, dirName);
                // TODO:!!!
                ////dirNode.ToolTipText = "<No path selected>";
                dirNode.NodeType = (KSPPathHelper.IsKSPDir(dirName.ToLower())) ? NodeType.KSPFolder : NodeType.UnknownFolder;
                parent.Nodes.Add(dirNode);

                Messenger.AddInfo(string.Format(Messages.MSG_DIR_ADDED_0, dirName));
            }

            return(dirNode);
        }
        /// <summary>
        /// Builds and sets the destination path to the passed node and its childes.
        /// </summary>
        /// <param name="node">Node to set the destination path.</param>
        /// <param name="gameDataFound">Flag to inform the function it the GameData folder was already found (for calls from a loop).</param>
        /// <returns>True if the passed node is the GameData folder, otherwise false.</returns>
        public static bool SetDestinationPaths(ModNode node, bool gameDataFound)
        {
            bool    result   = false;
            string  path     = string.Empty;
            ModNode tempNode = node;

            if (node.Text.Equals(Constants.GAMEDATA, StringComparison.CurrentCultureIgnoreCase))
            {
                tempNode = node;
                path     = KSPPathHelper.GetPath(KSPPaths.KSPRoot);
                result   = true;
            }
            else if (node.Text.Equals(Constants.SHIPS, StringComparison.CurrentCultureIgnoreCase))
            {
                tempNode = node;
                path     = KSPPathHelper.GetPath(KSPPaths.KSPRoot);
                result   = false;
            }
            else if (node.Text.Equals(Constants.VAB, StringComparison.CurrentCultureIgnoreCase) ||
                     node.Text.Equals(Constants.SPH, StringComparison.CurrentCultureIgnoreCase))
            {
                tempNode = node;
                path     = KSPPathHelper.GetPath(KSPPaths.Ships);
                result   = false;
            }
            else if (gameDataFound || node.Parent == null)
            {
                tempNode = node;
                path     = KSPPathHelper.GetPathByName(node.Name);
                path     = (path.ToLower().EndsWith(node.Name.ToLower())) ? path.ToLower().Replace(Path.DirectorySeparatorChar + node.Name.ToLower(), string.Empty) : path;
                result   = false;
            }
            else
            {
                tempNode = (ModNode)node.Parent;
                path     = KSPPathHelper.GetPath(KSPPaths.GameData);
                result   = false;
            }

            SetDestinationPaths(tempNode, path);

            return(result);
        }
        /// <summary>
        /// Removes the directory the ModNodes destination points to.
        /// </summary>
        /// <param name="node">The ModNode to get the destination of.</param>
        /// <param name="silent">Determines if info messages should be added displayed.</param>
        private static void RemoveDirectory(ModNode node, bool silent)
        {
            if (!node.IsKSPFolder)
            {
                string destination = node.Destination;
                if (!string.IsNullOrEmpty(destination))
                {
                    destination = KSPPathHelper.GetAbsolutePath(destination);
                }

                node.IsInstalled = false;
                if (Directory.Exists(destination))
                {
                    if (!Directory.GetDirectories(destination).Any() && !Directory.GetFiles(destination).Any())
                    {
                        try
                        {
                            Directory.Delete(destination, true);
                            node.IsInstalled = false;
                            if (!silent)
                            {
                                Messenger.AddInfo(string.Format(Messages.MSG_DIR_DELETED_0, destination));
                            }
                        }
                        catch
                        {
                            mNotDeletedDirs.Add(node);
                        }
                    }
                    else
                    {
                        // add dir for later try to delete
                        mNotDeletedDirs.Add(node);
                    }
                }
            }
            else
            {
                mNotDeletedDirs.Add(node);
            }

            node.NodeType = (node.IsKSPFolder) ? NodeType.KSPFolder : NodeType.UnknownFolder;
        }
        /// <summary>
        /// Builds and sets the destination path to the passed node and its childes.
        /// </summary>
        /// <param name="srcNode">Node to set the destination path.</param>
        /// <param name="destPath">The destination path.</param>
        public static void SetDestinationPaths(ModNode srcNode, string destPath, bool copyContent = false)
        {
            if (!copyContent)
            {
                ////if (srcNode.Text.ToLower() == Constants.GAMEDATA)
                ////    srcNode.Destination = destPath;
                ////else
                srcNode.Destination = (!string.IsNullOrEmpty(destPath)) ? Path.Combine(destPath, srcNode.Text) : string.Empty;

                destPath = (!string.IsNullOrEmpty(srcNode.Destination)) ? srcNode.Destination : string.Empty;

                if (!string.IsNullOrEmpty(srcNode.Destination))
                {
                    srcNode.Destination = KSPPathHelper.GetRelativePath(srcNode.Destination);
                }
            }

            SetToolTips(srcNode);

            foreach (ModNode child in srcNode.Nodes)
            {
                SetDestinationPaths(child, destPath);
            }
        }
        /// <summary>
        /// Extracts the file from the archive with the passed key.
        /// </summary>
        /// <param name="node">The node to install the file from.</param>
        /// <param name="path">The path to install the file to.</param>
        /// <param name="silent">Determines if info messages should be added displayed.</param>
        private static void ExtractFile(ModNode node, string path, bool silent = false, bool overrideOn = false)
        {
            if (node == null)
            {
                return;
            }

            string destination = path;

            if (!string.IsNullOrEmpty(destination))
            {
                destination = KSPPathHelper.GetAbsolutePath(destination);
            }

            using (IArchive archive = ArchiveFactory.Open(node.ZipRoot.Key))
            {
                IArchiveEntry entry = archive.Entries.FirstOrDefault(e => e.FilePath.Equals(node.Key, StringComparison.CurrentCultureIgnoreCase));
                if (entry == null)
                {
                    return;
                }

                node.IsInstalled = false;
                if (!File.Exists(destination))
                {
                    try
                    {
                        // create new file.
                        entry.WriteToFile(destination);
                        node.IsInstalled = true;

                        if (!silent)
                        {
                            Messenger.AddInfo(string.Format(Messages.MSG_FILE_EXTRACTED_0, destination));
                        }
                    }
                    catch (Exception ex)
                    {
                        Messenger.AddError(string.Format(Messages.MSG_FILE_EXTRACTED_ERROR_0, destination), ex);
                    }
                }
                else if (overrideOn)
                {
                    try
                    {
                        // delete old file
                        File.Delete(destination);

                        // create new file.
                        entry.WriteToFile(destination);

                        if (!silent)
                        {
                            Messenger.AddInfo(string.Format(Messages.MSG_FILE_EXTRACTED_0, destination));
                        }
                    }
                    catch (Exception ex)
                    {
                        Messenger.AddError(string.Format(Messages.MSG_FILE_EXTRACTED_ERROR_0, destination), ex);
                    }
                }

                node.IsInstalled = File.Exists(destination);
                node.NodeType    = (node.IsInstalled) ? NodeType.UnknownFileInstalled : NodeType.UnknownFile;
            }
        }
        /// <summary>
        /// Creates a tree of TreeNodeMod nodes that represent the content of a mod archive.
        /// </summary>
        /// <param name="modInfo">The ModInfo of the mod the create a tree for.</param>
        /// <param name="silent">Determines if info messages should be added.</param>
        /// <returns>A tree of TreeNodeMod nodes that represent the content of a mod archive.</returns>
        public static ModNode CreateModNode(ModInfo modInfo, bool silent = false)
        {
            if (File.Exists(modInfo.LocalPath))
            {
                // Get AVC version file informations.
                if (OptionsController.AVCSupportOnOff)
                {
                    AVCInfo avcInfo = TryReadAVCVersionFile(modInfo.LocalPath);
                    if (avcInfo != null)
                    {
                        ImportAvcInfo(avcInfo, ref modInfo);
                    }
                }

                // Still no name? Use filename then
                if (string.IsNullOrEmpty(modInfo.Name))
                {
                    modInfo.Name = Path.GetFileNameWithoutExtension(modInfo.LocalPath);
                }

                ModNode node = new ModNode(modInfo);
                using (IArchive archive = ArchiveFactory.Open(modInfo.LocalPath))
                {
                    char   seperator = '/';
                    string extension = Path.GetExtension(modInfo.LocalPath);
                    if (extension != null && extension.Equals(Constants.EXT_RAR, StringComparison.CurrentCultureIgnoreCase))
                    {
                        seperator = '\\';
                    }

                    // create a TreeNode for every archive entry
                    foreach (IArchiveEntry entry in archive.Entries)
                    {
                        CreateModNode(entry.FilePath, node, seperator, entry.IsDirectory, silent);
                    }
                }

                // Destination detection
                switch (OptionsController.DestinationDetectionType)
                {
                case DestinationDetectionType.SmartDetection:
                    // Find installation root node (first folder that contains (Parts or Plugins or ...)
                    if (!FindAndSetDestinationPaths(node) && !silent)
                    {
                        Messenger.AddInfo(string.Format(Messages.MSG_ROOT_NOT_FOUND_0, node.Text));
                    }

                    if (OptionsController.CopyToGameData)
                    {
                        if (!silent)
                        {
                            Messenger.AddInfo(string.Format(Messages.MSG_DESTINATION_0_SET_TO_GAMEDATA, node.Text));
                        }
                        SetDestinationPaths(node, KSPPathHelper.GetPath(KSPPaths.GameData));
                    }
                    break;

                case DestinationDetectionType.SimpleDump:
                    if (!silent)
                    {
                        Messenger.AddInfo(string.Format(Messages.MSG_DESTINATION_0_SET_TO_GAMEDATA, node.Text));
                    }
                    SetDestinationPaths(node, KSPPathHelper.GetPath(KSPPaths.GameData));
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                SetToolTips(node);
                CheckNodesWithDestination(node);

                return(node);
            }
            else
            {
                if (!silent)
                {
                    Messenger.AddInfo(string.Format(Messages.MSG_MOD_ZIP_NOT_FOUND_0, modInfo.LocalPath));
                }
            }

            return(null);
        }