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