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') 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