/// <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));
        }
Esempio n. 3
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>
        /// 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>
        /// 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);
        }