From 826dd53ab550e5b92796c510569118beee6bd044 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 19 Aug 2018 18:28:16 -0400 Subject: move most SMAPI files into subfolder (#582) --- src/SMAPI.Installer/InteractiveInstaller.cs | 115 +++++++++++++++++----------- 1 file changed, 71 insertions(+), 44 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index 0aac1da2..f9e1ff94 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -93,40 +93,39 @@ namespace StardewModdingApi.Installer { string GetInstallPath(string path) => Path.Combine(installDir.FullName, path); - // common - yield return GetInstallPath("0Harmony.dll"); - yield return GetInstallPath("0Harmony.pdb"); - yield return GetInstallPath("Mono.Cecil.dll"); - yield return GetInstallPath("Newtonsoft.Json.dll"); + // current files + yield return GetInstallPath("libgdiplus.dylib"); // Linux/Mac only + yield return GetInstallPath("StardewModdingAPI"); // Linux/Mac only yield return GetInstallPath("StardewModdingAPI.exe"); - yield return GetInstallPath("StardewModdingAPI.config.json"); - yield return GetInstallPath("StardewModdingAPI.metadata.json"); - yield return GetInstallPath("StardewModdingAPI.Toolkit.dll"); - yield return GetInstallPath("StardewModdingAPI.Toolkit.pdb"); - yield return GetInstallPath("StardewModdingAPI.Toolkit.xml"); - yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.dll"); - yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.pdb"); - yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.xml"); + yield return GetInstallPath("StardewModdingAPI.exe.mdb"); // Linux/Mac only + yield return GetInstallPath("StardewModdingAPI.pdb"); // Windows only yield return GetInstallPath("StardewModdingAPI.xml"); - yield return GetInstallPath("System.ValueTuple.dll"); - yield return GetInstallPath("steam_appid.txt"); - - // Linux/Mac only - yield return GetInstallPath("libgdiplus.dylib"); - yield return GetInstallPath("StardewModdingAPI"); - yield return GetInstallPath("StardewModdingAPI.exe.mdb"); - yield return GetInstallPath("System.Numerics.dll"); - yield return GetInstallPath("System.Runtime.Caching.dll"); - - // Windows only - yield return GetInstallPath("StardewModdingAPI.pdb"); + yield return GetInstallPath("smapi-internal"); // obsolete - yield return GetInstallPath(Path.Combine("Mods", ".cache")); // 1.3-1.4 + yield return GetInstallPath(Path.Combine("Mods", ".cache")); // 1.3-1.4 yield return GetInstallPath(Path.Combine("Mods", "TrainerMod")); // *–2.0 (renamed to ConsoleCommands) - yield return GetInstallPath("Mono.Cecil.Rocks.dll"); // 1.3–1.8 - yield return GetInstallPath("StardewModdingAPI-settings.json"); // 1.0-1.4 + yield return GetInstallPath("Mono.Cecil.Rocks.dll"); // 1.3–1.8 + yield return GetInstallPath("StardewModdingAPI-settings.json"); // 1.0-1.4 yield return GetInstallPath("StardewModdingAPI.AssemblyRewriters.dll"); // 1.3-2.5.5 + yield return GetInstallPath("0Harmony.dll"); // moved in 2.8 + yield return GetInstallPath("0Harmony.pdb"); // moved in 2.8 + yield return GetInstallPath("Mono.Cecil.dll"); // moved in 2.8 + yield return GetInstallPath("Newtonsoft.Json.dll"); // moved in 2.8 + yield return GetInstallPath("StardewModdingAPI.config.json"); // moved in 2.8 + yield return GetInstallPath("StardewModdingAPI.metadata.json"); // moved in 2.8 + yield return GetInstallPath("StardewModdingAPI.Toolkit.dll"); // moved in 2.8 + yield return GetInstallPath("StardewModdingAPI.Toolkit.pdb"); // moved in 2.8 + yield return GetInstallPath("StardewModdingAPI.Toolkit.xml"); // moved in 2.8 + yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.dll"); // moved in 2.8 + yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.pdb"); // moved in 2.8 + yield return GetInstallPath("StardewModdingAPI.Toolkit.CoreInterfaces.xml"); // moved in 2.8 + yield return GetInstallPath("StardewModdingAPI.xml"); // moved in 2.8 + yield return GetInstallPath("System.Numerics.dll"); // moved in 2.8 + yield return GetInstallPath("System.Runtime.Caching.dll"); // moved in 2.8 + yield return GetInstallPath("System.ValueTuple.dll"); // moved in 2.8 + yield return GetInstallPath("steam_appid.txt"); // moved in 2.8 + if (modsDir.Exists) { foreach (DirectoryInfo modDir in modsDir.EnumerateDirectories()) @@ -438,14 +437,13 @@ namespace StardewModdingApi.Installer { // copy SMAPI files to game dir this.PrintDebug("Adding SMAPI files..."); - foreach (FileInfo sourceFile in paths.PackageDir.EnumerateFiles().Where(this.ShouldCopyFile)) + foreach (FileSystemInfo sourceEntry in paths.PackageDir.EnumerateFileSystemInfos().Where(this.ShouldCopy)) { - if (sourceFile.Name == this.InstallerFileName) + if (sourceEntry.Name == this.InstallerFileName) continue; - string targetPath = Path.Combine(paths.GameDir.FullName, sourceFile.Name); - this.InteractivelyDelete(targetPath); - sourceFile.CopyTo(targetPath); + this.InteractivelyDelete(Path.Combine(paths.GameDir.FullName, sourceEntry.Name)); + this.RecursiveCopy(sourceEntry, paths.GameDir); } // replace mod launcher (if possible) @@ -508,7 +506,7 @@ namespace StardewModdingApi.Installer targetDir.Create(); // copy files - foreach (FileInfo sourceFile in sourceDir.EnumerateFiles().Where(this.ShouldCopyFile)) + foreach (FileInfo sourceFile in sourceDir.EnumerateFiles().Where(this.ShouldCopy)) sourceFile.CopyTo(Path.Combine(targetDir.FullName, sourceFile.Name)); } @@ -690,6 +688,31 @@ namespace StardewModdingApi.Installer } } + /// Recursively copy a directory or file. + /// The file or folder to copy. + /// The folder to copy into. + private void RecursiveCopy(FileSystemInfo source, DirectoryInfo targetFolder) + { + if (!targetFolder.Exists) + targetFolder.Create(); + + switch (source) + { + case FileInfo sourceFile: + sourceFile.CopyTo(Path.Combine(targetFolder.FullName, sourceFile.Name)); + break; + + case DirectoryInfo sourceDir: + DirectoryInfo targetSubfolder = new DirectoryInfo(Path.Combine(targetFolder.FullName, sourceDir.Name)); + foreach (var entry in sourceDir.EnumerateFileSystemInfos()) + this.RecursiveCopy(entry, targetSubfolder); + break; + + default: + throw new NotSupportedException($"Unknown filesystem info type '{source.GetType().FullName}'."); + } + } + /// Delete a file or folder regardless of file permissions, and block until deletion completes. /// The file or folder to reset. /// This method is mirred from FileUtilities.ForceDelete in the toolkit. @@ -871,7 +894,7 @@ namespace StardewModdingApi.Installer this.PrintDebug(" Support for mods here was dropped in SMAPI 1.0 (it was never officially supported)."); // move mods if no conflicts (else warn) - foreach (FileSystemInfo entry in modDir.EnumerateFileSystemInfos().Where(this.ShouldCopyFile)) + foreach (FileSystemInfo entry in modDir.EnumerateFileSystemInfos().Where(this.ShouldCopy)) { // get type bool isDir = entry is DirectoryInfo; @@ -928,22 +951,26 @@ namespace StardewModdingApi.Installer Directory.CreateDirectory(newPath); DirectoryInfo directory = (DirectoryInfo)entry; - foreach (FileSystemInfo child in directory.EnumerateFileSystemInfos().Where(this.ShouldCopyFile)) + foreach (FileSystemInfo child in directory.EnumerateFileSystemInfos().Where(this.ShouldCopy)) this.Move(child, Path.Combine(newPath, child.Name)); directory.Delete(recursive: true); } } - /// Get whether a file should be copied when moving a folder. - /// The file info. - private bool ShouldCopyFile(FileSystemInfo file) + /// Get whether a file or folder should be copied from the installer files. + /// The file or folder info. + private bool ShouldCopy(FileSystemInfo entry) { - // ignore Mac symlink - if (file is FileInfo && file.Name == "mcs") - return false; - - return true; + switch (entry.Name) + { + case "mcs": + return false; // ignore Mac symlink + case "Mods": + return false; // Mods folder handled separately + default: + return true; + } } } } -- cgit From 307bf6ce55e8880f0e0382cb678d7fcc6c74c11e Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 19 Aug 2018 21:08:58 -0400 Subject: adjust SaveBackup mod to simplify installer logic (#583) --- src/SMAPI.Installer/InteractiveInstaller.cs | 30 ++--------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index f9e1ff94..a92edadf 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -22,12 +22,6 @@ namespace StardewModdingApi.Installer /// The name of the installer file in the package. private readonly string InstallerFileName = "install.exe"; - /// Mod files which shouldn't be deleted when deploying bundled mods (mod folder name => file names). - private readonly IDictionary> ProtectBundledFiles = new Dictionary>(StringComparer.InvariantCultureIgnoreCase) - { - ["SaveBackup"] = new HashSet(new[] { "backups", "config.json" }, StringComparer.InvariantCultureIgnoreCase) - }; - /// The value that represents Windows 7. private readonly Version Windows7Version = new Version(6, 1); @@ -474,18 +468,6 @@ namespace StardewModdingApi.Installer { this.PrintDebug("Adding bundled mods..."); - // special case: rename Omegasis' SaveBackup mod - { - 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)) - { - this.PrintDebug($" moving {oldFolder.Name} to {newFolder.Name}..."); - this.Move(oldFolder, newFolder.FullName); - } - } - // add bundled mods foreach (DirectoryInfo sourceDir in packagedModsDir.EnumerateDirectories()) { @@ -494,16 +476,8 @@ namespace StardewModdingApi.Installer // 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(); + this.InteractivelyDelete(targetDir.FullName); + targetDir.Create(); // copy files foreach (FileInfo sourceFile in sourceDir.EnumerateFiles().Where(this.ShouldCopy)) -- cgit From 9f64dd2abb182b588cf5ae11201ca4dfbe26c45f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 19 Aug 2018 21:50:42 -0400 Subject: add installer logic to detect if player moved the bundled mods (#583) --- src/SMAPI.Installer/InteractiveInstaller.cs | 57 ++++++++++++++-------- src/SMAPI.Installer/Program.cs | 47 +++++++++++++++++- .../StardewModdingAPI.Installer.csproj | 6 +++ 3 files changed, 89 insertions(+), 21 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index a92edadf..565ad732 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -10,6 +10,9 @@ using StardewModdingApi.Installer.Enums; using StardewModdingAPI.Installer.Framework; using StardewModdingAPI.Internal; using StardewModdingAPI.Internal.ConsoleWriting; +using StardewModdingAPI.Toolkit; +using StardewModdingAPI.Toolkit.Framework.ModScanning; +using StardewModdingAPI.Toolkit.Utilities; namespace StardewModdingApi.Installer { @@ -468,31 +471,45 @@ namespace StardewModdingApi.Installer { this.PrintDebug("Adding bundled mods..."); - // add bundled mods - foreach (DirectoryInfo sourceDir in packagedModsDir.EnumerateDirectories()) + ModToolkit toolkit = new ModToolkit(); + ModFolder[] targetMods = toolkit.GetModFolders(paths.ModsPath).ToArray(); + foreach (ModFolder sourceMod in toolkit.GetModFolders(packagedModsDir.FullName)) { - this.PrintDebug($" adding {sourceDir.Name}..."); - - // init/clear target dir - DirectoryInfo targetDir = new DirectoryInfo(Path.Combine(paths.ModsDir.FullName, sourceDir.Name)); - if (targetDir.Exists) - this.InteractivelyDelete(targetDir.FullName); - targetDir.Create(); + // validate source mod + if (sourceMod.Manifest == null) + { + this.PrintWarning($" ignored invalid bundled mod {sourceMod.DisplayName}: {sourceMod.ManifestParseError}"); + continue; + } + + // find target folder + ModFolder targetMod = targetMods.FirstOrDefault(p => p.Manifest?.UniqueID?.Equals(sourceMod.Manifest.UniqueID, StringComparison.InvariantCultureIgnoreCase) == true); + DirectoryInfo defaultTargetFolder = new DirectoryInfo(Path.Combine(paths.ModsPath, sourceMod.Directory.Name)); + DirectoryInfo targetFolder = targetMod?.Directory ?? defaultTargetFolder; + this.PrintDebug(targetFolder.FullName == defaultTargetFolder.FullName + ? $" adding {sourceMod.Manifest.Name}..." + : $" adding {sourceMod.Manifest.Name} to {Path.Combine(paths.ModsDir.Name, PathUtilities.GetRelativePath(paths.ModsPath, targetFolder.FullName))}..." + ); + + // (re)create target folder + if (targetFolder.Exists) + this.InteractivelyDelete(targetFolder.FullName); + targetFolder.Create(); // copy files - foreach (FileInfo sourceFile in sourceDir.EnumerateFiles().Where(this.ShouldCopy)) - sourceFile.CopyTo(Path.Combine(targetDir.FullName, sourceFile.Name)); + foreach (FileInfo sourceFile in sourceMod.Directory.EnumerateFiles().Where(this.ShouldCopy)) + sourceFile.CopyTo(Path.Combine(targetFolder.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); - } + // 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 diff --git a/src/SMAPI.Installer/Program.cs b/src/SMAPI.Installer/Program.cs index 8f328ecf..4d259fd3 100644 --- a/src/SMAPI.Installer/Program.cs +++ b/src/SMAPI.Installer/Program.cs @@ -1,8 +1,22 @@ -namespace StardewModdingApi.Installer +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Reflection; +using StardewModdingAPI.Internal; + +namespace StardewModdingApi.Installer { /// The entry point for SMAPI's install and uninstall console app. internal class Program { + /********* + ** Properties + *********/ + /// The absolute path to search for referenced assemblies. + [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute", Justification = "The assembly location is never null in this context.")] + private static string DllSearchPath; + + /********* ** Public methods *********/ @@ -10,8 +24,39 @@ /// The command line arguments. public static void Main(string[] args) { + // set up assembly resolution + string installerPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + Program.DllSearchPath = Path.Combine(installerPath, "internal", EnvironmentUtility.DetectPlatform() == Platform.Windows ? "Windows" : "Mono", "smapi-internal"); + AppDomain.CurrentDomain.AssemblyResolve += Program.CurrentDomain_AssemblyResolve; + + // launch installer var installer = new InteractiveInstaller(); installer.Run(args); } + + /********* + ** Private methods + *********/ + /// Method called when assembly resolution fails, which may return a manually resolved assembly. + /// The event sender. + /// The event arguments. + private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs e) + { + AssemblyName name = new AssemblyName(e.Name); + foreach (FileInfo dll in new DirectoryInfo(Program.DllSearchPath).EnumerateFiles("*.dll")) + { + try + { + if (name.Name.Equals(AssemblyName.GetAssemblyName(dll.FullName).Name, StringComparison.InvariantCultureIgnoreCase)) + return Assembly.LoadFrom(dll.FullName); + } + catch (Exception ex) + { + throw new InvalidOperationException($"Could not load dependency 'smapi-lib/{dll.Name}'. Consider deleting and redownloading the SMAPI installer.", ex); + } + } + + return null; + } } } diff --git a/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj b/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj index e82c6093..e9af16c5 100644 --- a/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj +++ b/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj @@ -58,6 +58,12 @@ PreserveNewest + + + {ea5cfd2e-9453-4d29-b80f-8e0ea23f4ac6} + StardewModdingAPI.Toolkit + + -- cgit From 464d6b2275f52b9db5560e242c6073fbd816bcb3 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 19 Aug 2018 23:41:03 -0400 Subject: fix error handling when resolving assemblies (#582) --- src/SMAPI.Installer/Program.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/Program.cs b/src/SMAPI.Installer/Program.cs index 4d259fd3..fe3e1798 100644 --- a/src/SMAPI.Installer/Program.cs +++ b/src/SMAPI.Installer/Program.cs @@ -42,21 +42,21 @@ namespace StardewModdingApi.Installer /// The event arguments. private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs e) { - AssemblyName name = new AssemblyName(e.Name); - foreach (FileInfo dll in new DirectoryInfo(Program.DllSearchPath).EnumerateFiles("*.dll")) + try { - try + AssemblyName name = new AssemblyName(e.Name); + foreach (FileInfo dll in new DirectoryInfo(Program.DllSearchPath).EnumerateFiles("*.dll")) { if (name.Name.Equals(AssemblyName.GetAssemblyName(dll.FullName).Name, StringComparison.InvariantCultureIgnoreCase)) return Assembly.LoadFrom(dll.FullName); } - catch (Exception ex) - { - throw new InvalidOperationException($"Could not load dependency 'smapi-lib/{dll.Name}'. Consider deleting and redownloading the SMAPI installer.", ex); - } + return null; + } + catch (Exception ex) + { + Console.WriteLine($"Error resolving assembly: {ex}"); + return null; } - - return null; } } } -- cgit From 498a950be80a28a537c71d4b4e094bc554fcbeb3 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 19 Aug 2018 23:48:49 -0400 Subject: fix installer's assembly resolution on Linux/Mac (#582) --- src/SMAPI.Installer/Program.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/Program.cs b/src/SMAPI.Installer/Program.cs index fe3e1798..375678d2 100644 --- a/src/SMAPI.Installer/Program.cs +++ b/src/SMAPI.Installer/Program.cs @@ -26,7 +26,9 @@ namespace StardewModdingApi.Installer { // set up assembly resolution string installerPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - Program.DllSearchPath = Path.Combine(installerPath, "internal", EnvironmentUtility.DetectPlatform() == Platform.Windows ? "Windows" : "Mono", "smapi-internal"); + Program.DllSearchPath = EnvironmentUtility.DetectPlatform() == Platform.Windows + ? Path.Combine(installerPath, "internal", "Windows", "smapi-internal") + : Path.Combine(installerPath, "smapi-internal"); AppDomain.CurrentDomain.AssemblyResolve += Program.CurrentDomain_AssemblyResolve; // launch installer -- cgit From 49870671cfbeb5c0bb12ca159fc7f4f7474d2be9 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Mon, 20 Aug 2018 00:00:45 -0400 Subject: fix broken path in installer (#582) --- src/SMAPI.Installer/Framework/InstallerPaths.cs | 4 ++++ src/SMAPI.Installer/InteractiveInstaller.cs | 5 ++--- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/Framework/InstallerPaths.cs b/src/SMAPI.Installer/Framework/InstallerPaths.cs index d212876a..65e7699b 100644 --- a/src/SMAPI.Installer/Framework/InstallerPaths.cs +++ b/src/SMAPI.Installer/Framework/InstallerPaths.cs @@ -26,6 +26,9 @@ namespace StardewModdingAPI.Installer.Framework /// The full path to the directory into which to install mods. public string ModsPath => this.ModsDir.FullName; + /// The full path to SMAPI's internal configuration file. + public string ApiConfigPath { get; } + /// The full path to the installed SMAPI executable file. public string ExecutablePath { get; } @@ -56,6 +59,7 @@ namespace StardewModdingAPI.Installer.Framework this.UnixLauncherPath = Path.Combine(gameDir.FullName, "StardewValley"); this.UnixSmapiLauncherPath = Path.Combine(gameDir.FullName, "StardewModdingAPI"); this.UnixBackupLauncherPath = Path.Combine(gameDir.FullName, "StardewValley-original"); + this.ApiConfigPath = Path.Combine(gameDir.FullName, "smapi-internal", "StardewModdingAPI.config.json"); } } } diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index 565ad732..7f7acb0b 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -505,11 +505,10 @@ namespace StardewModdingApi.Installer // 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) + .ReadAllText(paths.ApiConfigPath) .Replace(@"""ColorScheme"": ""AutoDetect""", $@"""ColorScheme"": ""{scheme}"""); - File.WriteAllText(configPath, text); + File.WriteAllText(paths.ApiConfigPath, text); } // remove obsolete appdata mods -- cgit From fb3b7aefa79ed9edeee85cf64004e928d203de81 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 25 Aug 2018 21:44:10 -0400 Subject: add manual install notes for Linux/Mac (#587) --- src/SMAPI.Installer/readme.txt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/readme.txt b/src/SMAPI.Installer/readme.txt index 2ee5473c..88fe4a03 100644 --- a/src/SMAPI.Installer/readme.txt +++ b/src/SMAPI.Installer/readme.txt @@ -36,3 +36,10 @@ If you really want to install SMAPI manually, here's how. - Linux/Mac only: rename the "StardewValley" file (no extension) to "StardewValley-original", and "StardewModdingAPI" (no extension) to "StardewValley". Now just launch the game as usual to play with mods. + +When installing on Linux or Mac: +- Make sure Mono is installed (normally the installer checks for you). While it's not required, + many mods won't work correctly without it. (Specifically, mods which load PNG images may crash or + freeze the game.) +- To configure the color scheme, edit the `smapi-internal/StardewModdingAPI.config.json` file and + see instructions there for the 'ColorScheme' setting. -- cgit From b5adfd8bce12afb885d6bb6a347d25e33be602af Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 26 Aug 2018 20:42:31 -0400 Subject: add more default game install paths --- src/SMAPI.Installer/InteractiveInstaller.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index 7f7acb0b..e6e71cf4 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -55,8 +55,12 @@ namespace StardewModdingApi.Installer 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"; + foreach (string programFiles in new[] { @"C:\Program Files", @"C:\Program Files (x86)" }) + { + yield return $@"{programFiles}\GalaxyClient\Games\Stardew Valley"; + yield return $@"{programFiles}\GOG Galaxy\Games\Stardew Valley"; + yield return $@"{programFiles}\Steam\steamapps\common\Stardew Valley"; + } // Windows registry IDictionary registryKeys = new Dictionary -- cgit From 4af0786ecb6b16826b2a23b1448c3ab8f5ccd569 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 30 Aug 2018 18:14:40 -0400 Subject: fix assembly load security exceptions by restructuring installer and adding *.exe.config files (#582, #588) --- src/SMAPI.Installer/InteractiveInstaller.cs | 2 +- src/SMAPI.Installer/Program.cs | 8 +------- src/SMAPI.Installer/StardewModdingAPI.Installer.csproj | 8 +++++++- src/SMAPI.Installer/windows-exe-config.xml | 5 +++++ src/SMAPI.Installer/windows-install.bat | 1 + 5 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 src/SMAPI.Installer/windows-exe-config.xml create mode 100644 src/SMAPI.Installer/windows-install.bat (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index e6e71cf4..1da5c35a 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -440,7 +440,7 @@ namespace StardewModdingApi.Installer this.PrintDebug("Adding SMAPI files..."); foreach (FileSystemInfo sourceEntry in paths.PackageDir.EnumerateFileSystemInfos().Where(this.ShouldCopy)) { - if (sourceEntry.Name == this.InstallerFileName) + if (sourceEntry.Name.StartsWith(this.InstallerFileName)) // e.g. install.exe or install.exe.config continue; this.InteractivelyDelete(Path.Combine(paths.GameDir.FullName, sourceEntry.Name)); diff --git a/src/SMAPI.Installer/Program.cs b/src/SMAPI.Installer/Program.cs index 375678d2..ad5cf47f 100644 --- a/src/SMAPI.Installer/Program.cs +++ b/src/SMAPI.Installer/Program.cs @@ -2,7 +2,6 @@ using System; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; -using StardewModdingAPI.Internal; namespace StardewModdingApi.Installer { @@ -14,8 +13,7 @@ namespace StardewModdingApi.Installer *********/ /// The absolute path to search for referenced assemblies. [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute", Justification = "The assembly location is never null in this context.")] - private static string DllSearchPath; - + private static readonly string DllSearchPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "smapi-internal"); /********* ** Public methods @@ -25,10 +23,6 @@ namespace StardewModdingApi.Installer public static void Main(string[] args) { // set up assembly resolution - string installerPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - Program.DllSearchPath = EnvironmentUtility.DetectPlatform() == Platform.Windows - ? Path.Combine(installerPath, "internal", "Windows", "smapi-internal") - : Path.Combine(installerPath, "smapi-internal"); AppDomain.CurrentDomain.AssemblyResolve += Program.CurrentDomain_AssemblyResolve; // launch installer diff --git a/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj b/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj index e9af16c5..22c55af7 100644 --- a/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj +++ b/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj @@ -46,11 +46,17 @@ - + Always + + PreserveNewest + + + PreserveNewest + PreserveNewest diff --git a/src/SMAPI.Installer/windows-exe-config.xml b/src/SMAPI.Installer/windows-exe-config.xml new file mode 100644 index 00000000..386c7f1a --- /dev/null +++ b/src/SMAPI.Installer/windows-exe-config.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/SMAPI.Installer/windows-install.bat b/src/SMAPI.Installer/windows-install.bat new file mode 100644 index 00000000..716c7789 --- /dev/null +++ b/src/SMAPI.Installer/windows-install.bat @@ -0,0 +1 @@ +START /WAIT /B internal/Windows/install.exe -- cgit From e4a5d8d46a4417de8c966b8d4a338fb0c39bbaeb Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 31 Aug 2018 17:44:37 -0400 Subject: fix incorrect path in Windows installer (#582, #588) --- src/SMAPI.Installer/InteractiveInstaller.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index 1da5c35a..090d12b9 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -319,9 +319,7 @@ namespace StardewModdingApi.Installer } // 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 packageDir = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); paths = new InstallerPaths(packageDir, installDir, EnvironmentUtility.GetExecutableName(platform)); } Console.Clear(); -- cgit From 48e34dd6035af4e5c1f69932b0baf436d1620429 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 31 Aug 2018 17:54:20 -0400 Subject: fix readme filename capitalisation --- src/SMAPI.Installer/README.txt | 45 ++++++++++++++++++++++++++++++++++++++++++ src/SMAPI.Installer/readme.txt | 45 ------------------------------------------ 2 files changed, 45 insertions(+), 45 deletions(-) create mode 100644 src/SMAPI.Installer/README.txt delete mode 100644 src/SMAPI.Installer/readme.txt (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/README.txt b/src/SMAPI.Installer/README.txt new file mode 100644 index 00000000..88fe4a03 --- /dev/null +++ b/src/SMAPI.Installer/README.txt @@ -0,0 +1,45 @@ + ___ ___ ___ ___ ___ + / /\ /__/\ / /\ / /\ / /\ + / /:/_ | |::\ / /::\ / /::\ / /:/ + / /:/ /\ | |:|:\ / /:/\:\ / /:/\:\ / /:/ + / /:/ /::\ __|__|:|\:\ / /:/~/::\ / /:/~/:/ / /::\ ___ +/__/:/ /:/\:\ /__/::::| \:\ /__/:/ /:/\:\ /__/:/ /:/ /__/:/\:\ /\ +\ \:\/:/~/:/ \ \:\~~\__\/ \ \:\/:/__\/ \ \:\/:/ \__\/ \:\/:/ + \ \::/ /:/ \ \:\ \ \::/ \ \::/ \__\::/ + \__\/ /:/ \ \:\ \ \:\ \ \:\ / /:/ + /__/:/ \ \:\ \ \:\ \ \:\ /__/:/ + \__\/ \__\/ \__\/ \__\/ \__\/ + + +SMAPI lets you run Stardew Valley with mods. Don't forget to download mods separately. + + +Player's guide +-------------------------------- +See https://stardewvalleywiki.com/Modding:Player_Guide + + +Manual install +-------------------------------- +THIS IS NOT RECOMMENDED FOR MOST PLAYERS. See instructions above instead. +If you really want to install SMAPI manually, here's how. + +1. Download the latest version of SMAPI: https://github.com/Pathoschild/SMAPI/releases +2. Unzip the .zip file somewhere (not in your game folder). +3. Copy the files from the "internal/Windows" folder (on Windows) or "internal/Mono" folder (on + Linux/Mac) into your game folder. The `StardewModdingAPI.exe` file should be right next to the + game's executable. +4. + - Windows only: if you use Steam, see the install guide above to enable achievements and + overlay. Otherwise, just run StardewModdingAPI.exe in your game folder to play with mods. + + - Linux/Mac only: rename the "StardewValley" file (no extension) to "StardewValley-original", and + "StardewModdingAPI" (no extension) to "StardewValley". Now just launch the game as usual to + play with mods. + +When installing on Linux or Mac: +- Make sure Mono is installed (normally the installer checks for you). While it's not required, + many mods won't work correctly without it. (Specifically, mods which load PNG images may crash or + freeze the game.) +- To configure the color scheme, edit the `smapi-internal/StardewModdingAPI.config.json` file and + see instructions there for the 'ColorScheme' setting. diff --git a/src/SMAPI.Installer/readme.txt b/src/SMAPI.Installer/readme.txt deleted file mode 100644 index 88fe4a03..00000000 --- a/src/SMAPI.Installer/readme.txt +++ /dev/null @@ -1,45 +0,0 @@ - ___ ___ ___ ___ ___ - / /\ /__/\ / /\ / /\ / /\ - / /:/_ | |::\ / /::\ / /::\ / /:/ - / /:/ /\ | |:|:\ / /:/\:\ / /:/\:\ / /:/ - / /:/ /::\ __|__|:|\:\ / /:/~/::\ / /:/~/:/ / /::\ ___ -/__/:/ /:/\:\ /__/::::| \:\ /__/:/ /:/\:\ /__/:/ /:/ /__/:/\:\ /\ -\ \:\/:/~/:/ \ \:\~~\__\/ \ \:\/:/__\/ \ \:\/:/ \__\/ \:\/:/ - \ \::/ /:/ \ \:\ \ \::/ \ \::/ \__\::/ - \__\/ /:/ \ \:\ \ \:\ \ \:\ / /:/ - /__/:/ \ \:\ \ \:\ \ \:\ /__/:/ - \__\/ \__\/ \__\/ \__\/ \__\/ - - -SMAPI lets you run Stardew Valley with mods. Don't forget to download mods separately. - - -Player's guide --------------------------------- -See https://stardewvalleywiki.com/Modding:Player_Guide - - -Manual install --------------------------------- -THIS IS NOT RECOMMENDED FOR MOST PLAYERS. See instructions above instead. -If you really want to install SMAPI manually, here's how. - -1. Download the latest version of SMAPI: https://github.com/Pathoschild/SMAPI/releases -2. Unzip the .zip file somewhere (not in your game folder). -3. Copy the files from the "internal/Windows" folder (on Windows) or "internal/Mono" folder (on - Linux/Mac) into your game folder. The `StardewModdingAPI.exe` file should be right next to the - game's executable. -4. - - Windows only: if you use Steam, see the install guide above to enable achievements and - overlay. Otherwise, just run StardewModdingAPI.exe in your game folder to play with mods. - - - Linux/Mac only: rename the "StardewValley" file (no extension) to "StardewValley-original", and - "StardewModdingAPI" (no extension) to "StardewValley". Now just launch the game as usual to - play with mods. - -When installing on Linux or Mac: -- Make sure Mono is installed (normally the installer checks for you). While it's not required, - many mods won't work correctly without it. (Specifically, mods which load PNG images may crash or - freeze the game.) -- To configure the color scheme, edit the `smapi-internal/StardewModdingAPI.config.json` file and - see instructions there for the 'ColorScheme' setting. -- cgit From 75ed49972d32b889a9b140d7c71e2dc83f9c0c34 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 2 Sep 2018 23:31:20 -0400 Subject: add new file to uninstaller (#582, #588) --- src/SMAPI.Installer/InteractiveInstaller.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index 090d12b9..7e3bdbbf 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -98,6 +98,7 @@ namespace StardewModdingApi.Installer yield return GetInstallPath("libgdiplus.dylib"); // Linux/Mac only yield return GetInstallPath("StardewModdingAPI"); // Linux/Mac only yield return GetInstallPath("StardewModdingAPI.exe"); + yield return GetInstallPath("StardewModdingAPI.exe.config"); yield return GetInstallPath("StardewModdingAPI.exe.mdb"); // Linux/Mac only yield return GetInstallPath("StardewModdingAPI.pdb"); // Windows only yield return GetInstallPath("StardewModdingAPI.xml"); -- cgit From 43a3af1a671c46b48b4c4eb5ab1552d1177cb9fb Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 18 Sep 2018 17:49:36 -0400 Subject: prefer xterm when launching SMAPI --- src/SMAPI.Installer/unix-launcher.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/unix-launcher.sh b/src/SMAPI.Installer/unix-launcher.sh index 1e969c20..b64c021c 100644 --- a/src/SMAPI.Installer/unix-launcher.sh +++ b/src/SMAPI.Installer/unix-launcher.sh @@ -62,7 +62,9 @@ else fi # open SMAPI in terminal - if $COMMAND x-terminal-emulator 2>/dev/null; then + if $COMMAND xterm 2>/dev/null; then + xterm -e "$LAUNCHER" + elif $COMMAND x-terminal-emulator 2>/dev/null; then # Terminator converts -e to -x when used through x-terminal-emulator for some reason (per # `man terminator`), which causes an "unable to find shell" error. If x-terminal-emulator # is mapped to Terminator, invoke it directly instead. @@ -71,8 +73,6 @@ else else x-terminal-emulator -e "$LAUNCHER" fi - elif $COMMAND xterm 2>/dev/null; then - xterm -e "$LAUNCHER" elif $COMMAND xfce4-terminal 2>/dev/null; then xfce4-terminal -e "env TERM=xterm; $LAUNCHER" elif $COMMAND gnome-terminal 2>/dev/null; then -- cgit From 980bc873e76854ec5f0ee4b554f3f5e206358648 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Mon, 8 Oct 2018 20:52:30 -0400 Subject: move marker files into smapi-internal (#582) --- src/SMAPI.Installer/InteractiveInstaller.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index 7e3bdbbf..85882283 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -115,7 +115,9 @@ namespace StardewModdingApi.Installer yield return GetInstallPath("Mono.Cecil.dll"); // moved in 2.8 yield return GetInstallPath("Newtonsoft.Json.dll"); // moved in 2.8 yield return GetInstallPath("StardewModdingAPI.config.json"); // moved in 2.8 + yield return GetInstallPath("StardewModdingAPI.crash.marker"); // moved in 2.8 yield return GetInstallPath("StardewModdingAPI.metadata.json"); // moved in 2.8 + yield return GetInstallPath("StardewModdingAPI.update.marker"); // moved in 2.8 yield return GetInstallPath("StardewModdingAPI.Toolkit.dll"); // moved in 2.8 yield return GetInstallPath("StardewModdingAPI.Toolkit.pdb"); // moved in 2.8 yield return GetInstallPath("StardewModdingAPI.Toolkit.xml"); // moved in 2.8 -- cgit From 49e944d06fa7040889b569b62cb0025c057834df Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 4 Nov 2018 23:52:59 -0500 Subject: update HTTP URLs to HTTPS --- src/SMAPI.Installer/unix-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/unix-install.sh b/src/SMAPI.Installer/unix-install.sh index df02bb37..8379ed87 100644 --- a/src/SMAPI.Installer/unix-install.sh +++ b/src/SMAPI.Installer/unix-install.sh @@ -16,6 +16,6 @@ fi if $COMMAND mono >/dev/null 2>&1; then mono internal/Mono/install.exe else - echo "Oops! Looks like Mono isn't installed. Please install Mono from http://mono-project.com, reboot, and run this installer again." + echo "Oops! Looks like Mono isn't installed. Please install Mono from https://mono-project.com, reboot, and run this installer again." read fi -- cgit From 8cfada7e8bf912114c411e88fba55bbc1d06198b Mon Sep 17 00:00:00 2001 From: lqdev Date: Fri, 9 Nov 2018 18:17:13 +0100 Subject: Made the unix launcher compatible with any shell --- src/SMAPI.Installer/unix-launcher.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/unix-launcher.sh b/src/SMAPI.Installer/unix-launcher.sh index b64c021c..bf2cbb9c 100644 --- a/src/SMAPI.Installer/unix-launcher.sh +++ b/src/SMAPI.Installer/unix-launcher.sh @@ -71,12 +71,12 @@ else if [[ "$(readlink -e $(which x-terminal-emulator))" == *"/terminator" ]]; then terminator -e "$LAUNCHER" else - x-terminal-emulator -e "$LAUNCHER" + x-terminal-emulator -e "sh -c 'TERM=xterm $LAUNCHER'" fi elif $COMMAND xfce4-terminal 2>/dev/null; then - xfce4-terminal -e "env TERM=xterm; $LAUNCHER" + xfce4-terminal -e "sh -c 'TERM=xterm $LAUNCHER'" elif $COMMAND gnome-terminal 2>/dev/null; then - gnome-terminal -e "env TERM=xterm; $LAUNCHER" + gnome-terminal -e "sh -c 'TERM=xterm $LAUNCHER'" elif $COMMAND konsole 2>/dev/null; then konsole -p Environment=TERM=xterm -e "$LAUNCHER" elif $COMMAND terminal 2>/dev/null; then -- cgit From 76f1a37c166327d41646d797191101c8446376d8 Mon Sep 17 00:00:00 2001 From: lqdev Date: Fri, 9 Nov 2018 22:27:20 +0100 Subject: Added compatibility with even more terminals --- src/SMAPI.Installer/unix-launcher.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/unix-launcher.sh b/src/SMAPI.Installer/unix-launcher.sh index bf2cbb9c..3c332472 100644 --- a/src/SMAPI.Installer/unix-launcher.sh +++ b/src/SMAPI.Installer/unix-launcher.sh @@ -69,7 +69,7 @@ else # `man terminator`), which causes an "unable to find shell" error. If x-terminal-emulator # is mapped to Terminator, invoke it directly instead. if [[ "$(readlink -e $(which x-terminal-emulator))" == *"/terminator" ]]; then - terminator -e "$LAUNCHER" + terminator -e "sh -c 'TERM=xterm $LAUNCHER'" else x-terminal-emulator -e "sh -c 'TERM=xterm $LAUNCHER'" fi @@ -80,9 +80,9 @@ else elif $COMMAND konsole 2>/dev/null; then konsole -p Environment=TERM=xterm -e "$LAUNCHER" elif $COMMAND terminal 2>/dev/null; then - terminal -e "$LAUNCHER" + terminal -e "sh -c 'TERM=xterm $LAUNCHER'" else - $LAUNCHER + sh -c 'TERM=xterm $LAUNCHER' fi # some Linux users get error 127 (command not found) from the above block, even though -- cgit From 41e3c2802174562f356116eda81c8ddfff1edaeb Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 18 Nov 2018 00:44:56 -0500 Subject: fix installer allowing custom mods to be bundled with the install (#602) This led to confusion since the installer didn't copy mod subfolders correctly. The installer now explains where to add custom mods instead. --- src/SMAPI.Installer/InteractiveInstaller.cs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index 85882283..cef0d26c 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -28,6 +28,13 @@ namespace StardewModdingApi.Installer /// The value that represents Windows 7. private readonly Version Windows7Version = new Version(6, 1); + /// The mod IDs which the installer should allow as bundled mods. + private readonly string[] BundledModIDs = new[] + { + "SMAPI.SaveBackup", + "SMAPI.ConsoleCommands" + }; + /// 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. @@ -486,6 +493,11 @@ namespace StardewModdingApi.Installer this.PrintWarning($" ignored invalid bundled mod {sourceMod.DisplayName}: {sourceMod.ManifestParseError}"); continue; } + if (!this.BundledModIDs.Contains(sourceMod.Manifest.UniqueID)) + { + this.PrintWarning($" ignored unknown '{sourceMod.DisplayName}' mod in the installer folder. To add mods, put them here instead: {paths.ModsPath}"); + continue; + } // find target folder ModFolder targetMod = targetMods.FirstOrDefault(p => p.Manifest?.UniqueID?.Equals(sourceMod.Manifest.UniqueID, StringComparison.InvariantCultureIgnoreCase) == true); @@ -496,14 +508,12 @@ namespace StardewModdingApi.Installer : $" adding {sourceMod.Manifest.Name} to {Path.Combine(paths.ModsDir.Name, PathUtilities.GetRelativePath(paths.ModsPath, targetFolder.FullName))}..." ); - // (re)create target folder + // remove existing folder if (targetFolder.Exists) this.InteractivelyDelete(targetFolder.FullName); - targetFolder.Create(); // copy files - foreach (FileInfo sourceFile in sourceMod.Directory.EnumerateFiles().Where(this.ShouldCopy)) - sourceFile.CopyTo(Path.Combine(targetFolder.FullName, sourceFile.Name)); + this.RecursiveCopy(sourceMod.Directory, paths.ModsDir, filter: this.ShouldCopy); } } @@ -686,8 +696,12 @@ namespace StardewModdingApi.Installer /// Recursively copy a directory or file. /// The file or folder to copy. /// The folder to copy into. - private void RecursiveCopy(FileSystemInfo source, DirectoryInfo targetFolder) + /// A filter which matches directories and files to copy, or null to match all. + private void RecursiveCopy(FileSystemInfo source, DirectoryInfo targetFolder, Func filter = null) { + if (filter != null && !filter(source)) + return; + if (!targetFolder.Exists) targetFolder.Create(); @@ -700,7 +714,7 @@ namespace StardewModdingApi.Installer case DirectoryInfo sourceDir: DirectoryInfo targetSubfolder = new DirectoryInfo(Path.Combine(targetFolder.FullName, sourceDir.Name)); foreach (var entry in sourceDir.EnumerateFileSystemInfos()) - this.RecursiveCopy(entry, targetSubfolder); + this.RecursiveCopy(entry, targetSubfolder, filter); break; default: -- cgit From e5bc00e7a25a98338dd6b3795d6d229a662ab004 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 18 Nov 2018 00:47:35 -0500 Subject: hide installer's bundled files to avoid confusion (#602) --- src/SMAPI.Installer/Framework/InstallerPaths.cs | 14 +++---- src/SMAPI.Installer/InteractiveInstaller.cs | 46 ++++++++-------------- src/SMAPI.Installer/Program.cs | 32 +++++++++++++-- src/SMAPI.Installer/README.txt | 13 +++--- .../StardewModdingAPI.Installer.csproj | 2 + src/SMAPI.Installer/unix-install.sh | 2 +- src/SMAPI.Installer/windows-install.bat | 2 +- 7 files changed, 61 insertions(+), 50 deletions(-) (limited to 'src/SMAPI.Installer') diff --git a/src/SMAPI.Installer/Framework/InstallerPaths.cs b/src/SMAPI.Installer/Framework/InstallerPaths.cs index 65e7699b..e5396018 100644 --- a/src/SMAPI.Installer/Framework/InstallerPaths.cs +++ b/src/SMAPI.Installer/Framework/InstallerPaths.cs @@ -8,8 +8,8 @@ namespace StardewModdingAPI.Installer.Framework /********* ** Accessors *********/ - /// The directory containing the installer files for the current platform. - public DirectoryInfo PackageDir { get; } + /// The directory path containing the files to copy into the game folder. + public DirectoryInfo BundleDir { get; } /// The directory containing the installed game. public DirectoryInfo GameDir { get; } @@ -17,8 +17,8 @@ namespace StardewModdingAPI.Installer.Framework /// 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 directory path containing the files to copy into the game folder. + public string BundlePath => this.BundleDir.FullName; /// The full path to the directory containing the installed game. public string GamePath => this.GameDir.FullName; @@ -46,12 +46,12 @@ namespace StardewModdingAPI.Installer.Framework ** Public methods *********/ /// Construct an instance. - /// The directory path containing the installer files for the current platform. + /// The directory path containing the files to copy into the game folder. /// 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) + public InstallerPaths(DirectoryInfo bundleDir, DirectoryInfo gameDir, string gameExecutableName) { - this.PackageDir = packageDir; + this.BundleDir = bundleDir; this.GameDir = gameDir; this.ModsDir = new DirectoryInfo(Path.Combine(gameDir.FullName, "Mods")); diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index cef0d26c..4212418d 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using System.Reflection; using System.Threading; using Microsoft.Win32; using StardewModdingApi.Installer.Enums; @@ -22,8 +21,8 @@ namespace StardewModdingApi.Installer /********* ** Properties *********/ - /// The name of the installer file in the package. - private readonly string InstallerFileName = "install.exe"; + /// The absolute path to the directory containing the files to copy into the game folder. + private readonly string BundlePath; /// The value that represents Windows 7. private readonly Version Windows7Version = new Version(6, 1); @@ -153,8 +152,10 @@ namespace StardewModdingApi.Installer ** Public methods *********/ /// Construct an instance. - public InteractiveInstaller() + /// The absolute path to the directory containing the files to copy into the game folder. + public InteractiveInstaller(string bundlePath) { + this.BundlePath = bundlePath; this.ConsoleWriter = new ColorfulConsoleWriter(EnvironmentUtility.DetectPlatform(), MonitorColorScheme.AutoDetect); } @@ -329,8 +330,8 @@ namespace StardewModdingApi.Installer } // get folders - DirectoryInfo packageDir = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); - paths = new InstallerPaths(packageDir, installDir, EnvironmentUtility.GetExecutableName(platform)); + DirectoryInfo bundleDir = new DirectoryInfo(this.BundlePath); + paths = new InstallerPaths(bundleDir, installDir, EnvironmentUtility.GetExecutableName(platform)); } Console.Clear(); @@ -338,23 +339,11 @@ namespace StardewModdingApi.Installer /********* ** Step 4: validate assumptions *********/ + if (!File.Exists(paths.ExecutablePath)) { - if (!paths.PackageDir.Exists) - { - 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})." - ); - Console.ReadLine(); - return; - } - - if (!File.Exists(paths.ExecutablePath)) - { - this.PrintError("The detected game install path doesn't contain a Stardew Valley executable."); - Console.ReadLine(); - return; - } + this.PrintError("The detected game install path doesn't contain a Stardew Valley executable."); + Console.ReadLine(); + return; } @@ -446,11 +435,8 @@ namespace StardewModdingApi.Installer { // copy SMAPI files to game dir this.PrintDebug("Adding SMAPI files..."); - foreach (FileSystemInfo sourceEntry in paths.PackageDir.EnumerateFileSystemInfos().Where(this.ShouldCopy)) + foreach (FileSystemInfo sourceEntry in paths.BundleDir.EnumerateFileSystemInfos().Where(this.ShouldCopy)) { - if (sourceEntry.Name.StartsWith(this.InstallerFileName)) // e.g. install.exe or install.exe.config - continue; - this.InteractivelyDelete(Path.Combine(paths.GameDir.FullName, sourceEntry.Name)); this.RecursiveCopy(sourceEntry, paths.GameDir); } @@ -478,14 +464,14 @@ namespace StardewModdingApi.Installer } // add or replace bundled mods - DirectoryInfo packagedModsDir = new DirectoryInfo(Path.Combine(paths.PackageDir.FullName, "Mods")); - if (packagedModsDir.Exists && packagedModsDir.EnumerateDirectories().Any()) + DirectoryInfo bundledModsDir = new DirectoryInfo(Path.Combine(paths.BundlePath, "Mods")); + if (bundledMo