From cfe2c3975f8be62581195fbfffc41528f22b2ee3 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 17 Jan 2021 15:06:04 -0500 Subject: prefer GOG/Steam registry paths when scanning for game folder --- .../Framework/GameScanning/GameScanner.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/SMAPI.Toolkit') diff --git a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs index d4c82180..055e3b6d 100644 --- a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs +++ b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs @@ -90,14 +90,6 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning case Platform.Windows: { - // Windows - 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 #if SMAPI_FOR_WINDOWS IDictionary registryKeys = new Dictionary @@ -113,10 +105,18 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning } // via Steam library path - string steampath = this.GetCurrentUserRegistryValue(@"Software\Valve\Steam", "SteamPath"); - if (steampath != null) - yield return Path.Combine(steampath.Replace('/', '\\'), @"steamapps\common\Stardew Valley"); + string steamPath = this.GetCurrentUserRegistryValue(@"Software\Valve\Steam", "SteamPath"); + if (steamPath != null) + yield return Path.Combine(steamPath.Replace('/', '\\'), @"steamapps\common\Stardew Valley"); #endif + + // Windows + 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"; + } } break; -- cgit From bc71f994ece3943f02f91cdefbbe126cbef5a541 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 17 Jan 2021 15:11:45 -0500 Subject: improve game path detection --- src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/SMAPI.Toolkit') diff --git a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs index 055e3b6d..785daba3 100644 --- a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs +++ b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs @@ -110,11 +110,12 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning yield return Path.Combine(steamPath.Replace('/', '\\'), @"steamapps\common\Stardew Valley"); #endif - // Windows + // default paths 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}\GOG Games\Stardew Valley"; yield return $@"{programFiles}\Steam\steamapps\common\Stardew Valley"; } } -- cgit From ff16a6567b6137b1aafed3470406d5f5884a5bdc Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 19 Jan 2021 21:20:25 -0500 Subject: add multi-key binding API (#744) --- .../Serialization/Converters/SemanticVersionConverter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/SMAPI.Toolkit') diff --git a/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs b/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs index 3604956b..cf69104d 100644 --- a/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs +++ b/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs @@ -18,10 +18,10 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters ** Accessors *********/ /// Get whether this converter can read JSON. - public override bool CanRead => true; + public override bool CanRead { get; } = true; /// Get whether this converter can write JSON. - public override bool CanWrite => true; + public override bool CanWrite { get; } = true; /********* -- cgit From 342fc80394ac2d1bd67fb1b745b8ddec927fac49 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 20 Jan 2021 23:22:24 -0500 Subject: rewrite C# 9 code not supported in Linux build tools yet --- src/SMAPI.Toolkit/SemanticVersion.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/SMAPI.Toolkit') diff --git a/src/SMAPI.Toolkit/SemanticVersion.cs b/src/SMAPI.Toolkit/SemanticVersion.cs index d58dce0c..2f3e282b 100644 --- a/src/SMAPI.Toolkit/SemanticVersion.cs +++ b/src/SMAPI.Toolkit/SemanticVersion.cs @@ -293,12 +293,12 @@ namespace StardewModdingAPI.Toolkit return string.Compare(this.ToString(), new SemanticVersion(otherMajor, otherMinor, otherPatch, otherPlatformRelease, otherTag).ToString(), StringComparison.OrdinalIgnoreCase); } - return CompareToRaw() switch - { - (< 0) => curOlder, - (> 0) => curNewer, - _ => same - }; + int result = CompareToRaw(); + if (result < 0) + return curOlder; + if (result > 0) + return curNewer; + return same; } /// Assert that the current version is valid. -- cgit From 7fc7a45102f856e84de36fdc5acc0bcb4d99afbb Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 21 Jan 2021 19:01:57 -0500 Subject: fix some broken mods incorrectly listed as XNB mods --- .../Framework/ModScanning/ModScanner.cs | 37 +++++++++++++++------- 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'src/SMAPI.Toolkit') diff --git a/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs b/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs index 5eacee9e..b2f09431 100644 --- a/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs +++ b/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs @@ -58,16 +58,18 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning ".lnk" }; - /// The extensions for files which an XNB mod may contain. If a mod doesn't have a manifest.json and contains *only* these file extensions, it should be considered an XNB mod. - private readonly HashSet PotentialXnbModExtensions = new HashSet(StringComparer.OrdinalIgnoreCase) + /// The extensions for packed content files. + private readonly HashSet StrictXnbModExtensions = new HashSet(StringComparer.OrdinalIgnoreCase) { - // XNB files ".xgs", ".xnb", ".xsb", - ".xwb", + ".xwb" + }; - // unpacking artifacts + /// The extensions for files which an XNB mod may contain, in addition to . + private readonly HashSet PotentialXnbModExtensions = new HashSet(StringComparer.OrdinalIgnoreCase) + { ".json", ".yaml" }; @@ -118,7 +120,7 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning return new ModFolder(root, searchFolder, ModType.Invalid, null, ModParseError.EmptyFolder, "it's an empty folder."); // XNB mod - if (files.All(this.IsPotentialXnbFile)) + if (this.IsXnbMod(files)) return new ModFolder(root, searchFolder, ModType.Xnb, null, ModParseError.XnbMod, "it's not a SMAPI mod (see https://smapi.io/xnb for info)."); // SMAPI installer @@ -302,14 +304,25 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning return !this.IgnoreFilesystemNames.Any(p => p.IsMatch(entry.Name)); } - /// Get whether a file is potentially part of an XNB mod. - /// The file. - private bool IsPotentialXnbFile(FileInfo entry) + /// Get whether a set of files looks like an XNB mod. + /// The files in the mod. + private bool IsXnbMod(IEnumerable files) { - if (!this.IsRelevant(entry)) - return true; + bool hasXnbFile = false; + + foreach (FileInfo file in files.Where(this.IsRelevant)) + { + if (this.StrictXnbModExtensions.Contains(file.Extension)) + { + hasXnbFile = true; + continue; + } + + if (!this.PotentialXnbModExtensions.Contains(file.Extension)) + return false; + } - return this.PotentialXnbModExtensions.Contains(entry.Extension); // use EndsWith to handle cases like image..png + return hasXnbFile; } /// Strip newlines from a string. -- cgit From 546012da8c6ab5e29f34926cda47756d6d18c326 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 21 Jan 2021 19:04:34 -0500 Subject: add clearer error for empty Vortex folders to reduce confusion --- .../Framework/ModScanning/ModParseError.cs | 3 ++ .../Framework/ModScanning/ModScanner.cs | 49 ++++++++++++++++++---- 2 files changed, 44 insertions(+), 8 deletions(-) (limited to 'src/SMAPI.Toolkit') diff --git a/src/SMAPI.Toolkit/Framework/ModScanning/ModParseError.cs b/src/SMAPI.Toolkit/Framework/ModScanning/ModParseError.cs index b10510ff..f1e782b6 100644 --- a/src/SMAPI.Toolkit/Framework/ModScanning/ModParseError.cs +++ b/src/SMAPI.Toolkit/Framework/ModScanning/ModParseError.cs @@ -9,6 +9,9 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning /// The folder is empty or contains only ignored files. EmptyFolder, + /// The folder is an empty folder managed by Vortex. + EmptyVortexFolder, + /// The folder is ignored by convention. IgnoredFolder, diff --git a/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs b/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs index b2f09431..86a97016 100644 --- a/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs +++ b/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs @@ -74,6 +74,12 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning ".yaml" }; + /// The name of the marker file added by Vortex to indicate it's managing the folder. + private readonly string VortexMarkerFileName = "__folder_managed_by_vortex"; + + /// The name for a mod's configuration JSON file. + private readonly string ConfigFileName = "config.json"; + /********* ** Public methods @@ -113,18 +119,24 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning // set appropriate invalid-mod error if (manifestFile == null) { - FileInfo[] files = this.RecursivelyGetRelevantFiles(searchFolder).ToArray(); + FileInfo[] files = this.RecursivelyGetFiles(searchFolder).ToArray(); + FileInfo[] relevantFiles = files.Where(this.IsRelevant).ToArray(); + + // empty Vortex folder + // (this filters relevant files internally so it can check for the normally-ignored Vortex marker file) + if (this.IsEmptyVortexFolder(files)) + return new ModFolder(root, searchFolder, ModType.Invalid, null, ModParseError.EmptyVortexFolder, "it's an empty Vortex folder (is the mod disabled in Vortex?)."); // empty folder - if (!files.Any()) + if (!relevantFiles.Any()) return new ModFolder(root, searchFolder, ModType.Invalid, null, ModParseError.EmptyFolder, "it's an empty folder."); // XNB mod - if (this.IsXnbMod(files)) + if (this.IsXnbMod(relevantFiles)) return new ModFolder(root, searchFolder, ModType.Xnb, null, ModParseError.XnbMod, "it's not a SMAPI mod (see https://smapi.io/xnb for info)."); // SMAPI installer - if (files.Any(p => p.Name == "install on Linux.sh" || p.Name == "install on Mac.command" || p.Name == "install on Windows.bat")) + if (relevantFiles.Any(p => p.Name == "install on Linux.sh" || p.Name == "install on Mac.command" || p.Name == "install on Windows.bat")) return new ModFolder(root, searchFolder, ModType.Invalid, null, ModParseError.ManifestMissing, "the SMAPI installer isn't a mod (you can delete this folder after running the installer file)."); // not a mod? @@ -272,13 +284,13 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning return subfolders.Any() && !files.Any(); } - /// Recursively get all relevant files in a folder based on the result of . + /// Recursively get all files in a folder. /// The root folder to search. - private IEnumerable RecursivelyGetRelevantFiles(DirectoryInfo folder) + private IEnumerable RecursivelyGetFiles(DirectoryInfo folder) { foreach (FileSystemInfo entry in folder.GetFileSystemInfos()) { - if (!this.IsRelevant(entry)) + if (entry is DirectoryInfo && !this.IsRelevant(entry)) continue; if (entry is FileInfo file) @@ -286,7 +298,7 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning if (entry is DirectoryInfo subfolder) { - foreach (FileInfo subfolderFile in this.RecursivelyGetRelevantFiles(subfolder)) + foreach (FileInfo subfolderFile in this.RecursivelyGetFiles(subfolder)) yield return subfolderFile; } } @@ -325,6 +337,27 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning return hasXnbFile; } + /// Get whether a set of files looks like an XNB mod. + /// The files in the mod. + private bool IsEmptyVortexFolder(IEnumerable files) + { + bool hasVortexMarker = false; + + foreach (FileInfo file in files) + { + if (file.Name == this.VortexMarkerFileName) + { + hasVortexMarker = true; + continue; + } + + if (this.IsRelevant(file) && file.Name != this.ConfigFileName) + return false; + } + + return hasVortexMarker; + } + /// Strip newlines from a string. /// The input to strip. private string StripNewlines(string input) -- cgit