From 30cc7ac9161e4cea91c3b566a7edb5e438af98cb Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 1 May 2019 23:45:50 -0400 Subject: consolidate XNB mods when scanning mods --- docs/release-notes.md | 1 + .../Framework/ModScanning/ModScanner.cs | 27 ++++++++++++++++++---- src/SMAPI.Toolkit/ModToolkit.cs | 9 ++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index 05fccd74..68763598 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -7,6 +7,7 @@ These changes have not been released yet. * Improved performance. * Updated mod compatibility list. * Rewrote launch script on Linux to improve compatibility (thanks to kurumushi and toastal!). + * Improved handling for XNB mods unzipped into `Mods` (improved detection over generic invalid mods, and multi-folder XNB mods are now counted as one mod). * Fixed Save Backup not pruning old backups if they're uncompressed. * Fixed issues when a farmhand reconnects before the game notices they're disconnected. * Fixed 'received message' logs shown in non-developer mode. diff --git a/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs b/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs index 507e7be2..ae0f292f 100644 --- a/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs +++ b/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs @@ -52,6 +52,15 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning return this.GetModFolders(root, root); } + /// Extract information about all mods in the given folder. + /// The root folder containing mods. Only the will be searched, but this field allows it to be treated as a potential mod folder of its own. + /// The mod path to search. + // /// If the folder contains multiple XNB mods, treat them as subfolders of a single mod. This is useful when reading a single mod archive, as opposed to a mods folder. + public IEnumerable GetModFolders(string rootPath, string modPath) + { + return this.GetModFolders(root: new DirectoryInfo(rootPath), folder: new DirectoryInfo(modPath)); + } + /// Extract information from a mod folder. /// The root folder containing mods. /// The folder to search for a mod. @@ -120,17 +129,25 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning /// The folder to search for mods. public IEnumerable GetModFolders(DirectoryInfo root, DirectoryInfo folder) { + bool isRoot = folder.FullName == root.FullName; + // skip - if (folder.FullName != root.FullName && folder.Name.StartsWith(".")) + if (!isRoot && folder.Name.StartsWith(".")) yield return new ModFolder(root, folder, ModType.Invalid, null, "ignored folder because its name starts with a dot.", shouldBeLoaded: false); - // recurse into subfolders + // find mods in subfolders else if (this.IsModSearchFolder(root, folder)) { - foreach (DirectoryInfo subfolder in folder.EnumerateDirectories()) + ModFolder[] subfolders = folder.EnumerateDirectories().SelectMany(sub => this.GetModFolders(root, sub)).ToArray(); + if (!isRoot && subfolders.Length > 1 && subfolders.All(p => p.Type == ModType.Xnb)) + { + // if this isn't the root, and all subfolders are XNB mods, treat the whole folder as one XNB mod + yield return new ModFolder(folder, folder, ModType.Xnb, null, subfolders[0].ManifestParseError); + } + else { - foreach (ModFolder match in this.GetModFolders(root, subfolder)) - yield return match; + foreach (ModFolder subfolder in subfolders) + yield return subfolder; } } diff --git a/src/SMAPI.Toolkit/ModToolkit.cs b/src/SMAPI.Toolkit/ModToolkit.cs index 1b53e59e..f1da62a2 100644 --- a/src/SMAPI.Toolkit/ModToolkit.cs +++ b/src/SMAPI.Toolkit/ModToolkit.cs @@ -69,6 +69,15 @@ namespace StardewModdingAPI.Toolkit return new ModScanner(this.JsonHelper).GetModFolders(rootPath); } + /// Extract information about all mods in the given folder. + /// The root folder containing mods. Only the will be searched, but this field allows it to be treated as a potential mod folder of its own. + /// The mod path to search. + // /// If the folder contains multiple XNB mods, treat them as subfolders of a single mod. This is useful when reading a single mod archive, as opposed to a mods folder. + public IEnumerable GetModFolders(string rootPath, string modPath) + { + return new ModScanner(this.JsonHelper).GetModFolders(rootPath, modPath); + } + /// Get an update URL for an update key (if valid). /// The update key. public string GetUpdateUrl(string updateKey) -- cgit