From 99d0450b2cb291d565cb836de9f132ca657472c1 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 4 Feb 2017 16:50:09 -0500 Subject: fix install error when the mods folder doesn't exist (#229) --- src/StardewModdingAPI.Installer/InteractiveInstaller.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 5abcfc8f..551c648c 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -80,8 +80,11 @@ namespace StardewModdingApi.Installer // obsolete yield return installPath("Mods/.cache"); // 1.3-1.4 yield return installPath("StardewModdingAPI-settings.json"); // 1.0-1.4 - foreach (DirectoryInfo modDir in modsDir.EnumerateDirectories()) - yield return Path.Combine(modDir.FullName, ".cache"); // 1.4–1.7 + if (modsDir.Exists) + { + foreach (DirectoryInfo modDir in modsDir.EnumerateDirectories()) + yield return Path.Combine(modDir.FullName, ".cache"); // 1.4–1.7 + } } /// Whether the current console supports color formatting. -- cgit From 036595cc712d20e7c0fb9a9a9444d5206a25ad7e Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 8 Feb 2017 00:53:53 -0500 Subject: remove old log file to avoid confusion (#231) --- src/StardewModdingAPI.Installer/InteractiveInstaller.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 551c648c..d6d395b6 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -85,6 +85,7 @@ namespace StardewModdingApi.Installer foreach (DirectoryInfo modDir in modsDir.EnumerateDirectories()) yield return Path.Combine(modDir.FullName, ".cache"); // 1.4–1.7 } + yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "ErrorLogs", "MODDED_ProgramLog.Log_LATEST.txt"); // *–1.8 } /// Whether the current console supports color formatting. -- cgit From a13003de8b8601ac693d7af960fab67d285dbd0e Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 9 Feb 2017 22:38:10 -0500 Subject: remove Mono.Cecil.Rocks (#231) It's not needed since we're not injecting new instructions, and causes the field rewriters to fail unexpectedly. --- README.md | 2 -- src/StardewModdingAPI.Installer/InteractiveInstaller.cs | 6 +++--- src/StardewModdingAPI/Framework/AssemblyLoader.cs | 3 --- src/StardewModdingAPI/StardewModdingAPI.csproj | 4 ---- src/prepare-install-package.targets | 2 -- 5 files changed, 3 insertions(+), 14 deletions(-) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/README.md b/README.md index b1062077..63adcf78 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,6 @@ folder containing `src`). Mono/ Mods/* Mono.Cecil.dll - Mono.Cecil.Rocks.dll Newtonsoft.Json.dll StardewModdingAPI StardewModdingAPI.AssemblyRewriters.dll @@ -95,7 +94,6 @@ folder containing `src`). Windows/ Mods/* Mono.Cecil.dll - Mono.Cecil.Rocks.dll Newtonsoft.Json.dll StardewModdingAPI.AssemblyRewriters.dll StardewModdingAPI.config.json diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index d6d395b6..868889fa 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -59,6 +59,8 @@ namespace StardewModdingApi.Installer Func installPath = path => Path.Combine(installDir.FullName, path); // common + yield return installPath("Mono.Cecil.dll"); + yield return installPath("Newtonsoft.Json.dll"); yield return installPath("StardewModdingAPI.exe"); yield return installPath("StardewModdingAPI.config.json"); yield return installPath("StardewModdingAPI.data.json"); @@ -66,9 +68,6 @@ namespace StardewModdingApi.Installer yield return installPath("steam_appid.txt"); // Linux/Mac only - yield return installPath("Mono.Cecil.dll"); - yield return installPath("Mono.Cecil.Rocks.dll"); - yield return installPath("Newtonsoft.Json.dll"); yield return installPath("StardewModdingAPI"); yield return installPath("StardewModdingAPI.exe.mdb"); yield return installPath("System.Numerics.dll"); @@ -79,6 +78,7 @@ namespace StardewModdingApi.Installer // obsolete yield return installPath("Mods/.cache"); // 1.3-1.4 + yield return installPath("Mono.Cecil.Rocks.dll"); // 1.3–1.8 yield return installPath("StardewModdingAPI-settings.json"); // 1.0-1.4 if (modsDir.Exists) { diff --git a/src/StardewModdingAPI/Framework/AssemblyLoader.cs b/src/StardewModdingAPI/Framework/AssemblyLoader.cs index d5e8f5ee..0cf6e569 100644 --- a/src/StardewModdingAPI/Framework/AssemblyLoader.cs +++ b/src/StardewModdingAPI/Framework/AssemblyLoader.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Reflection; using Mono.Cecil; using Mono.Cecil.Cil; -using Mono.Cecil.Rocks; using StardewModdingAPI.AssemblyRewriters; namespace StardewModdingAPI.Framework @@ -195,7 +194,6 @@ namespace StardewModdingAPI.Framework continue; // prepare method - method.Body.SimplifyMacros(); ILProcessor cil = method.Body.GetILProcessor(); // rewrite instructions @@ -206,7 +204,6 @@ namespace StardewModdingAPI.Framework } // finalise method - method.Body.OptimizeMacros(); anyRewritten = true; } diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj index d148e0c8..eca2713f 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.csproj +++ b/src/StardewModdingAPI/StardewModdingAPI.csproj @@ -90,10 +90,6 @@ ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll True - - ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll - True - ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True diff --git a/src/prepare-install-package.targets b/src/prepare-install-package.targets index f411b909..bd9287f1 100644 --- a/src/prepare-install-package.targets +++ b/src/prepare-install-package.targets @@ -23,7 +23,6 @@ - @@ -38,7 +37,6 @@ - -- cgit From 95786e9e44ed2ddfc0d38e8279b8c0166db7fc85 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 12 Feb 2017 18:43:21 -0500 Subject: encapsulate file & folder deletion (#237) --- .../InteractiveInstaller.cs | 30 ++++++++++++---------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 868889fa..36301829 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -104,7 +104,7 @@ namespace StardewModdingApi.Installer /// /// Uninstall logic: /// 1. On Linux/Mac: if a backup of the launcher exists, delete the launcher and restore the backup. - /// 2. Delete all files and folders in the game directory matching one of the . + /// 2. Delete all files and folders in the game directory matching one of the values returned by . /// /// Install flow: /// 1. Run the uninstall flow. @@ -179,8 +179,7 @@ namespace StardewModdingApi.Installer if (platform == Platform.Mono && File.Exists(paths.unixLauncherBackup)) { this.PrintDebug("Removing SMAPI launcher..."); - if (File.Exists(paths.unixLauncher)) - File.Delete(paths.unixLauncher); + this.InteractivelyDelete(paths.unixLauncher); File.Move(paths.unixLauncherBackup, paths.unixLauncher); } @@ -192,12 +191,7 @@ namespace StardewModdingApi.Installer { this.PrintDebug(action == ScriptAction.Install ? "Removing previous SMAPI files..." : "Removing SMAPI files..."); foreach (string path in removePaths) - { - if (Directory.Exists(path)) - Directory.Delete(path, recursive: true); - else - File.Delete(path); - } + this.InteractivelyDelete(path); } /**** @@ -210,8 +204,7 @@ namespace StardewModdingApi.Installer foreach (FileInfo sourceFile in packageDir.EnumerateFiles()) { string targetPath = Path.Combine(installDir.FullName, sourceFile.Name); - if (File.Exists(targetPath)) - File.Delete(targetPath); + this.InteractivelyDelete(targetPath); sourceFile.CopyTo(targetPath); } @@ -222,7 +215,7 @@ namespace StardewModdingApi.Installer if (!File.Exists(paths.unixLauncherBackup)) File.Move(paths.unixLauncher, paths.unixLauncherBackup); else if (File.Exists(paths.unixLauncher)) - File.Delete(paths.unixLauncher); + this.InteractivelyDelete(paths.unixLauncher); File.Move(paths.unixSmapiLauncher, paths.unixLauncher); } @@ -246,8 +239,7 @@ namespace StardewModdingApi.Installer // initialise target dir DirectoryInfo targetDir = new DirectoryInfo(Path.Combine(modsDir.FullName, sourceDir.Name)); - if (targetDir.Exists) - targetDir.Delete(recursive: true); + this.InteractivelyDelete(targetDir.FullName); targetDir.Create(); // copy files @@ -364,6 +356,16 @@ namespace StardewModdingApi.Installer Console.WriteLine(text); } + /// Interactively delete a file or folder path. + /// The file or folder path. + private void InteractivelyDelete(string path) + { + if (Directory.Exists(path)) + Directory.Delete(path, recursive: true); + else if (File.Exists(path)) + File.Delete(path); + } + /// Interactively ask the user to choose a value. /// The message to print. /// The allowed options (not case sensitive). -- cgit From 96c21b1acc2140fb58b5ba214f42b709b2893e74 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 12 Feb 2017 19:11:00 -0500 Subject: avoid special case in error printing (#237) --- src/StardewModdingAPI.Installer/InteractiveInstaller.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 36301829..c751cef9 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -137,12 +137,14 @@ namespace StardewModdingApi.Installer ****/ if (!packageDir.Exists) { - this.ExitError($"The 'internal/{platform}' package folder is missing (should be at {packageDir})."); + this.PrintError($"The 'internal/{platform}' package folder is missing (should be at {packageDir})."); + Console.ReadLine(); return; } if (!File.Exists(paths.executable)) { - this.ExitError("The detected game install path doesn't contain a Stardew Valley executable."); + this.PrintError("The detected game install path doesn't contain a Stardew Valley executable."); + Console.ReadLine(); return; } Console.WriteLine(); @@ -333,12 +335,11 @@ namespace StardewModdingApi.Installer this.PrintColor(text, ConsoleColor.DarkYellow); } - /// Print an error and pause the console if needed. - /// The error text. - private void ExitError(string error) + /// Print a warning message. + /// The text to print. + private void PrintError(string text) { - this.PrintColor(error, ConsoleColor.Red); - Console.ReadLine(); + this.PrintColor(text, ConsoleColor.Red); } /// Print a message to the console. -- cgit From e5324e170c27adddb4292c97c34a2e8f90dfe231 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 12 Feb 2017 19:39:38 -0500 Subject: handle permissions & delays in installer's file/folder deletion code (#237) --- .../InteractiveInstaller.cs | 56 ++++++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index c751cef9..86e11d71 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using System.Threading; #if SMAPI_FOR_WINDOWS using Microsoft.Win32; #endif @@ -357,14 +358,59 @@ namespace StardewModdingApi.Installer Console.WriteLine(text); } - /// Interactively delete a file or folder path. + /// Interactively delete a file or folder path, and block until deletion completes. /// The file or folder path. private void InteractivelyDelete(string path) { - if (Directory.Exists(path)) - Directory.Delete(path, recursive: true); - else if (File.Exists(path)) - File.Delete(path); + while (true) + { + try + { + this.ForceDelete(Directory.Exists(path) ? new DirectoryInfo(path) : (FileSystemInfo)new FileInfo(path)); + break; + } + catch (Exception ex) + { + this.PrintError($"Oops! The installer couldn't delete {path}: [{ex.GetType().Name}] {ex.Message}."); + this.PrintError("Please delete it yourself, then press any key to retry."); + Console.ReadKey(); + } + } + } + + /// Delete a file or folder regardless of file permissions, and block until deletion completes. + /// The file or folder to reset. + private void ForceDelete(FileSystemInfo entry) + { + // ignore if already deleted + entry.Refresh(); + if (!entry.Exists) + return; + + // delete children + var folder = entry as DirectoryInfo; + if (folder != null) + { + foreach (FileSystemInfo child in folder.GetFileSystemInfos()) + this.ForceDelete(child); + } + + // reset permissions & delete + entry.Attributes = FileAttributes.Normal; + entry.Delete(); + + // wait for deletion to finish + for (int i = 0; i < 10; i++) + { + entry.Refresh(); + if (entry.Exists) + Thread.Sleep(500); + } + + // throw exception if deletion didn't happen before timeout + entry.Refresh(); + if (entry.Exists) + throw new IOException($"Timed out trying to delete {entry.FullName}"); } /// Interactively ask the user to choose a value. -- cgit From a893cd9eeabdd88bd57a4b7e422de5f1d442073c Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 19 Feb 2017 01:07:04 -0500 Subject: fix installer not ignoring potential game folders that don't contain a Stardew Valley exe --- release-notes.md | 1 + src/StardewModdingAPI.Installer/InteractiveInstaller.cs | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/release-notes.md b/release-notes.md index a277ee4f..7cce15c4 100644 --- a/release-notes.md +++ b/release-notes.md @@ -9,6 +9,7 @@ For players: * Simple nested mod folders are now recognised by SMAPI (e.g. `ModName-1.0\ModName\manifest.json`). * Fixed game's debug output being shown in the console for all users. * Fixed installer errors for some players when deleting files. +* Fixed installer not ignoring potential game folders that don't contain a Stardew Valley exe. * Fixed rare issue where mod dependencies would override SMAPI dependencies and cause unpredictable bugs. For mod developers: diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 86e11d71..1496bedd 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -435,10 +435,16 @@ namespace StardewModdingApi.Installer /// The current platform. private DirectoryInfo InteractivelyGetInstallPath(Platform platform) { + // get executable name + string executableFilename = platform == Platform.Windows + ? "Stardew Valley.exe" + : "StardewValley.exe"; + // try default paths foreach (string defaultPath in this.DefaultInstallPaths) { - if (Directory.Exists(defaultPath)) + DirectoryInfo dir = new DirectoryInfo(defaultPath); + if (dir.Exists && dir.EnumerateFiles(executableFilename).Any()) return new DirectoryInfo(defaultPath); } @@ -447,7 +453,7 @@ namespace StardewModdingApi.Installer while (true) { // get path from user - Console.WriteLine($"Type the file path to the game directory (the one containing '{(platform == Platform.Mono ? "StardewValley.exe" : "Stardew Valley.exe")}'), then press enter."); + Console.WriteLine($"Type the file path to the game directory (the one containing '{executableFilename}'), then press enter."); string path = Console.ReadLine()?.Trim(); if (string.IsNullOrWhiteSpace(path)) { @@ -470,7 +476,7 @@ namespace StardewModdingApi.Installer Console.WriteLine(" That directory doesn't seem to exist."); continue; } - if (!directory.EnumerateFiles("*.exe").Any(p => p.Name == "StardewValley.exe" || p.Name == "Stardew Valley.exe")) + if (!directory.EnumerateFiles(executableFilename).Any()) { Console.WriteLine(" That directory doesn't contain a Stardew Valley executable."); continue; -- cgit From c72adcd119d9e96f47f93a2a7d5beb4974dffc0b Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 19 Feb 2017 01:28:00 -0500 Subject: use more robust crossplatform path checks in installer --- .../InteractiveInstaller.cs | 62 +++++++++++----------- 1 file changed, 32 insertions(+), 30 deletions(-) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 1496bedd..7f59ed2a 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -4,9 +4,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Threading; -#if SMAPI_FOR_WINDOWS using Microsoft.Win32; -#endif using StardewModdingApi.Installer.Enums; namespace StardewModdingApi.Installer @@ -18,37 +16,43 @@ namespace StardewModdingApi.Installer ** Properties *********/ /// The default file paths where Stardew Valley can be installed. + /// The target platform. /// Derived from the crossplatform mod config: https://github.com/Pathoschild/Stardew.ModBuildConfig. - private IEnumerable DefaultInstallPaths + private IEnumerable GetDefaultInstallPaths(Platform platform) { - get + switch (platform) { - // Linux - yield return $"{Environment.GetEnvironmentVariable("HOME")}/GOG Games/Stardew Valley/game"; - yield return $"{Environment.GetEnvironmentVariable("HOME")}/.local/share/Steam/steamapps/common/Stardew Valley"; + case Platform.Mono: + // Linux + yield return $"{Environment.GetEnvironmentVariable("HOME")}/GOG Games/Stardew Valley/game"; + yield return $"{Environment.GetEnvironmentVariable("HOME")}/.local/share/Steam/steamapps/common/Stardew Valley"; + + // Mac + yield return "/Applications/Stardew Valley.app/Contents/MacOS"; + yield return $"{Environment.GetEnvironmentVariable("HOME")}/Library/Application Support/Steam/steamapps/common/Stardew Valley/Contents/MacOS"; + break; - // Mac - yield return "/Applications/Stardew Valley.app/Contents/MacOS"; - yield return $"{Environment.GetEnvironmentVariable("HOME")}/Library/Application Support/Steam/steamapps/common/Stardew Valley/Contents/MacOS"; + case Platform.Windows: + // Windows + yield return @"C:\Program Files (x86)\GalaxyClient\Games\Stardew Valley"; + yield return @"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley"; - // Windows - yield return @"C:\Program Files (x86)\GalaxyClient\Games\Stardew Valley"; - yield return @"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley"; + // Windows registry + IDictionary registryKeys = new Dictionary + { + [@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 413150"] = "InstallLocation", // Steam + [@"SOFTWARE\WOW6432Node\GOG.com\Games\1453375253"] = "PATH", // GOG on 64-bit Windows + }; + foreach (var pair in registryKeys) + { + string path = this.GetLocalMachineRegistryValue(pair.Key, pair.Value); + if (!string.IsNullOrWhiteSpace(path)) + yield return path; + } + break; - // Windows registry -#if SMAPI_FOR_WINDOWS - IDictionary registryKeys = new Dictionary - { - [@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 413150"] = "InstallLocation", // Steam - [@"SOFTWARE\WOW6432Node\GOG.com\Games\1453375253"] = "PATH", // GOG on 64-bit Windows - }; - foreach (var pair in registryKeys) - { - string path = this.GetLocalMachineRegistryValue(pair.Key, pair.Value); - if (!string.IsNullOrWhiteSpace(path)) - yield return path; - } -#endif + default: + throw new InvalidOperationException($"Unknown platform '{platform}'."); } } @@ -307,7 +311,6 @@ namespace StardewModdingApi.Installer } } -#if SMAPI_FOR_WINDOWS /// Get the value of a key in the Windows registry. /// The full path of the registry key relative to HKLM. /// The name of the value. @@ -320,7 +323,6 @@ namespace StardewModdingApi.Installer using (openKey) return (string)openKey.GetValue(name); } -#endif /// Print a debug message. /// The text to print. @@ -441,7 +443,7 @@ namespace StardewModdingApi.Installer : "StardewValley.exe"; // try default paths - foreach (string defaultPath in this.DefaultInstallPaths) + foreach (string defaultPath in this.GetDefaultInstallPaths(platform)) { DirectoryInfo dir = new DirectoryInfo(defaultPath); if (dir.Exists && dir.EnumerateFiles(executableFilename).Any()) -- cgit From 69ed617e568c9f2e4a15aee4a7bdecba03c13341 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 19 Feb 2017 01:29:30 -0500 Subject: fix installer not recognising Linux/Mac paths starting with ~ or containing an escaped space --- release-notes.md | 1 + src/StardewModdingAPI.Installer/InteractiveInstaller.cs | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/release-notes.md b/release-notes.md index 7cce15c4..b827f6bf 100644 --- a/release-notes.md +++ b/release-notes.md @@ -10,6 +10,7 @@ For players: * Fixed game's debug output being shown in the console for all users. * Fixed installer errors for some players when deleting files. * Fixed installer not ignoring potential game folders that don't contain a Stardew Valley exe. +* Fixed installer not recognising Linux/Mac paths starting with `~/` or containing an escaped space. * Fixed rare issue where mod dependencies would override SMAPI dependencies and cause unpredictable bugs. For mod developers: diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 7f59ed2a..7dcd88fd 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -463,9 +463,16 @@ namespace StardewModdingApi.Installer continue; } - // normalise on Windows + // normalise path if (platform == Platform.Windows) path = path.Replace("\"", ""); // in Windows, quotes are used to escape spaces and aren't part of the file path + if (platform == Platform.Mono) + 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)) -- cgit From 79e63fde9a54717378bb29ea97d7b90e6bf56091 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 14 Mar 2017 19:36:18 -0400 Subject: validate .NET Framework 4.5+ is installed on Windows in SMAPI installer --- release-notes.md | 3 +- .../InteractiveInstaller.cs | 34 ++++++++++++++++++++++ src/StardewModdingAPI.sln | 4 +-- 3 files changed, 38 insertions(+), 3 deletions(-) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/release-notes.md b/release-notes.md index f91ef733..3f7b9f9e 100644 --- a/release-notes.md +++ b/release-notes.md @@ -15,7 +15,8 @@ See [log](https://github.com/Pathoschild/SMAPI/compare/1.8...1.9). For players: * Updated for Stardew Valley 1.2. Most mods are now rewritten for compatibility; some mods require an update from their authors. -* Added automatic detection of incompatible mods so they're disabled before they cause problems. +* SMAPI now automatically detects incompatible mods and disables them before they cause problems. +* The installer now automatically detects if you need to update .NET Framework before SMAPI will work. * Simplified log filename. * Simplified error messages when a mod can't be loaded. * Simple nested mod folders are now recognised by SMAPI (e.g. `ModName-1.0\ModName\manifest.json`). diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 7dcd88fd..52d0642a 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -15,6 +15,9 @@ namespace StardewModdingApi.Installer /********* ** Properties *********/ + /// The value that represents Windows 7. + private readonly Version Windows7Version = new Version(6, 1); + /// The default file paths where Stardew Valley can be installed. /// The target platform. /// Derived from the crossplatform mod config: https://github.com/Pathoschild/Stardew.ModBuildConfig. @@ -152,6 +155,21 @@ namespace StardewModdingApi.Installer Console.ReadLine(); return; } + + /**** + ** validate .NET Framework version + ****/ + if (platform == Platform.Windows && !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; + } + Console.WriteLine(); /**** @@ -360,6 +378,22 @@ namespace StardewModdingApi.Installer Console.WriteLine(text); } + /// Get whether the current system has .NET Framework 4.5 or later installed. + /// The current platform. + /// The current platform is not Windows. + private bool HasNetFramework45(Platform platform) + { + switch (platform) + { + case Platform.Windows: + using (RegistryKey versionKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full")) + return versionKey?.GetValue("Release") != null; // .NET Framework 4.5+ + + default: + throw new NotSupportedException("The installed .NET Framework version can only be checked on Windows."); + } + } + /// Interactively delete a file or folder path, and block until deletion completes. /// The file or folder path. private void InteractivelyDelete(string path) diff --git a/src/StardewModdingAPI.sln b/src/StardewModdingAPI.sln index 8ab297ed..441b51a9 100644 --- a/src/StardewModdingAPI.sln +++ b/src/StardewModdingAPI.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrainerMod", "TrainerMod\TrainerMod.csproj", "{28480467-1A48-46A7-99F8-236D95225359}" EndProject -- cgit From abfa2022aad8478c369158e89a38eaae9bd81c96 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 16 Mar 2017 17:06:53 -0400 Subject: validate XNA 4.0+ is installed on Windows in SMAPI installer --- release-notes.md | 1 + .../InteractiveInstaller.cs | 46 +++++++++++++++++----- 2 files changed, 37 insertions(+), 10 deletions(-) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/release-notes.md b/release-notes.md index e8b6ccfd..9d133f30 100644 --- a/release-notes.md +++ b/release-notes.md @@ -19,6 +19,7 @@ For players: * SMAPI now detects incompatible mods and disables them before they cause problems. * SMAPI now allows mods nested into an otherwise empty parent folder (like `Mods\ModName-1.0\ModName\manifest.json`), since that's a common default behaviour when unpacking mods. * The installer now detects if you need to update .NET Framework before installing SMAPI. +* The installer now detects if you need to run the game at least once (to let it perform first-time setup) before installing SMAPI. * The console now has simpler error messages. * The console now has improved command handling & feedback. * The console no longer shows the game's debug output (unless you use a _SMAPI for developers_ build). diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 52d0642a..0e920f1f 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -157,17 +157,27 @@ namespace StardewModdingApi.Installer } /**** - ** validate .NET Framework version + ** validate Windows dependencies ****/ - if (platform == Platform.Windows && !this.HasNetFramework45(platform)) + if (platform == Platform.Windows) { - 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; + // .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; + } } Console.WriteLine(); @@ -378,7 +388,7 @@ namespace StardewModdingApi.Installer Console.WriteLine(text); } - /// Get whether the current system has .NET Framework 4.5 or later installed. + /// Get whether the current system has .NET Framework 4.5 or later installed. This only applies on Windows. /// The current platform. /// The current platform is not Windows. private bool HasNetFramework45(Platform platform) @@ -394,6 +404,22 @@ namespace StardewModdingApi.Installer } } + /// Get whether the current system has XNA Framework installed. This only applies on Windows. + /// The current platform. + /// The current platform is not Windows. + private bool HasXNA(Platform platform) + { + switch (platform) + { + case Platform.Windows: + using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\XNA\Framework")) + return key != null; // XNA Framework 4.0+ + + default: + throw new NotSupportedException("The installed XNA Framework version can only be checked on Windows."); + } + } + /// Interactively delete a file or folder path, and block until deletion completes. /// The file or folder path. private void InteractivelyDelete(string path) -- cgit From 45d2ed705473f51935af269c852a94432968a15c Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 16 Mar 2017 19:01:22 -0400 Subject: add another default game path for Linux Thanks to ShneekeyTheLost on the Stardew Valley forums. --- release-notes.md | 1 + src/StardewModdingAPI.Installer/InteractiveInstaller.cs | 1 + 2 files changed, 2 insertions(+) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/release-notes.md b/release-notes.md index 9d133f30..67286308 100644 --- a/release-notes.md +++ b/release-notes.md @@ -20,6 +20,7 @@ For players: * SMAPI now allows mods nested into an otherwise empty parent folder (like `Mods\ModName-1.0\ModName\manifest.json`), since that's a common default behaviour when unpacking mods. * The installer now detects if you need to update .NET Framework before installing SMAPI. * The installer now detects if you need to run the game at least once (to let it perform first-time setup) before installing SMAPI. +* The installer on Linux now finds games installed to `~/.steam/steam/steamapps/common/Stardew Valley` too. * The console now has simpler error messages. * The console now has improved command handling & feedback. * The console no longer shows the game's debug output (unless you use a _SMAPI for developers_ build). diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 0e920f1f..33cbc2dc 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -29,6 +29,7 @@ namespace StardewModdingApi.Installer // Linux yield return $"{Environment.GetEnvironmentVariable("HOME")}/GOG Games/Stardew Valley/game"; yield return $"{Environment.GetEnvironmentVariable("HOME")}/.local/share/Steam/steamapps/common/Stardew Valley"; + yield return $"{Environment.GetEnvironmentVariable("HOME")}/.steam/steam/steamapps/common/Stardew Valley"; // Mac yield return "/Applications/Stardew Valley.app/Contents/MacOS"; -- cgit From b4b4689f00c74b50842e3f651be6bbe297b5f02d Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 30 Mar 2017 19:48:01 -0400 Subject: remove old error logs when installing a new version to avoid confusion --- release-notes.md | 1 + src/StardewModdingAPI.Installer/InteractiveInstaller.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src/StardewModdingAPI.Installer/InteractiveInstaller.cs') diff --git a/release-notes.md b/release-notes.md index 55740ef1..bde3e4b0 100644 --- a/release-notes.md +++ b/release-notes.md @@ -24,6 +24,7 @@ For players: * The installer now detects if you need to update .NET Framework before installing SMAPI. * The installer now detects if you need to run the game at least once (to let it perform first-time setup) before installing SMAPI. * The installer on Linux now finds games installed to `~/.steam/steam/steamapps/common/Stardew Valley` too. +* The installer now removes old SMAPI logs to prevent confusion. * The console now has simpler error messages. * The console now has improved command handling & feedback. * The console no longer shows the game's debug output (unless you use a _SMAPI for developers_ build). diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 33cbc2dc..fffba30f 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -94,7 +94,7 @@ namespace StardewModdingApi.Installer foreach (DirectoryInfo modDir in modsDir.EnumerateDirectories()) yield return Path.Combine(modDir.FullName, ".cache"); // 1.4–1.7 } - yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "ErrorLogs", "MODDED_ProgramLog.Log_LATEST.txt"); // *–1.8 + yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "ErrorLogs"); // remove old log files } /// Whether the current console supports color formatting. -- cgit