/// <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> /// 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); }