/// <summary>Get the possible game paths to update.</summary> /// <param name="toolkit">The mod toolkit.</param> /// <param name="context">The installer context.</param> private IEnumerable <DirectoryInfo> DetectGameFolders(ModToolkit toolkit, InstallerContext context) { HashSet <string> foundPaths = new HashSet <string>(); // game folder which contains the installer, if any { DirectoryInfo curPath = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory; while (curPath?.Parent != null) // must be in a folder (not at the root) { if (context.LooksLikeGameFolder(curPath)) { foundPaths.Add(curPath.FullName); yield return(curPath); break; } curPath = curPath.Parent; } } // game paths detected by toolkit foreach (DirectoryInfo dir in toolkit.GetGameFolders()) { if (foundPaths.Add(dir.FullName)) { yield return(dir); } } }
/// <summary>Interactively locate the game install path to update.</summary> /// <param name="toolkit">The mod toolkit.</param> /// <param name="context">The installer context.</param> /// <param name="specifiedPath">The path specified as a command-line argument (if any), which should override automatic path detection.</param> private DirectoryInfo InteractivelyGetInstallPath(ModToolkit toolkit, InstallerContext context, string specifiedPath) { // use specified path if (specifiedPath != null) { var dir = new DirectoryInfo(specifiedPath); if (!dir.Exists) { this.PrintError($"You specified --game-path \"{specifiedPath}\", but that folder doesn't exist."); return(null); } if (!context.LooksLikeGameFolder(dir)) { this.PrintError($"You specified --game-path \"{specifiedPath}\", but that folder doesn't contain the Stardew Valley executable."); return(null); } return(dir); } // use game folder which contains the installer, if any { DirectoryInfo curPath = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory; while (curPath?.Parent != null) // must be in a folder (not at the root) { if (context.LooksLikeGameFolder(curPath)) { return(curPath); } curPath = curPath.Parent; } } // use an installed path DirectoryInfo[] defaultPaths = toolkit.GetGameFolders().ToArray(); if (defaultPaths.Any()) { // only one path if (defaultPaths.Length == 1) { return(defaultPaths.First()); } // let user choose path Console.WriteLine(); this.PrintInfo("Found multiple copies of the game:"); for (int i = 0; i < defaultPaths.Length; i++) { this.PrintInfo($"[{i + 1}] {defaultPaths[i].FullName}"); } Console.WriteLine(); string[] validOptions = Enumerable.Range(1, defaultPaths.Length).Select(p => p.ToString(CultureInfo.InvariantCulture)).ToArray(); string choice = this.InteractivelyChoose("Where do you want to add/remove SMAPI? Type the number next to your choice, then press enter.", validOptions); int index = int.Parse(choice, CultureInfo.InvariantCulture) - 1; return(defaultPaths[index]); } // ask user this.PrintInfo("Oops, couldn't find the game automatically."); while (true) { // get path from user this.PrintInfo($"Type the file path to the game directory (the one containing '{context.ExecutableName}'), then press enter."); string path = Console.ReadLine()?.Trim(); if (string.IsNullOrWhiteSpace(path)) { this.PrintInfo(" You must specify a directory path to continue."); continue; } // normalize path path = context.IsWindows ? path.Replace("\"", "") // in Windows, quotes are used to escape spaces and aren't part of the file path : path.Replace("\\ ", " "); // in Linux/Mac, spaces in paths may be escaped if copied from the command line if (path.StartsWith("~/")) { string home = Environment.GetEnvironmentVariable("HOME") ?? Environment.GetEnvironmentVariable("USERPROFILE"); path = Path.Combine(home, path.Substring(2)); } // get directory if (File.Exists(path)) { path = Path.GetDirectoryName(path); } DirectoryInfo directory = new DirectoryInfo(path); // validate path if (!directory.Exists) { this.PrintInfo(" That directory doesn't seem to exist."); continue; } if (!context.LooksLikeGameFolder(directory)) { this.PrintInfo(" That directory doesn't contain a Stardew Valley executable."); continue; } // looks OK this.PrintInfo(" OK!"); return(directory); } }
/// <summary>Interactively locate the game install path to update.</summary> /// <param name="toolkit">The mod toolkit.</param> /// <param name="context">The installer context.</param> /// <param name="specifiedPath">The path specified as a command-line argument (if any), which should override automatic path detection.</param> private DirectoryInfo InteractivelyGetInstallPath(ModToolkit toolkit, InstallerContext context, string specifiedPath) { // use specified path if (specifiedPath != null) { var dir = new DirectoryInfo(specifiedPath); if (!dir.Exists) { this.PrintError($"You specified --game-path \"{specifiedPath}\", but that folder doesn't exist."); return(null); } if (!context.LooksLikeGameFolder(dir)) { this.PrintError($"You specified --game-path \"{specifiedPath}\", but that folder doesn't contain the Secrets of Grindea executable."); return(null); } return(dir); } // let user choose detected path DirectoryInfo[] defaultPaths = this.DetectGameFolders(toolkit, context).ToArray(); if (defaultPaths.Any()) { this.PrintInfo("Where do you want to add or remove SoGMAPI?"); Console.WriteLine(); for (int i = 0; i < defaultPaths.Length; i++) { this.PrintInfo($"[{i + 1}] {defaultPaths[i].FullName}"); } this.PrintInfo($"[{defaultPaths.Length + 1}] Enter a custom game path."); Console.WriteLine(); string[] validOptions = Enumerable.Range(1, defaultPaths.Length + 1).Select(p => p.ToString(CultureInfo.InvariantCulture)).ToArray(); string choice = this.InteractivelyChoose("Type the number next to your choice, then press enter.", validOptions); int index = int.Parse(choice, CultureInfo.InvariantCulture) - 1; if (index < defaultPaths.Length) { return(defaultPaths[index]); } } else { this.PrintInfo("Oops, couldn't find the game automatically."); } // let user enter manual path while (true) { // get path from user Console.WriteLine(); this.PrintInfo($"Type the file path to the game directory (the one containing '{context.ExecutableName}'), then press enter."); string path = Console.ReadLine()?.Trim(); if (string.IsNullOrWhiteSpace(path)) { this.PrintWarning("You must specify a directory path to continue."); continue; } // normalize path path = context.IsWindows ? path.Replace("\"", "") // in Windows, quotes are used to escape spaces and aren't part of the file path : path.Replace("\\ ", " "); // in Linux/macOS, spaces in paths may be escaped if copied from the command line if (path.StartsWith("~/")) { string home = Environment.GetEnvironmentVariable("HOME") ?? Environment.GetEnvironmentVariable("USERPROFILE"); path = Path.Combine(home, path.Substring(2)); } // get directory if (File.Exists(path)) { path = Path.GetDirectoryName(path); } DirectoryInfo directory = new DirectoryInfo(path); // validate path if (!directory.Exists) { this.PrintWarning("That directory doesn't seem to exist."); continue; } if (!context.LooksLikeGameFolder(directory)) { this.PrintWarning("That directory doesn't contain a Secrets of Grindea executable."); continue; } // looks OK this.PrintInfo(" OK!"); return(directory); } }