summaryrefslogtreecommitdiff
path: root/src/SMAPI.Toolkit
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2021-01-22 21:05:04 -0500
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2021-01-22 21:05:04 -0500
commitd0dc3ea6f6d03e6aabdab5f5f10a60177f0e53b6 (patch)
tree02896d970c7650d8f7c8b84f54e53eddab88b4ca /src/SMAPI.Toolkit
parent5953fc3bd083ae0a579d2da1ad833e6163848086 (diff)
parent733750fdc4f5d16069d95880144619c0e31e8a89 (diff)
downloadSMAPI-d0dc3ea6f6d03e6aabdab5f5f10a60177f0e53b6.tar.gz
SMAPI-d0dc3ea6f6d03e6aabdab5f5f10a60177f0e53b6.tar.bz2
SMAPI-d0dc3ea6f6d03e6aabdab5f5f10a60177f0e53b6.zip
Merge branch 'develop' into stable
Diffstat (limited to 'src/SMAPI.Toolkit')
-rw-r--r--src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs23
-rw-r--r--src/SMAPI.Toolkit/Framework/ModScanning/ModParseError.cs3
-rw-r--r--src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs84
-rw-r--r--src/SMAPI.Toolkit/SemanticVersion.cs12
-rw-r--r--src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs4
5 files changed, 88 insertions, 38 deletions
diff --git a/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs b/src/SMAPI.Toolkit/Framework/GameScanning/GameScanner.cs
index d4c82180..785daba3 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<string, string> registryKeys = new Dictionary<string, string>
@@ -113,10 +105,19 @@ 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
+
+ // 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";
+ }
}
break;
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
/// <summary>The folder is empty or contains only ignored files.</summary>
EmptyFolder,
+ /// <summary>The folder is an empty folder managed by Vortex.</summary>
+ EmptyVortexFolder,
+
/// <summary>The folder is ignored by convention.</summary>
IgnoredFolder,
diff --git a/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs b/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs
index 5eacee9e..86a97016 100644
--- a/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs
+++ b/src/SMAPI.Toolkit/Framework/ModScanning/ModScanner.cs
@@ -58,20 +58,28 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning
".lnk"
};
- /// <summary>The extensions for files which an XNB mod may contain. If a mod doesn't have a <c>manifest.json</c> and contains *only* these file extensions, it should be considered an XNB mod.</summary>
- private readonly HashSet<string> PotentialXnbModExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
+ /// <summary>The extensions for packed content files.</summary>
+ private readonly HashSet<string> StrictXnbModExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
- // XNB files
".xgs",
".xnb",
".xsb",
- ".xwb",
+ ".xwb"
+ };
- // unpacking artifacts
+ /// <summary>The extensions for files which an XNB mod may contain, in addition to <see cref="StrictXnbModExtensions"/>.</summary>
+ private readonly HashSet<string> PotentialXnbModExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
+ {
".json",
".yaml"
};
+ /// <summary>The name of the marker file added by Vortex to indicate it's managing the folder.</summary>
+ private readonly string VortexMarkerFileName = "__folder_managed_by_vortex";
+
+ /// <summary>The name for a mod's configuration JSON file.</summary>
+ private readonly string ConfigFileName = "config.json";
+
/*********
** Public methods
@@ -111,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 (files.All(this.IsPotentialXnbFile))
+ 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?
@@ -270,13 +284,13 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning
return subfolders.Any() && !files.Any();
}
- /// <summary>Recursively get all relevant files in a folder based on the result of <see cref="IsRelevant"/>.</summary>
+ /// <summary>Recursively get all files in a folder.</summary>
/// <param name="folder">The root folder to search.</param>
- private IEnumerable<FileInfo> RecursivelyGetRelevantFiles(DirectoryInfo folder)
+ private IEnumerable<FileInfo> 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)
@@ -284,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;
}
}
@@ -302,14 +316,46 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning
return !this.IgnoreFilesystemNames.Any(p => p.IsMatch(entry.Name));
}
- /// <summary>Get whether a file is potentially part of an XNB mod.</summary>
- /// <param name="entry">The file.</param>
- private bool IsPotentialXnbFile(FileInfo entry)
+ /// <summary>Get whether a set of files looks like an XNB mod.</summary>
+ /// <param name="files">The files in the mod.</param>
+ private bool IsXnbMod(IEnumerable<FileInfo> 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 hasXnbFile;
+ }
+
+ /// <summary>Get whether a set of files looks like an XNB mod.</summary>
+ /// <param name="files">The files in the mod.</param>
+ private bool IsEmptyVortexFolder(IEnumerable<FileInfo> 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 this.PotentialXnbModExtensions.Contains(entry.Extension); // use EndsWith to handle cases like image..png
+ return hasVortexMarker;
}
/// <summary>Strip newlines from a string.</summary>
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;
}
/// <summary>Assert that the current version is valid.</summary>
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
*********/
/// <summary>Get whether this converter can read JSON.</summary>
- public override bool CanRead => true;
+ public override bool CanRead { get; } = true;
/// <summary>Get whether this converter can write JSON.</summary>
- public override bool CanWrite => true;
+ public override bool CanWrite { get; } = true;
/*********