From 9029633f7f1076415fcb9e76fd3e0e58357ddcec Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 11 Aug 2018 23:17:36 -0400 Subject: overhaul installer display (#554) The installer now validates preconditions earlier when possible, and after each step will reset the text and condense details from previous steps. This way players only see info for the current question to avoid confusion, and it's easier to add new steps. --- src/SMAPI.Installer/Framework/InstallerPaths.cs | 61 ++++ src/SMAPI.Installer/InteractiveInstaller.cs | 385 ++++++++++++--------- .../StardewModdingAPI.Installer.csproj | 1 + 3 files changed, 282 insertions(+), 165 deletions(-) create mode 100644 src/SMAPI.Installer/Framework/InstallerPaths.cs (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/Framework/InstallerPaths.cs b/src/SMAPI.Installer/Framework/InstallerPaths.cs new file mode 100644 index 00000000..d212876a --- /dev/null +++ b/src/SMAPI.Installer/Framework/InstallerPaths.cs @@ -0,0 +1,61 @@ +using System.IO; + +namespace StardewModdingAPI.Installer.Framework +{ + /// Manages paths for the SMAPI installer. + internal class InstallerPaths + { + /********* + ** Accessors + *********/ + /// The directory containing the installer files for the current platform. + public DirectoryInfo PackageDir { get; } + + /// The directory containing the installed game. + public DirectoryInfo GameDir { get; } + + /// The directory into which to install mods. + public DirectoryInfo ModsDir { get; } + + /// The full path to the directory containing the installer files for the current platform. + public string PackagePath => this.PackageDir.FullName; + + /// The full path to the directory containing the installed game. + public string GamePath => this.GameDir.FullName; + + /// The full path to the directory into which to install mods. + public string ModsPath => this.ModsDir.FullName; + + /// The full path to the installed SMAPI executable file. + public string ExecutablePath { get; } + + /// The full path to the vanilla game launcher on Linux/Mac. + public string UnixLauncherPath { get; } + + /// The full path to the installed SMAPI launcher on Linux/Mac before it's renamed. + public string UnixSmapiLauncherPath { get; } + + /// The full path to the vanilla game launcher on Linux/Mac after SMAPI is installed. + public string UnixBackupLauncherPath { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The directory path containing the installer files for the current platform. + /// The directory path for the installed game. + /// The name of the game's executable file for the current platform. + public InstallerPaths(DirectoryInfo packageDir, DirectoryInfo gameDir, string gameExecutableName) + { + this.PackageDir = packageDir; + this.GameDir = gameDir; + this.ModsDir = new DirectoryInfo(Path.Combine(gameDir.FullName, "Mods")); + + this.ExecutablePath = Path.Combine(gameDir.FullName, gameExecutableName); + this.UnixLauncherPath = Path.Combine(gameDir.FullName, "StardewValley"); + this.UnixSmapiLauncherPath = Path.Combine(gameDir.FullName, "StardewModdingAPI"); + this.UnixBackupLauncherPath = Path.Combine(gameDir.FullName, "StardewValley-original"); + } + } +} diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index f39486e1..b686e5bc 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Threading; using Microsoft.Win32; using StardewModdingApi.Installer.Enums; +using StardewModdingAPI.Installer.Framework; using StardewModdingAPI.Internal; using StardewModdingAPI.Internal.ConsoleWriting; @@ -168,6 +169,9 @@ namespace StardewModdingApi.Installer /// public void Run(string[] args) { + /********* + ** Step 1: initial setup + *********/ /**** ** Get platform & set window title ****/ @@ -175,6 +179,9 @@ namespace StardewModdingApi.Installer Console.Title = $"SMAPI {this.GetDisplayVersion(this.GetType().Assembly.GetName().Version)} installer on {platform} {EnvironmentUtility.GetFriendlyPlatformName(platform)}"; Console.WriteLine(); + /**** + ** Check if correct installer + ****/ #if SMAPI_FOR_WINDOWS if (platform == Platform.Linux || platform == Platform.Mac) { @@ -182,8 +189,39 @@ namespace StardewModdingApi.Installer Console.ReadLine(); return; } +#else + if (platform == Platform.Windows) + { + this.PrintError($"This is the installer for Linux/Mac. Run the 'install on Windows.exe' file instead."); + Console.ReadLine(); + return; + } #endif + /**** + ** Check Windows dependencies + ****/ + if (platform == Platform.Windows) + { + // .NET Framework 4.5+ + if (!this.HasNetFramework45(platform)) + { + this.PrintError(Environment.OSVersion.Version >= this.Windows7Version + ? "Please install the latest version of .NET Framework before installing SMAPI." // Windows 7+ + : "Please install .NET Framework 4.5 before installing SMAPI." // Windows Vista or earlier + ); + this.PrintError("See the download page at https://www.microsoft.com/net/download/framework for details."); + Console.ReadLine(); + return; + } + if (!this.HasXna(platform)) + { + this.PrintError("You don't seem to have XNA Framework installed. Please run the game at least once before installing SMAPI, so it can perform its first-time setup."); + Console.ReadLine(); + return; + } + } + /**** ** read command-line arguments ****/ @@ -205,230 +243,242 @@ namespace StardewModdingApi.Installer gamePathArg = args[pathIndex]; } - /**** - ** collect details - ****/ - // get game path - DirectoryInfo installDir = this.InteractivelyGetInstallPath(platform, gamePathArg); - if (installDir == null) - { - this.PrintError("Failed finding your game path."); - Console.ReadLine(); - return; - } - // get folders - DirectoryInfo packageDir = platform.IsMono() - ? new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)) // installer runs from internal folder on Mono - : new DirectoryInfo(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "internal", "Windows")); - DirectoryInfo modsDir = new DirectoryInfo(Path.Combine(installDir.FullName, "Mods")); - var paths = new + /********* + ** Step 2: find game folder + *********/ + InstallerPaths paths; { - executable = Path.Combine(installDir.FullName, EnvironmentUtility.GetExecutableName(platform)), - unixSmapiLauncher = Path.Combine(installDir.FullName, "StardewModdingAPI"), - unixLauncher = Path.Combine(installDir.FullName, "StardewValley"), - unixLauncherBackup = Path.Combine(installDir.FullName, "StardewValley-original") - }; + /**** + ** print header + ****/ + this.PrintInfo("Hi there! I'll help you install or remove SMAPI. Just a few questions first."); + this.PrintDebug("----------------------------------------------------------------------------"); + Console.WriteLine(); - // show output - this.PrintInfo($"Your game folder: {installDir}."); + /**** + ** collect details + ****/ + // get game path + this.PrintInfo("Where is your game folder?"); + DirectoryInfo installDir = this.InteractivelyGetInstallPath(platform, gamePathArg); + if (installDir == null) + { + this.PrintError("Failed finding your game path."); + Console.ReadLine(); + return; + } - /**** - ** validate assumptions - ****/ - if (!packageDir.Exists) - { - this.PrintError(platform == Platform.Windows && packageDir.FullName.Contains(Path.GetTempPath()) && packageDir.FullName.Contains(".zip") - ? "The installer is missing some files. It looks like you're running the installer from inside the downloaded zip; make sure you unzip the downloaded file first, then run the installer from the unzipped folder." - : $"The 'internal/{packageDir.Name}' package folder is missing (should be at {packageDir})." - ); - Console.ReadLine(); - return; - } - if (!File.Exists(paths.executable)) - { - this.PrintError("The detected game install path doesn't contain a Stardew Valley executable."); - Console.ReadLine(); - return; + // get folders + DirectoryInfo packageDir = platform.IsMono() + ? new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)) // installer runs from internal folder on Mono + : new DirectoryInfo(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "internal", "Windows")); + paths = new InstallerPaths(packageDir, installDir, EnvironmentUtility.GetExecutableName(platform)); } + Console.Clear(); - /**** - ** validate Windows dependencies - ****/ - if (platform == Platform.Windows) + + /********* + ** Step 3: validate assumptions + *********/ { - // .NET Framework 4.5+ - if (!this.HasNetFramework45(platform)) + if (!paths.PackageDir.Exists) { - this.PrintError(Environment.OSVersion.Version >= this.Windows7Version - ? "Please install the latest version of .NET Framework before installing SMAPI." // Windows 7+ - : "Please install .NET Framework 4.5 before installing SMAPI." // Windows Vista or earlier + this.PrintError(platform == Platform.Windows && paths.PackagePath.Contains(Path.GetTempPath()) && paths.PackagePath.Contains(".zip") + ? "The installer is missing some files. It looks like you're running the installer from inside the downloaded zip; make sure you unzip the downloaded file first, then run the installer from the unzipped folder." + : $"The 'internal/{paths.PackageDir.Name}' package folder is missing (should be at {paths.PackagePath})." ); - this.PrintError("See the download page at https://www.microsoft.com/net/download/framework for details."); Console.ReadLine(); return; } - if (!this.HasXna(platform)) + + if (!File.Exists(paths.ExecutablePath)) { - this.PrintError("You don't seem to have XNA Framework installed. Please run the game at least once before installing SMAPI, so it can perform its first-time setup."); + this.PrintError("The detected game install path doesn't contain a Stardew Valley executable."); Console.ReadLine(); return; } } - Console.WriteLine(); - /**** - ** ask user what to do - ****/ + /********* + ** Step 4: ask what to do + *********/ ScriptAction action; - - if (installArg) - action = ScriptAction.Install; - else if (uninstallArg) - action = ScriptAction.Uninstall; - else { - this.PrintInfo("You can...."); - this.PrintInfo("[1] Install SMAPI."); - this.PrintInfo("[2] Uninstall SMAPI."); + /**** + ** print header + ****/ + this.PrintInfo("Hi there! I'll help you install or remove SMAPI. Just one question first."); + this.PrintDebug($"Game path: {paths.GamePath}"); + this.PrintDebug("----------------------------------------------------------------------------"); Console.WriteLine(); - string choice = this.InteractivelyChoose("What do you want to do? Type 1 or 2, then press enter.", "1", "2"); - switch (choice) + /**** + ** ask what to do + ****/ + if (installArg) + action = ScriptAction.Install; + else if (uninstallArg) + action = ScriptAction.Uninstall; + else { - case "1": - action = ScriptAction.Install; - break; - case "2": - action = ScriptAction.Uninstall; - break; - default: - throw new InvalidOperationException($"Unexpected action key '{choice}'."); + this.PrintInfo("What do you want to do?"); + Console.WriteLine(); + this.PrintInfo("[1] Install SMAPI."); + this.PrintInfo("[2] Uninstall SMAPI."); + Console.WriteLine(); + + string choice = this.InteractivelyChoose("What do you want to do? Type 1 or 2, then press enter.", new[] { "1", "2" }); + switch (choice) + { + case "1": + action = ScriptAction.Install; + break; + case "2": + action = ScriptAction.Uninstall; + break; + default: + throw new InvalidOperationException($"Unexpected action key '{choice}'."); + } } - Console.WriteLine(); } + Console.Clear(); - /**** - ** Always uninstall old files - ****/ - // restore game launcher - if (platform.IsMono() && File.Exists(paths.unixLauncherBackup)) - { - this.PrintDebug("Removing SMAPI launcher..."); - this.InteractivelyDelete(paths.unixLauncher); - File.Move(paths.unixLauncherBackup, paths.unixLauncher); - } - // remove old files - string[] removePaths = this.GetUninstallPaths(installDir, modsDir) - .Where(path => Directory.Exists(path) || File.Exists(path)) - .ToArray(); - if (removePaths.Any()) + /********* + ** Step 5: apply + *********/ { - this.PrintDebug(action == ScriptAction.Install ? "Removing previous SMAPI files..." : "Removing SMAPI files..."); - foreach (string path in removePaths) - this.InteractivelyDelete(path); - } + /**** + ** print header + ****/ + this.PrintInfo($"That's all I need! I'll {action.ToString().ToLower()} SMAPI now."); + this.PrintDebug($"Game path: {paths.GamePath}"); + this.PrintDebug("----------------------------------------------------------------------------"); + Console.WriteLine(); - /**** - ** Install new files - ****/ - if (action == ScriptAction.Install) - { - // copy SMAPI files to game dir - this.PrintDebug("Adding SMAPI files..."); - foreach (FileInfo sourceFile in packageDir.EnumerateFiles().Where(this.ShouldCopyFile)) + /**** + ** Always uninstall old files + ****/ + // restore game launcher + if (platform.IsMono() && File.Exists(paths.UnixBackupLauncherPath)) { - if (sourceFile.Name == this.InstallerFileName) - continue; - - string targetPath = Path.Combine(installDir.FullName, sourceFile.Name); - this.InteractivelyDelete(targetPath); - sourceFile.CopyTo(targetPath); + this.PrintDebug("Removing SMAPI launcher..."); + this.InteractivelyDelete(paths.UnixLauncherPath); + File.Move(paths.UnixBackupLauncherPath, paths.UnixLauncherPath); } - // replace mod launcher (if possible) - if (platform.IsMono()) + // remove old files + string[] removePaths = this.GetUninstallPaths(paths.GameDir, paths.ModsDir) + .Where(path => Directory.Exists(path) || File.Exists(path)) + .ToArray(); + if (removePaths.Any()) { - this.PrintDebug("Safely replacing game launcher..."); - if (File.Exists(paths.unixLauncher)) - { - if (!File.Exists(paths.unixLauncherBackup)) - File.Move(paths.unixLauncher, paths.unixLauncherBackup); - else - this.InteractivelyDelete(paths.unixLauncher); - } - - File.Move(paths.unixSmapiLauncher, paths.unixLauncher); + this.PrintDebug(action == ScriptAction.Install ? "Removing previous SMAPI files..." : "Removing SMAPI files..."); + foreach (string path in removePaths) + this.InteractivelyDelete(path); } - // create mods directory (if needed) - if (!modsDir.Exists) + /**** + ** Install new files + ****/ + if (action == ScriptAction.Install) { - this.PrintDebug("Creating mods directory..."); - modsDir.Create(); - } + // copy SMAPI files to game dir + this.PrintDebug("Adding SMAPI files..."); + foreach (FileInfo sourceFile in paths.PackageDir.EnumerateFiles().Where(this.ShouldCopyFile)) + { + if (sourceFile.Name == this.InstallerFileName) + continue; - // add or replace bundled mods - modsDir.Create(); - DirectoryInfo packagedModsDir = new DirectoryInfo(Path.Combine(packageDir.FullName, "Mods")); - if (packagedModsDir.Exists && packagedModsDir.EnumerateDirectories().Any()) - { - this.PrintDebug("Adding bundled mods..."); + string targetPath = Path.Combine(paths.GameDir.FullName, sourceFile.Name); + this.InteractivelyDelete(targetPath); + sourceFile.CopyTo(targetPath); + } - // special case: rename Omegasis' SaveBackup mod + // replace mod launcher (if possible) + if (platform.IsMono()) { - DirectoryInfo oldFolder = new DirectoryInfo(Path.Combine(modsDir.FullName, "SaveBackup")); - DirectoryInfo newFolder = new DirectoryInfo(Path.Combine(modsDir.FullName, "AdvancedSaveBackup")); - FileInfo manifest = new FileInfo(Path.Combine(oldFolder.FullName, "manifest.json")); - if (manifest.Exists && !newFolder.Exists && File.ReadLines(manifest.FullName).Any(p => p.IndexOf("Omegasis", StringComparison.InvariantCultureIgnoreCase) != -1)) + this.PrintDebug("Safely replacing game launcher..."); + if (File.Exists(paths.UnixLauncherPath)) { - this.PrintDebug($" moving {oldFolder.Name} to {newFolder.Name}..."); - this.Move(oldFolder, newFolder.FullName); + if (!File.Exists(paths.UnixBackupLauncherPath)) + File.Move(paths.UnixLauncherPath, paths.UnixBackupLauncherPath); + else + this.InteractivelyDelete(paths.UnixLauncherPath); } + + File.Move(paths.UnixSmapiLauncherPath, paths.UnixLauncherPath); } - // add bundled mods - foreach (DirectoryInfo sourceDir in packagedModsDir.EnumerateDirectories()) + // create mods directory (if needed) + if (!paths.ModsDir.Exists) { - this.PrintDebug($" adding {sourceDir.Name}..."); + this.PrintDebug("Creating mods directory..."); + paths.ModsDir.Create(); + } - // init/clear target dir - DirectoryInfo targetDir = new DirectoryInfo(Path.Combine(modsDir.FullName, sourceDir.Name)); - if (targetDir.Exists) + // add or replace bundled mods + DirectoryInfo packagedModsDir = new DirectoryInfo(Path.Combine(paths.PackageDir.FullName, "Mods")); + if (packagedModsDir.Exists && packagedModsDir.EnumerateDirectories().Any()) + { + this.PrintDebug("Adding bundled mods..."); + + // special case: rename Omegasis' SaveBackup mod { - this.ProtectBundledFiles.TryGetValue(targetDir.Name, out HashSet protectedFiles); - foreach (FileSystemInfo entry in targetDir.EnumerateFileSystemInfos()) + DirectoryInfo oldFolder = new DirectoryInfo(Path.Combine(paths.ModsDir.FullName, "SaveBackup")); + DirectoryInfo newFolder = new DirectoryInfo(Path.Combine(paths.ModsDir.FullName, "AdvancedSaveBackup")); + FileInfo manifest = new FileInfo(Path.Combine(oldFolder.FullName, "manifest.json")); + if (manifest.Exists && !newFolder.Exists && File.ReadLines(manifest.FullName).Any(p => p.IndexOf("Omegasis", StringComparison.InvariantCultureIgnoreCase) != -1)) { - if (protectedFiles == null || !protectedFiles.Contains(entry.Name)) - this.InteractivelyDelete(entry.FullName); + this.PrintDebug($" moving {oldFolder.Name} to {newFolder.Name}..."); + this.Move(oldFolder, newFolder.FullName); } } - else - targetDir.Create(); - // copy files - foreach (FileInfo sourceFile in sourceDir.EnumerateFiles().Where(this.ShouldCopyFile)) - sourceFile.CopyTo(Path.Combine(targetDir.FullName, sourceFile.Name)); + // add bundled mods + foreach (DirectoryInfo sourceDir in packagedModsDir.EnumerateDirectories()) + { + this.PrintDebug($" adding {sourceDir.Name}..."); + + // init/clear target dir + DirectoryInfo targetDir = new DirectoryInfo(Path.Combine(paths.ModsDir.FullName, sourceDir.Name)); + if (targetDir.Exists) + { + this.ProtectBundledFiles.TryGetValue(targetDir.Name, out HashSet protectedFiles); + foreach (FileSystemInfo entry in targetDir.EnumerateFileSystemInfos()) + { + if (protectedFiles == null || !protectedFiles.Contains(entry.Name)) + this.InteractivelyDelete(entry.FullName); + } + } + else + targetDir.Create(); + + // copy files + foreach (FileInfo sourceFile in sourceDir.EnumerateFiles().Where(this.ShouldCopyFile)) + sourceFile.CopyTo(Path.Combine(targetDir.FullName, sourceFile.Name)); + } } - } - // remove obsolete appdata mods - this.InteractivelyRemoveAppDataMods(modsDir, packagedModsDir); + // remove obsolete appdata mods + this.InteractivelyRemoveAppDataMods(paths.ModsDir, packagedModsDir); + } } Console.WriteLine(); Console.WriteLine(); - /**** - ** final instructions - ****/ + + /********* + ** Step 6: final instructions + *********/ if (platform == Platform.Windows) { if (action == ScriptAction.Install) { this.PrintSuccess("SMAPI is installed! If you use Steam, set your launch options to enable achievements (see smapi.io/install):"); - this.PrintSuccess($" \"{Path.Combine(installDir.FullName, "StardewModdingAPI.exe")}\" %command%"); + this.PrintSuccess($" \"{Path.Combine(paths.GamePath, "StardewModdingAPI.exe")}\" %command%"); Console.WriteLine(); this.PrintSuccess("If you don't use Steam, launch StardewModdingAPI.exe in your game folder to play with mods."); } @@ -594,17 +644,22 @@ namespace StardewModdingApi.Installer } /// Interactively ask the user to choose a value. + /// A callback which prints a message to the console. /// The message to print. /// The allowed options (not case sensitive). - private string InteractivelyChoose(string message, params string[] options) + /// The indentation to prefix to output. + private string InteractivelyChoose(string message, string[] options, string indent = "", Action print = null) { + print = print ?? this.PrintInfo; + while (true) { - this.PrintInfo(message); + print(indent + message); + Console.Write(indent); string input = Console.ReadLine()?.Trim().ToLowerInvariant(); if (!options.Contains(input)) { - this.PrintInfo("That's not a valid option."); + print($"{indent}That's not a valid option."); continue; } return input; diff --git a/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj b/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj index 2ad7e82a..e82c6093 100644 --- a/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj +++ b/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj @@ -40,6 +40,7 @@ Properties\GlobalAssemblyInfo.cs + -- cgit From 4e49ce8547c926f13589807a1ac70a3406a1cf01 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 11 Aug 2018 23:19:21 -0400 Subject: let Linux/Mac players choose the console scheme when installing (#554) --- src/SMAPI.Installer/InteractiveInstaller.cs | 94 +++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 6 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index b686e5bc..bb953865 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -136,7 +136,7 @@ namespace StardewModdingApi.Installer } /// Handles writing color-coded text to the console. - private readonly ColorfulConsoleWriter ConsoleWriter; + private ColorfulConsoleWriter ConsoleWriter; /********* @@ -245,7 +245,55 @@ namespace StardewModdingApi.Installer /********* - ** Step 2: find game folder + ** Step 2: choose a theme (can't auto-detect on Linux/Mac) + *********/ + MonitorColorScheme scheme = MonitorColorScheme.AutoDetect; + if (platform == Platform.Linux || platform == Platform.Mac) + { + /**** + ** print header + ****/ + this.PrintPlain("Hi there! I'll help you install or remove SMAPI. Just a few questions first."); + this.PrintPlain("----------------------------------------------------------------------------"); + Console.WriteLine(); + + /**** + ** show theme selector + ****/ + // get theme writers + var lightBackgroundWriter = new ColorfulConsoleWriter(EnvironmentUtility.DetectPlatform(), MonitorColorScheme.LightBackground); + var darkDarkgroundWriter = new ColorfulConsoleWriter(EnvironmentUtility.DetectPlatform(), MonitorColorScheme.DarkBackground); + + // print question + this.PrintPlain("Which text looks more readable?"); + Console.WriteLine(); + Console.Write(" [1] "); + lightBackgroundWriter.WriteLine("Dark text on light background", ConsoleLogLevel.Info); + Console.Write(" [2] "); + darkDarkgroundWriter.WriteLine("Light text on dark background", ConsoleLogLevel.Info); + Console.WriteLine(); + + // handle choice + string choice = this.InteractivelyChoose("Type 1 or 2, then press enter.", new[] { "1", "2" }); + switch (choice) + { + case "1": + scheme = MonitorColorScheme.LightBackground; + this.ConsoleWriter = lightBackgroundWriter; + break; + case "2": + scheme = MonitorColorScheme.DarkBackground; + this.ConsoleWriter = darkDarkgroundWriter; + break; + default: + throw new InvalidOperationException($"Unexpected action key '{choice}'."); + } + } + Console.Clear(); + + + /********* + ** Step 3: find game folder *********/ InstallerPaths paths; { @@ -253,6 +301,7 @@ namespace StardewModdingApi.Installer ** print header ****/ this.PrintInfo("Hi there! I'll help you install or remove SMAPI. Just a few questions first."); + this.PrintDebug($"Color scheme: {this.GetDisplayText(scheme)}"); this.PrintDebug("----------------------------------------------------------------------------"); Console.WriteLine(); @@ -279,7 +328,7 @@ namespace StardewModdingApi.Installer /********* - ** Step 3: validate assumptions + ** Step 4: validate assumptions *********/ { if (!paths.PackageDir.Exists) @@ -302,7 +351,7 @@ namespace StardewModdingApi.Installer /********* - ** Step 4: ask what to do + ** Step 5: ask what to do *********/ ScriptAction action; { @@ -311,6 +360,7 @@ namespace StardewModdingApi.Installer ****/ this.PrintInfo("Hi there! I'll help you install or remove SMAPI. Just one question first."); this.PrintDebug($"Game path: {paths.GamePath}"); + this.PrintDebug($"Color scheme: {this.GetDisplayText(scheme)}"); this.PrintDebug("----------------------------------------------------------------------------"); Console.WriteLine(); @@ -347,7 +397,7 @@ namespace StardewModdingApi.Installer /********* - ** Step 5: apply + ** Step 6: apply *********/ { /**** @@ -355,6 +405,7 @@ namespace StardewModdingApi.Installer ****/ this.PrintInfo($"That's all I need! I'll {action.ToString().ToLower()} SMAPI now."); this.PrintDebug($"Game path: {paths.GamePath}"); + this.PrintDebug($"Color scheme: {this.GetDisplayText(scheme)}"); this.PrintDebug("----------------------------------------------------------------------------"); Console.WriteLine(); @@ -460,6 +511,16 @@ namespace StardewModdingApi.Installer foreach (FileInfo sourceFile in sourceDir.EnumerateFiles().Where(this.ShouldCopyFile)) sourceFile.CopyTo(Path.Combine(targetDir.FullName, sourceFile.Name)); } + + // set SMAPI's color scheme if defined + if (scheme != MonitorColorScheme.AutoDetect) + { + string configPath = Path.Combine(paths.GamePath, "StardewModdingAPI.config.json"); + string text = File + .ReadAllText(configPath) + .Replace(@"""ColorScheme"": ""AutoDetect""", $@"""ColorScheme"": ""{scheme}"""); + File.WriteAllText(configPath, text); + } } // remove obsolete appdata mods @@ -471,7 +532,7 @@ namespace StardewModdingApi.Installer /********* - ** Step 6: final instructions + ** Step 7: final instructions *********/ if (platform == Platform.Windows) { @@ -510,6 +571,23 @@ namespace StardewModdingApi.Installer return str; } + /// Get the display text for a color scheme. + /// The color scheme. + private string GetDisplayText(MonitorColorScheme scheme) + { + switch (scheme) + { + case MonitorColorScheme.AutoDetect: + return "auto-detect"; + case MonitorColorScheme.DarkBackground: + return "light text on dark background"; + case MonitorColorScheme.LightBackground: + return "dark text on light background"; + default: + return scheme.ToString(); + } + } + /// Get the value of a key in the Windows HKLM registry. /// The full path of the registry key relative to HKLM. /// The name of the value. @@ -536,6 +614,10 @@ namespace StardewModdingApi.Installer return (string)openKey.GetValue(name); } + /// Print a message without formatting. + /// The text to print. + private void PrintPlain(string text) => Console.WriteLine(text); + /// Print a debug message. /// The text to print. private void PrintDebug(string text) => this.ConsoleWriter.WriteLine(text, ConsoleLogLevel.Debug); -- cgit From 13f9a4d8d2155463f9ceaa41dd15d4526927476e Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 12 Aug 2018 00:51:27 -0400 Subject: fix redundant text (#554) --- src/SMAPI.Installer/InteractiveInstaller.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index bb953865..0aac1da2 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -379,7 +379,7 @@ namespace StardewModdingApi.Installer this.PrintInfo("[2] Uninstall SMAPI."); Console.WriteLine(); - string choice = this.InteractivelyChoose("What do you want to do? Type 1 or 2, then press enter.", new[] { "1", "2" }); + string choice = this.InteractivelyChoose("Type 1 or 2, then press enter.", new[] { "1", "2" }); switch (choice) { case "1": -- cgit