use ordinal comparison/sorting instead of invariant

This commit is contained in:
Jesse Plamondon-Willard 2020-07-26 02:50:20 -04:00
parent ee4c88f601
commit 7900a84bd6
No known key found for this signature in database
GPG Key ID: CF8B1456B3E29F49
43 changed files with 76 additions and 75 deletions

View File

@ -13,6 +13,7 @@
* Added trace log for GPU running the game to simplify troubleshooting some issues. * Added trace log for GPU running the game to simplify troubleshooting some issues.
* Fixed launcher's fallback logic on Linux when no compatible terminal was found (thanks to jlaw!). * Fixed launcher's fallback logic on Linux when no compatible terminal was found (thanks to jlaw!).
* Fixed rare crash when a mod adds/removes an event handler from an event handler. * Fixed rare crash when a mod adds/removes an event handler from an event handler.
* Fixed string sorting/comparison for some special characters.
* For the Console Commands mod: * For the Console Commands mod:
* Fixed error opening menu when some item data is invalid. * Fixed error opening menu when some item data is invalid.

View File

@ -468,7 +468,7 @@ namespace StardewModdingApi.Installer
} }
// find target folder // find target folder
ModFolder targetMod = targetMods.FirstOrDefault(p => p.Manifest?.UniqueID?.Equals(sourceMod.Manifest.UniqueID, StringComparison.InvariantCultureIgnoreCase) == true); ModFolder targetMod = targetMods.FirstOrDefault(p => p.Manifest?.UniqueID?.Equals(sourceMod.Manifest.UniqueID, StringComparison.OrdinalIgnoreCase) == true);
DirectoryInfo defaultTargetFolder = new DirectoryInfo(Path.Combine(paths.ModsPath, sourceMod.Directory.Name)); DirectoryInfo defaultTargetFolder = new DirectoryInfo(Path.Combine(paths.ModsPath, sourceMod.Directory.Name));
DirectoryInfo targetFolder = targetMod?.Directory ?? defaultTargetFolder; DirectoryInfo targetFolder = targetMod?.Directory ?? defaultTargetFolder;
this.PrintDebug(targetFolder.FullName == defaultTargetFolder.FullName this.PrintDebug(targetFolder.FullName == defaultTargetFolder.FullName
@ -808,7 +808,7 @@ namespace StardewModdingApi.Installer
continue; // should never happen continue; // should never happen
// delete packaged mods (newer version bundled into SMAPI) // delete packaged mods (newer version bundled into SMAPI)
if (isDir && packagedModNames.Contains(entry.Name, StringComparer.InvariantCultureIgnoreCase)) if (isDir && packagedModNames.Contains(entry.Name, StringComparer.OrdinalIgnoreCase))
{ {
this.PrintDebug($" Deleting {entry.Name} because it's bundled into SMAPI..."); this.PrintDebug($" Deleting {entry.Name} because it's bundled into SMAPI...");
this.InteractivelyDelete(entry.FullName); this.InteractivelyDelete(entry.FullName);

View File

@ -67,7 +67,7 @@ namespace StardewModdingApi.Installer
AssemblyName name = new AssemblyName(e.Name); AssemblyName name = new AssemblyName(e.Name);
foreach (FileInfo dll in new DirectoryInfo(Program.InternalFilesPath).EnumerateFiles("*.dll")) foreach (FileInfo dll in new DirectoryInfo(Program.InternalFilesPath).EnumerateFiles("*.dll"))
{ {
if (name.Name.Equals(AssemblyName.GetAssemblyName(dll.FullName).Name, StringComparison.InvariantCultureIgnoreCase)) if (name.Name.Equals(AssemblyName.GetAssemblyName(dll.FullName).Name, StringComparison.OrdinalIgnoreCase))
return Assembly.LoadFrom(dll.FullName); return Assembly.LoadFrom(dll.FullName);
} }
return null; return null;

View File

@ -33,7 +33,7 @@ namespace StardewModdingAPI.ModBuildConfig.Framework
/// <exception cref="UserErrorException">The mod package isn't valid.</exception> /// <exception cref="UserErrorException">The mod package isn't valid.</exception>
public ModFileManager(string projectDir, string targetDir, Regex[] ignoreFilePatterns, bool validateRequiredModFiles) public ModFileManager(string projectDir, string targetDir, Regex[] ignoreFilePatterns, bool validateRequiredModFiles)
{ {
this.Files = new Dictionary<string, FileInfo>(StringComparer.InvariantCultureIgnoreCase); this.Files = new Dictionary<string, FileInfo>(StringComparer.OrdinalIgnoreCase);
// validate paths // validate paths
if (!Directory.Exists(projectDir)) if (!Directory.Exists(projectDir))
@ -68,7 +68,7 @@ namespace StardewModdingAPI.ModBuildConfig.Framework
/// <summary>Get the files in the mod package.</summary> /// <summary>Get the files in the mod package.</summary>
public IDictionary<string, FileInfo> GetFiles() public IDictionary<string, FileInfo> GetFiles()
{ {
return new Dictionary<string, FileInfo>(this.Files, StringComparer.InvariantCultureIgnoreCase); return new Dictionary<string, FileInfo>(this.Files, StringComparer.OrdinalIgnoreCase);
} }
/// <summary>Get a semantic version from the mod manifest.</summary> /// <summary>Get a semantic version from the mod manifest.</summary>
@ -165,8 +165,8 @@ namespace StardewModdingAPI.ModBuildConfig.Framework
|| this.EqualsInvariant(file.Name, "Newtonsoft.Json.xml") || this.EqualsInvariant(file.Name, "Newtonsoft.Json.xml")
// code analysis files // code analysis files
|| file.Name.EndsWith(".CodeAnalysisLog.xml", StringComparison.InvariantCultureIgnoreCase) || file.Name.EndsWith(".CodeAnalysisLog.xml", StringComparison.OrdinalIgnoreCase)
|| file.Name.EndsWith(".lastcodeanalysissucceeded", StringComparison.InvariantCultureIgnoreCase) || file.Name.EndsWith(".lastcodeanalysissucceeded", StringComparison.OrdinalIgnoreCase)
// OS metadata files // OS metadata files
|| this.EqualsInvariant(file.Name, ".DS_Store") || this.EqualsInvariant(file.Name, ".DS_Store")
@ -183,7 +183,7 @@ namespace StardewModdingAPI.ModBuildConfig.Framework
{ {
if (str == null) if (str == null)
return other == null; return other == null;
return str.Equals(other, StringComparison.InvariantCultureIgnoreCase); return str.Equals(other, StringComparison.OrdinalIgnoreCase);
} }
} }
} }

View File

@ -64,7 +64,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands
this.LogError($"Argument {index} ({name}) is required."); this.LogError($"Argument {index} ({name}) is required.");
return false; return false;
} }
if (oneOf?.Any() == true && !oneOf.Contains(this.Args[index], StringComparer.InvariantCultureIgnoreCase)) if (oneOf?.Any() == true && !oneOf.Contains(this.Args[index], StringComparer.OrdinalIgnoreCase))
{ {
this.LogError($"Argument {index} ({name}) must be one of {string.Join(", ", oneOf)}."); this.LogError($"Argument {index} ({name}) must be one of {string.Join(", ", oneOf)}.");
return false; return false;

View File

@ -56,7 +56,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World
return; return;
// get target location // get target location
GameLocation location = Game1.locations.FirstOrDefault(p => p.Name != null && p.Name.Equals(locationName, StringComparison.InvariantCultureIgnoreCase)); GameLocation location = Game1.locations.FirstOrDefault(p => p.Name != null && p.Name.Equals(locationName, StringComparison.OrdinalIgnoreCase));
if (location == null && locationName == "current") if (location == null && locationName == "current")
location = Game1.currentLocation; location = Game1.currentLocation;
if (location == null) if (location == null)

View File

@ -44,8 +44,8 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.ItemData
public bool NameContains(string substring) public bool NameContains(string substring)
{ {
return return
this.Name.IndexOf(substring, StringComparison.InvariantCultureIgnoreCase) != -1 this.Name.IndexOf(substring, StringComparison.OrdinalIgnoreCase) != -1
|| this.DisplayName.IndexOf(substring, StringComparison.InvariantCultureIgnoreCase) != -1; || this.DisplayName.IndexOf(substring, StringComparison.OrdinalIgnoreCase) != -1;
} }
/// <summary>Get whether the item name is exactly equal to a case-insensitive string.</summary> /// <summary>Get whether the item name is exactly equal to a case-insensitive string.</summary>
@ -53,8 +53,8 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.ItemData
public bool NameEquivalentTo(string name) public bool NameEquivalentTo(string name)
{ {
return return
this.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase) this.Name.Equals(name, StringComparison.OrdinalIgnoreCase)
|| this.DisplayName.Equals(name, StringComparison.InvariantCultureIgnoreCase); || this.DisplayName.Equals(name, StringComparison.OrdinalIgnoreCase);
} }
} }
} }

View File

@ -233,7 +233,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
// parse // parse
// Specified on the wiki in the form "remote version → mapped version; another remote version → mapped version" // Specified on the wiki in the form "remote version → mapped version; another remote version → mapped version"
IDictionary<string, string> map = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase); IDictionary<string, string> map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (string pair in raw.Split(';')) foreach (string pair in raw.Split(';'))
{ {
string[] versions = pair.Split('→'); string[] versions = pair.Split('→');

View File

@ -30,7 +30,7 @@ namespace StardewModdingAPI.Toolkit.Framework.GameScanning
.GetCustomInstallPaths(platform) .GetCustomInstallPaths(platform)
.Concat(this.GetDefaultInstallPaths(platform)) .Concat(this.GetDefaultInstallPaths(platform))
.Select(PathUtilities.NormalizePathSeparators) .Select(PathUtilities.NormalizePathSeparators)
.Distinct(StringComparer.InvariantCultureIgnoreCase); .Distinct(StringComparer.OrdinalIgnoreCase);
// yield valid folders // yield valid folders
foreach (string path in paths) foreach (string path in paths)

View File

@ -68,7 +68,7 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData
foreach (string part in parts.Take(parts.Length - 1)) foreach (string part in parts.Take(parts.Length - 1))
{ {
// 'default' // 'default'
if (part.Equals("Default", StringComparison.InvariantCultureIgnoreCase)) if (part.Equals("Default", StringComparison.OrdinalIgnoreCase))
{ {
isDefault = true; isDefault = true;
continue; continue;

View File

@ -46,13 +46,13 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData
public bool HasID(string id) public bool HasID(string id)
{ {
// try main ID // try main ID
if (this.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase)) if (this.ID.Equals(id, StringComparison.OrdinalIgnoreCase))
return true; return true;
// try former IDs // try former IDs
foreach (string formerID in this.FormerIDs) foreach (string formerID in this.FormerIDs)
{ {
if (formerID.Equals(id, StringComparison.InvariantCultureIgnoreCase)) if (formerID.Equals(id, StringComparison.OrdinalIgnoreCase))
return true; return true;
} }

View File

@ -59,7 +59,7 @@ namespace StardewModdingAPI.Toolkit.Framework.ModScanning
}; };
/// <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> /// <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.InvariantCultureIgnoreCase) private readonly HashSet<string> PotentialXnbModExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{ {
// XNB files // XNB files
".xgs", ".xgs",

View File

@ -22,7 +22,7 @@ namespace StardewModdingAPI.Toolkit
private readonly string UserAgent; private readonly string UserAgent;
/// <summary>Maps vendor keys (like <c>Nexus</c>) to their mod URL template (where <c>{0}</c> is the mod ID). This doesn't affect update checks, which defer to the remote web API.</summary> /// <summary>Maps vendor keys (like <c>Nexus</c>) to their mod URL template (where <c>{0}</c> is the mod ID). This doesn't affect update checks, which defer to the remote web API.</summary>
private readonly IDictionary<string, string> VendorModUrls = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) private readonly IDictionary<string, string> VendorModUrls = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{ {
["Chucklefish"] = "https://community.playstarbound.com/resources/{0}", ["Chucklefish"] = "https://community.playstarbound.com/resources/{0}",
["GitHub"] = "https://github.com/{0}/releases", ["GitHub"] = "https://github.com/{0}/releases",

View File

@ -278,9 +278,9 @@ namespace StardewModdingAPI.Toolkit
if (curParts[i] != otherParts[i]) if (curParts[i] != otherParts[i])
{ {
// unofficial is always lower-precedence // unofficial is always lower-precedence
if (otherParts[i].Equals("unofficial", StringComparison.InvariantCultureIgnoreCase)) if (otherParts[i].Equals("unofficial", StringComparison.OrdinalIgnoreCase))
return curNewer; return curNewer;
if (curParts[i].Equals("unofficial", StringComparison.InvariantCultureIgnoreCase)) if (curParts[i].Equals("unofficial", StringComparison.OrdinalIgnoreCase))
return curOlder; return curOlder;
// compare numerically if possible // compare numerically if possible
@ -295,7 +295,7 @@ namespace StardewModdingAPI.Toolkit
} }
// fallback (this should never happen) // fallback (this should never happen)
return string.Compare(this.ToString(), new SemanticVersion(otherMajor, otherMinor, otherPatch, otherPlatformRelease, otherTag).ToString(), StringComparison.InvariantCultureIgnoreCase); return string.Compare(this.ToString(), new SemanticVersion(otherMajor, otherMinor, otherPatch, otherPlatformRelease, otherTag).ToString(), StringComparison.OrdinalIgnoreCase);
} }
/// <summary>Assert that the current version is valid.</summary> /// <summary>Assert that the current version is valid.</summary>

View File

@ -12,7 +12,7 @@ namespace StardewModdingAPI.Toolkit.Serialization
/// <param name="fieldName">The field name.</param> /// <param name="fieldName">The field name.</param>
public static T ValueIgnoreCase<T>(this JObject obj, string fieldName) public static T ValueIgnoreCase<T>(this JObject obj, string fieldName)
{ {
JToken token = obj.GetValue(fieldName, StringComparison.InvariantCultureIgnoreCase); JToken token = obj.GetValue(fieldName, StringComparison.OrdinalIgnoreCase);
return token != null return token != null
? token.Value<T>() ? token.Value<T>()
: default(T); : default(T);

View File

@ -280,7 +280,7 @@ namespace StardewModdingAPI.Web.Controllers
IDictionary<string, string> errors = this.GetExtensionField<Dictionary<string, string>>(error.Schema, "@errorMessages"); IDictionary<string, string> errors = this.GetExtensionField<Dictionary<string, string>>(error.Schema, "@errorMessages");
if (errors == null) if (errors == null)
return null; return null;
errors = new Dictionary<string, string>(errors, StringComparer.InvariantCultureIgnoreCase); errors = new Dictionary<string, string>(errors, StringComparer.OrdinalIgnoreCase);
// match error by type and message // match error by type and message
foreach ((string target, string errorMessage) in errors) foreach ((string target, string errorMessage) in errors)
@ -289,7 +289,7 @@ namespace StardewModdingAPI.Web.Controllers
continue; continue;
string[] parts = target.Split(':', 2); string[] parts = target.Split(':', 2);
if (parts[0].Equals(error.ErrorType.ToString(), StringComparison.InvariantCultureIgnoreCase) && Regex.IsMatch(error.Message, parts[1])) if (parts[0].Equals(error.ErrorType.ToString(), StringComparison.OrdinalIgnoreCase) && Regex.IsMatch(error.Message, parts[1]))
return errorMessage?.Trim(); return errorMessage?.Trim();
} }
@ -313,7 +313,7 @@ namespace StardewModdingAPI.Web.Controllers
{ {
foreach ((string curKey, JToken value) in schema.ExtensionData) foreach ((string curKey, JToken value) in schema.ExtensionData)
{ {
if (curKey.Equals(key, StringComparison.InvariantCultureIgnoreCase)) if (curKey.Equals(key, StringComparison.OrdinalIgnoreCase))
return value.ToObject<T>(); return value.ToObject<T>();
} }
} }

View File

@ -118,9 +118,9 @@ namespace StardewModdingAPI.Web.Controllers
{ {
// cross-reference data // cross-reference data
ModDataRecord record = this.ModDatabase.Get(search.ID); ModDataRecord record = this.ModDatabase.Get(search.ID);
WikiModEntry wikiEntry = wikiData.FirstOrDefault(entry => entry.ID.Contains(search.ID.Trim(), StringComparer.InvariantCultureIgnoreCase)); WikiModEntry wikiEntry = wikiData.FirstOrDefault(entry => entry.ID.Contains(search.ID.Trim(), StringComparer.OrdinalIgnoreCase));
UpdateKey[] updateKeys = this.GetUpdateKeys(search.UpdateKeys, record, wikiEntry).ToArray(); UpdateKey[] updateKeys = this.GetUpdateKeys(search.UpdateKeys, record, wikiEntry).ToArray();
ModOverrideConfig overrides = this.Config.Value.ModOverrides.FirstOrDefault(p => p.ID.Equals(search.ID?.Trim(), StringComparison.InvariantCultureIgnoreCase)); ModOverrideConfig overrides = this.Config.Value.ModOverrides.FirstOrDefault(p => p.ID.Equals(search.ID?.Trim(), StringComparison.OrdinalIgnoreCase));
bool allowNonStandardVersions = overrides?.AllowNonStandardVersions ?? false; bool allowNonStandardVersions = overrides?.AllowNonStandardVersions ?? false;
// get latest versions // get latest versions

View File

@ -13,7 +13,7 @@ namespace StardewModdingAPI.Web.Framework.Caching.Mods
** Fields ** Fields
*********/ *********/
/// <summary>The cached mod data indexed by <c>{site key}:{ID}</c>.</summary> /// <summary>The cached mod data indexed by <c>{site key}:{ID}</c>.</summary>
private readonly IDictionary<string, Cached<IModPage>> Mods = new Dictionary<string, Cached<IModPage>>(StringComparer.InvariantCultureIgnoreCase); private readonly IDictionary<string, Cached<IModPage>> Mods = new Dictionary<string, Cached<IModPage>>(StringComparer.OrdinalIgnoreCase);
/********* /*********

View File

@ -150,7 +150,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.GitHub
/// <exception cref="ArgumentException">The repository key is invalid.</exception> /// <exception cref="ArgumentException">The repository key is invalid.</exception>
private void AssertKeyFormat(string repo) private void AssertKeyFormat(string repo)
{ {
if (repo == null || !repo.Contains("/") || repo.IndexOf("/", StringComparison.InvariantCultureIgnoreCase) != repo.LastIndexOf("/", StringComparison.InvariantCultureIgnoreCase)) if (repo == null || !repo.Contains("/") || repo.IndexOf("/", StringComparison.OrdinalIgnoreCase) != repo.LastIndexOf("/", StringComparison.OrdinalIgnoreCase))
throw new ArgumentException($"The value '{repo}' isn't a valid GitHub repository key, must be a username and project name like 'Pathoschild/SMAPI'.", nameof(repo)); throw new ArgumentException($"The value '{repo}' isn't a valid GitHub repository key, must be a username and project name like 'Pathoschild/SMAPI'.", nameof(repo));
} }
} }

View File

@ -13,7 +13,7 @@ namespace StardewModdingAPI.Framework
** Fields ** Fields
*********/ *********/
/// <summary>The commands registered with SMAPI.</summary> /// <summary>The commands registered with SMAPI.</summary>
private readonly IDictionary<string, Command> Commands = new Dictionary<string, Command>(StringComparer.InvariantCultureIgnoreCase); private readonly IDictionary<string, Command> Commands = new Dictionary<string, Command>(StringComparer.OrdinalIgnoreCase);
/********* /*********

View File

@ -67,7 +67,7 @@ namespace StardewModdingAPI.Framework.Content
{ {
// change ID if needed so new tilesheets are added after vanilla ones (to avoid errors in hardcoded game logic) // change ID if needed so new tilesheets are added after vanilla ones (to avoid errors in hardcoded game logic)
string id = sourceSheet.Id; string id = sourceSheet.Id;
if (!id.StartsWith("z_", StringComparison.InvariantCultureIgnoreCase)) if (!id.StartsWith("z_", StringComparison.OrdinalIgnoreCase))
id = $"z_{id}"; id = $"z_{id}";
// change ID if it conflicts with an existing tilesheet // change ID if it conflicts with an existing tilesheet

View File

@ -47,7 +47,7 @@ namespace StardewModdingAPI.Framework.Content
public bool AssetNameEquals(string path) public bool AssetNameEquals(string path)
{ {
path = this.GetNormalizedPath(path); path = this.GetNormalizedPath(path);
return this.AssetName.Equals(path, StringComparison.InvariantCultureIgnoreCase); return this.AssetName.Equals(path, StringComparison.OrdinalIgnoreCase);
} }

View File

@ -89,7 +89,7 @@ namespace StardewModdingAPI.Framework.Content
public string NormalizeKey(string key) public string NormalizeKey(string key)
{ {
key = this.NormalizePathSeparators(key); key = this.NormalizePathSeparators(key);
return key.EndsWith(".xnb", StringComparison.InvariantCultureIgnoreCase) return key.EndsWith(".xnb", StringComparison.OrdinalIgnoreCase)
? key.Substring(0, key.Length - 4) ? key.Substring(0, key.Length - 4)
: this.NormalizeAssetNameForPlatform(key); : this.NormalizeAssetNameForPlatform(key);
} }

View File

@ -229,7 +229,7 @@ namespace StardewModdingAPI.Framework
public IEnumerable<string> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false) public IEnumerable<string> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false)
{ {
// invalidate cache & track removed assets // invalidate cache & track removed assets
IDictionary<string, Type> removedAssets = new Dictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase); IDictionary<string, Type> removedAssets = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
this.ContentManagerLock.InReadLock(() => this.ContentManagerLock.InReadLock(() =>
{ {
// cached assets // cached assets
@ -263,7 +263,7 @@ namespace StardewModdingAPI.Framework
if (removedAssets.Any()) if (removedAssets.Any())
{ {
IDictionary<string, bool> propagated = this.CoreAssets.Propagate(this.MainContentManager, removedAssets.ToDictionary(p => p.Key, p => p.Value)); // use an intercepted content manager IDictionary<string, bool> propagated = this.CoreAssets.Propagate(this.MainContentManager, removedAssets.ToDictionary(p => p.Key, p => p.Value)); // use an intercepted content manager
this.Monitor.Log($"Invalidated {removedAssets.Count} asset names ({string.Join(", ", removedAssets.Keys.OrderBy(p => p, StringComparer.InvariantCultureIgnoreCase))}); propagated {propagated.Count(p => p.Value)} core assets.", LogLevel.Trace); this.Monitor.Log($"Invalidated {removedAssets.Count} asset names ({string.Join(", ", removedAssets.Keys.OrderBy(p => p, StringComparer.OrdinalIgnoreCase))}); propagated {propagated.Count(p => p.Value)} core assets.", LogLevel.Trace);
} }
else else
this.Monitor.Log("Invalidated 0 cache entries.", LogLevel.Trace); this.Monitor.Log("Invalidated 0 cache entries.", LogLevel.Trace);

View File

@ -87,7 +87,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
this.IsNamespaced = isNamespaced; this.IsNamespaced = isNamespaced;
// get asset data // get asset data
this.LanguageCodes = this.GetKeyLocales().ToDictionary(p => p.Value, p => p.Key, StringComparer.InvariantCultureIgnoreCase); this.LanguageCodes = this.GetKeyLocales().ToDictionary(p => p.Value, p => p.Key, StringComparer.OrdinalIgnoreCase);
this.BaseDisposableReferences = reflection.GetField<List<IDisposable>>(this, "disposableAssets").GetValue(); this.BaseDisposableReferences = reflection.GetField<List<IDisposable>>(this, "disposableAssets").GetValue();
} }
@ -192,7 +192,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
/// <returns>Returns the invalidated asset names and instances.</returns> /// <returns>Returns the invalidated asset names and instances.</returns>
public IDictionary<string, object> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false) public IDictionary<string, object> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false)
{ {
IDictionary<string, object> removeAssets = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase); IDictionary<string, object> removeAssets = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
this.Cache.Remove((key, asset) => this.Cache.Remove((key, asset) =>
{ {
this.ParseCacheKey(key, out string assetName, out _); this.ParseCacheKey(key, out string assetName, out _);
@ -295,7 +295,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
// handle localized key // handle localized key
if (!string.IsNullOrWhiteSpace(cacheKey)) if (!string.IsNullOrWhiteSpace(cacheKey))
{ {
int lastSepIndex = cacheKey.LastIndexOf(".", StringComparison.InvariantCulture); int lastSepIndex = cacheKey.LastIndexOf(".", StringComparison.Ordinal);
if (lastSepIndex >= 0) if (lastSepIndex >= 0)
{ {
string suffix = cacheKey.Substring(lastSepIndex + 1, cacheKey.Length - lastSepIndex - 1); string suffix = cacheKey.Substring(lastSepIndex + 1, cacheKey.Length - lastSepIndex - 1);

View File

@ -123,7 +123,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
base.OnLocaleChanged(); base.OnLocaleChanged();
// find assets for which a translatable version was loaded // find assets for which a translatable version was loaded
HashSet<string> removeAssetNames = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase); HashSet<string> removeAssetNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (string key in this.IsLocalizableLookup.Where(p => p.Value).Select(p => p.Key)) foreach (string key in this.IsLocalizableLookup.Where(p => p.Value).Select(p => p.Key))
removeAssetNames.Add(this.TryParseExplicitLanguageAssetKey(key, out string assetName, out _) ? assetName : key); removeAssetNames.Add(this.TryParseExplicitLanguageAssetKey(key, out string assetName, out _) ? assetName : key);
@ -134,7 +134,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
|| (this.TryParseExplicitLanguageAssetKey(key, out string assetName, out _) && removeAssetNames.Contains(assetName)) || (this.TryParseExplicitLanguageAssetKey(key, out string assetName, out _) && removeAssetNames.Contains(assetName))
) )
.Select(p => p.Key) .Select(p => p.Key)
.OrderBy(p => p, StringComparer.InvariantCultureIgnoreCase) .OrderBy(p => p, StringComparer.OrdinalIgnoreCase)
.ToArray(); .ToArray();
if (invalidated.Any()) if (invalidated.Any())
this.Monitor.Log($"Invalidated {invalidated.Length} asset names: {string.Join(", ", invalidated)} for locale change.", LogLevel.Trace); this.Monitor.Log($"Invalidated {invalidated.Length} asset names: {string.Join(", ", invalidated)} for locale change.", LogLevel.Trace);

View File

@ -372,7 +372,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
break; break;
} }
} }
if (contentKey.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase)) if (contentKey.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
contentKey = contentKey.Substring(0, contentKey.Length - 4); contentKey = contentKey.Substring(0, contentKey.Length - 4);
try try

View File

@ -11,7 +11,7 @@ namespace StardewModdingAPI.Framework
** Fields ** Fields
*********/ *********/
/// <summary>The deprecations which have already been logged (as 'mod name::noun phrase::version').</summary> /// <summary>The deprecations which have already been logged (as 'mod name::noun phrase::version').</summary>
private readonly HashSet<string> LoggedDeprecations = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase); private readonly HashSet<string> LoggedDeprecations = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
/// <summary>Encapsulates monitoring and logging for a given module.</summary> /// <summary>Encapsulates monitoring and logging for a given module.</summary>
private readonly IMonitor Monitor; private readonly IMonitor Monitor;

View File

@ -10,7 +10,7 @@ namespace StardewModdingAPI.Framework
** Private methods ** Private methods
*********/ *********/
/// <summary>A mapping of game to semantic versions.</summary> /// <summary>A mapping of game to semantic versions.</summary>
private static readonly IDictionary<string, string> VersionMap = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) private static readonly IDictionary<string, string> VersionMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{ {
["1.0"] = "1.0.0", ["1.0"] = "1.0.0",
["1.01"] = "1.0.1", ["1.01"] = "1.0.1",
@ -64,7 +64,7 @@ namespace StardewModdingAPI.Framework
{ {
foreach (var mapping in GameVersion.VersionMap) foreach (var mapping in GameVersion.VersionMap)
{ {
if (mapping.Value.Equals(semanticVersion, StringComparison.InvariantCultureIgnoreCase)) if (mapping.Value.Equals(semanticVersion, StringComparison.OrdinalIgnoreCase))
return mapping.Key; return mapping.Key;
} }

View File

@ -18,7 +18,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework
public ISet<InstructionHandleResult> Flags { get; } = new HashSet<InstructionHandleResult>(); public ISet<InstructionHandleResult> Flags { get; } = new HashSet<InstructionHandleResult>();
/// <summary>The brief noun phrases indicating what the handler matched for the current module.</summary> /// <summary>The brief noun phrases indicating what the handler matched for the current module.</summary>
public ISet<string> Phrases { get; } = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase); public ISet<string> Phrases { get; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
/********* /*********

View File

@ -173,7 +173,7 @@ namespace StardewModdingAPI.Framework.ModLoading
{ {
return return
this.HasID() this.HasID()
&& string.Equals(this.Manifest.UniqueID.Trim(), id?.Trim(), StringComparison.InvariantCultureIgnoreCase); && string.Equals(this.Manifest.UniqueID.Trim(), id?.Trim(), StringComparison.OrdinalIgnoreCase);
} }
/// <summary>Get the defined update keys.</summary> /// <summary>Get the defined update keys.</summary>
@ -192,7 +192,7 @@ namespace StardewModdingAPI.Framework.ModLoading
/// <param name="includeOptional">Whether to include optional dependencies.</param> /// <param name="includeOptional">Whether to include optional dependencies.</param>
public IEnumerable<string> GetRequiredModIds(bool includeOptional = false) public IEnumerable<string> GetRequiredModIds(bool includeOptional = false)
{ {
HashSet<string> required = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase); HashSet<string> required = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
// yield dependencies // yield dependencies
if (this.Manifest?.Dependencies != null) if (this.Manifest?.Dependencies != null)

View File

@ -190,7 +190,7 @@ namespace StardewModdingAPI.Framework.ModLoading
// validate IDs are unique // validate IDs are unique
{ {
var duplicatesByID = mods var duplicatesByID = mods
.GroupBy(mod => mod.Manifest?.UniqueID?.Trim(), mod => mod, StringComparer.InvariantCultureIgnoreCase) .GroupBy(mod => mod.Manifest?.UniqueID?.Trim(), mod => mod, StringComparer.OrdinalIgnoreCase)
.Where(p => p.Count() > 1); .Where(p => p.Count() > 1);
foreach (var group in duplicatesByID) foreach (var group in duplicatesByID)
{ {

View File

@ -25,7 +25,7 @@ namespace StardewModdingAPI.Framework.Models
}; };
/// <summary>The default values for <see cref="SuppressUpdateChecks"/>, to log changes if different.</summary> /// <summary>The default values for <see cref="SuppressUpdateChecks"/>, to log changes if different.</summary>
private static readonly HashSet<string> DefaultSuppressUpdateChecks = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) private static readonly HashSet<string> DefaultSuppressUpdateChecks = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{ {
"SMAPI.ConsoleCommands", "SMAPI.ConsoleCommands",
"SMAPI.SaveBackup" "SMAPI.SaveBackup"
@ -84,7 +84,7 @@ namespace StardewModdingAPI.Framework.Models
custom[pair.Key] = value; custom[pair.Key] = value;
} }
HashSet<string> curSuppressUpdateChecks = new HashSet<string>(this.SuppressUpdateChecks ?? new string[0], StringComparer.InvariantCultureIgnoreCase); HashSet<string> curSuppressUpdateChecks = new HashSet<string>(this.SuppressUpdateChecks ?? new string[0], StringComparer.OrdinalIgnoreCase);
if (SConfig.DefaultSuppressUpdateChecks.Count != curSuppressUpdateChecks.Count || SConfig.DefaultSuppressUpdateChecks.Any(p => !curSuppressUpdateChecks.Contains(p))) if (SConfig.DefaultSuppressUpdateChecks.Count != curSuppressUpdateChecks.Count || SConfig.DefaultSuppressUpdateChecks.Any(p => !curSuppressUpdateChecks.Contains(p)))
custom[nameof(this.SuppressUpdateChecks)] = "[" + string.Join(", ", this.SuppressUpdateChecks ?? new string[0]) + "]"; custom[nameof(this.SuppressUpdateChecks)] = "[" + string.Join(", ", this.SuppressUpdateChecks ?? new string[0]) + "]";

View File

@ -71,7 +71,7 @@ namespace StardewModdingAPI.Framework.Networking
return null; return null;
id = id.Trim(); id = id.Trim();
return this.Mods.FirstOrDefault(mod => mod.ID != null && mod.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase)); return this.Mods.FirstOrDefault(mod => mod.ID != null && mod.ID.Equals(id, StringComparison.OrdinalIgnoreCase));
} }
/// <summary>Send a message to the given peer, bypassing the game's normal validation to allow messages before the connection is approved.</summary> /// <summary>Send a message to the given peer, bypassing the game's normal validation to allow messages before the connection is approved.</summary>

View File

@ -189,7 +189,7 @@ namespace StardewModdingAPI.Framework.PerformanceMonitoring
public void ResetSource(string source) public void ResetSource(string source)
{ {
foreach (var i in this.PerformanceCounters) foreach (var i in this.PerformanceCounters)
if (i.Value.Source.Equals(source, StringComparison.InvariantCultureIgnoreCase)) if (i.Value.Source.Equals(source, StringComparison.OrdinalIgnoreCase))
i.Value.Reset(); i.Value.Reset();
} }

View File

@ -23,7 +23,7 @@ namespace StardewModdingAPI.Framework.PerformanceMonitoring
private readonly Stopwatch InvocationStopwatch = new Stopwatch(); private readonly Stopwatch InvocationStopwatch = new Stopwatch();
/// <summary>The underlying performance counter collections.</summary> /// <summary>The underlying performance counter collections.</summary>
private readonly IDictionary<string, PerformanceCounterCollection> Collections = new Dictionary<string, PerformanceCounterCollection>(StringComparer.InvariantCultureIgnoreCase); private readonly IDictionary<string, PerformanceCounterCollection> Collections = new Dictionary<string, PerformanceCounterCollection>(StringComparer.OrdinalIgnoreCase);
/********* /*********

View File

@ -451,7 +451,7 @@ namespace StardewModdingAPI.Framework
{ {
string[] looseFiles = new DirectoryInfo(this.ModsPath).GetFiles().Select(p => p.Name).ToArray(); string[] looseFiles = new DirectoryInfo(this.ModsPath).GetFiles().Select(p => p.Name).ToArray();
if (looseFiles.Any()) if (looseFiles.Any())
this.Monitor.Log($" Ignored loose files: {string.Join(", ", looseFiles.OrderBy(p => p, StringComparer.InvariantCultureIgnoreCase))}", LogLevel.Trace); this.Monitor.Log($" Ignored loose files: {string.Join(", ", looseFiles.OrderBy(p => p, StringComparer.OrdinalIgnoreCase))}", LogLevel.Trace);
} }
// load manifests // load manifests
@ -650,7 +650,7 @@ namespace StardewModdingAPI.Framework
{ {
try try
{ {
HashSet<string> suppressUpdateChecks = new HashSet<string>(this.Settings.SuppressUpdateChecks, StringComparer.InvariantCultureIgnoreCase); HashSet<string> suppressUpdateChecks = new HashSet<string>(this.Settings.SuppressUpdateChecks, StringComparer.OrdinalIgnoreCase);
// prepare search model // prepare search model
List<ModSearchEntryModel> searchMods = new List<ModSearchEntryModel>(); List<ModSearchEntryModel> searchMods = new List<ModSearchEntryModel>();
@ -756,7 +756,7 @@ namespace StardewModdingAPI.Framework
using (AssemblyLoader modAssemblyLoader = new AssemblyLoader(Constants.Platform, this.Monitor, this.Settings.ParanoidWarnings)) using (AssemblyLoader modAssemblyLoader = new AssemblyLoader(Constants.Platform, this.Monitor, this.Settings.ParanoidWarnings))
{ {
// init // init
HashSet<string> suppressUpdateChecks = new HashSet<string>(this.Settings.SuppressUpdateChecks, StringComparer.InvariantCultureIgnoreCase); HashSet<string> suppressUpdateChecks = new HashSet<string>(this.Settings.SuppressUpdateChecks, StringComparer.OrdinalIgnoreCase);
InterfaceProxyFactory proxyFactory = new InterfaceProxyFactory(); InterfaceProxyFactory proxyFactory = new InterfaceProxyFactory();
void LogSkip(IModMetadata mod, string errorPhrase, string errorDetails) void LogSkip(IModMetadata mod, string errorPhrase, string errorDetails)
{ {
@ -1103,8 +1103,8 @@ namespace StardewModdingAPI.Framework
// find skipped dependencies // find skipped dependencies
KeyValuePair<IModMetadata, Tuple<string, string>>[] skippedDependencies; KeyValuePair<IModMetadata, Tuple<string, string>>[] skippedDependencies;
{ {
HashSet<string> skippedDependencyIds = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase); HashSet<string> skippedDependencyIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
HashSet<string> skippedModIds = new HashSet<string>(from mod in skippedMods where mod.Key.HasID() select mod.Key.Manifest.UniqueID, StringComparer.InvariantCultureIgnoreCase); HashSet<string> skippedModIds = new HashSet<string>(from mod in skippedMods where mod.Key.HasID() select mod.Key.Manifest.UniqueID, StringComparer.OrdinalIgnoreCase);
foreach (IModMetadata mod in skippedMods.Keys) foreach (IModMetadata mod in skippedMods.Keys)
{ {
foreach (string requiredId in skippedModIds.Intersect(mod.GetRequiredModIds())) foreach (string requiredId in skippedModIds.Intersect(mod.GetRequiredModIds()))
@ -1351,8 +1351,8 @@ namespace StardewModdingAPI.Framework
foreach (string locale in translations.Keys.ToArray()) foreach (string locale in translations.Keys.ToArray())
{ {
// handle duplicates // handle duplicates
HashSet<string> keys = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase); HashSet<string> keys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
HashSet<string> duplicateKeys = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase); HashSet<string> duplicateKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (string key in translations[locale].Keys.ToArray()) foreach (string key in translations[locale].Keys.ToArray())
{ {
if (!keys.Add(key)) if (!keys.Add(key))
@ -1458,7 +1458,7 @@ namespace StardewModdingAPI.Framework
foreach (FileInfo logFile in logsDir.EnumerateFiles()) foreach (FileInfo logFile in logsDir.EnumerateFiles())
{ {
// skip non-SMAPI file // skip non-SMAPI file
if (!logFile.Name.StartsWith(Constants.LogNamePrefix, StringComparison.InvariantCultureIgnoreCase)) if (!logFile.Name.StartsWith(Constants.LogNamePrefix, StringComparison.OrdinalIgnoreCase))
continue; continue;
// skip crash log // skip crash log

View File

@ -239,7 +239,7 @@ namespace StardewModdingAPI.Framework
private void OnModMessageReceived(ModMessageModel message) private void OnModMessageReceived(ModMessageModel message)
{ {
// get mod IDs to notify // get mod IDs to notify
HashSet<string> modIDs = new HashSet<string>(message.ToModIDs ?? this.ModRegistry.GetAll().Select(p => p.Manifest.UniqueID), StringComparer.InvariantCultureIgnoreCase); HashSet<string> modIDs = new HashSet<string>(message.ToModIDs ?? this.ModRegistry.GetAll().Select(p => p.Manifest.UniqueID), StringComparer.OrdinalIgnoreCase);
if (message.FromPlayerID == Game1.player?.UniqueMultiplayerID) if (message.FromPlayerID == Game1.player?.UniqueMultiplayerID)
modIDs.Remove(message.FromModID); // don't send a broadcast back to the sender modIDs.Remove(message.FromModID); // don't send a broadcast back to the sender

View File

@ -373,7 +373,7 @@ namespace StardewModdingAPI.Framework
// filter by mod ID // filter by mod ID
if (toModIDs != null) if (toModIDs != null)
{ {
HashSet<string> sendToMods = new HashSet<string>(toModIDs, StringComparer.InvariantCultureIgnoreCase); HashSet<string> sendToMods = new HashSet<string>(toModIDs, StringComparer.OrdinalIgnoreCase);
if (sendToSelf && toModIDs.All(id => this.ModRegistry.Get(id) == null)) if (sendToSelf && toModIDs.All(id => this.ModRegistry.Get(id) == null))
sendToSelf = false; sendToSelf = false;

View File

@ -12,7 +12,7 @@ namespace StardewModdingAPI.Framework
** Fields ** Fields
*********/ *********/
/// <summary>The translations for each locale.</summary> /// <summary>The translations for each locale.</summary>
private readonly IDictionary<string, IDictionary<string, string>> All = new Dictionary<string, IDictionary<string, string>>(StringComparer.InvariantCultureIgnoreCase); private readonly IDictionary<string, IDictionary<string, string>> All = new Dictionary<string, IDictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
/// <summary>The translations for the current locale, with locale fallback taken into account.</summary> /// <summary>The translations for the current locale, with locale fallback taken into account.</summary>
private IDictionary<string, Translation> ForLocale; private IDictionary<string, Translation> ForLocale;
@ -45,7 +45,7 @@ namespace StardewModdingAPI.Framework
this.Locale = locale.ToLower().Trim(); this.Locale = locale.ToLower().Trim();
this.LocaleEnum = localeEnum; this.LocaleEnum = localeEnum;
this.ForLocale = new Dictionary<string, Translation>(StringComparer.InvariantCultureIgnoreCase); this.ForLocale = new Dictionary<string, Translation>(StringComparer.OrdinalIgnoreCase);
foreach (string next in this.GetRelevantLocales(this.Locale)) foreach (string next in this.GetRelevantLocales(this.Locale))
{ {
// skip if locale not defined // skip if locale not defined
@ -90,7 +90,7 @@ namespace StardewModdingAPI.Framework
// reset translations // reset translations
this.All.Clear(); this.All.Clear();
foreach (var pair in translations) foreach (var pair in translations)
this.All[pair.Key] = new Dictionary<string, string>(pair.Value, StringComparer.InvariantCultureIgnoreCase); this.All[pair.Key] = new Dictionary<string, string>(pair.Value, StringComparer.OrdinalIgnoreCase);
// rebuild cache // rebuild cache
this.SetLocale(this.Locale, this.LocaleEnum); this.SetLocale(this.Locale, this.LocaleEnum);

View File

@ -84,7 +84,7 @@ namespace StardewModdingAPI.Metadata
}); });
// reload assets // reload assets
IDictionary<string, bool> propagated = assets.ToDictionary(p => p.Key, p => false, StringComparer.InvariantCultureIgnoreCase); IDictionary<string, bool> propagated = assets.ToDictionary(p => p.Key, p => false, StringComparer.OrdinalIgnoreCase);
foreach (var bucket in buckets) foreach (var bucket in buckets)
{ {
switch (bucket.Key) switch (bucket.Key)
@ -779,7 +779,7 @@ namespace StardewModdingAPI.Metadata
private void ReloadNpcSprites(LocalizedContentManager content, IEnumerable<string> keys, IDictionary<string, bool> propagated) private void ReloadNpcSprites(LocalizedContentManager content, IEnumerable<string> keys, IDictionary<string, bool> propagated)
{ {
// get NPCs // get NPCs
HashSet<string> lookup = new HashSet<string>(keys, StringComparer.InvariantCultureIgnoreCase); HashSet<string> lookup = new HashSet<string>(keys, StringComparer.OrdinalIgnoreCase);
var characters = var characters =
( (
from npc in this.GetCharacters() from npc in this.GetCharacters()
@ -806,7 +806,7 @@ namespace StardewModdingAPI.Metadata
private void ReloadNpcPortraits(LocalizedContentManager content, IEnumerable<string> keys, IDictionary<string, bool> propagated) private void ReloadNpcPortraits(LocalizedContentManager content, IEnumerable<string> keys, IDictionary<string, bool> propagated)
{ {
// get NPCs // get NPCs
HashSet<string> lookup = new HashSet<string>(keys, StringComparer.InvariantCultureIgnoreCase); HashSet<string> lookup = new HashSet<string>(keys, StringComparer.OrdinalIgnoreCase);
var characters = var characters =
( (
from npc in this.GetCharacters() from npc in this.GetCharacters()
@ -1031,7 +1031,7 @@ namespace StardewModdingAPI.Metadata
if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(rawSubstring)) if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(rawSubstring))
return false; return false;
return key.StartsWith(this.NormalizeAssetNameIgnoringEmpty(rawSubstring), StringComparison.InvariantCultureIgnoreCase); return key.StartsWith(this.NormalizeAssetNameIgnoringEmpty(rawSubstring), StringComparison.OrdinalIgnoreCase);
} }
/// <summary>Get whether a normalized asset key is in the given folder.</summary> /// <summary>Get whether a normalized asset key is in the given folder.</summary>

View File

@ -67,7 +67,7 @@ namespace StardewModdingAPI
AssemblyName name = new AssemblyName(e.Name); AssemblyName name = new AssemblyName(e.Name);
foreach (FileInfo dll in new DirectoryInfo(Program.DllSearchPath).EnumerateFiles("*.dll")) foreach (FileInfo dll in new DirectoryInfo(Program.DllSearchPath).EnumerateFiles("*.dll"))
{ {
if (name.Name.Equals(AssemblyName.GetAssemblyName(dll.FullName).Name, StringComparison.InvariantCultureIgnoreCase)) if (name.Name.Equals(AssemblyName.GetAssemblyName(dll.FullName).Name, StringComparison.OrdinalIgnoreCase))
return Assembly.LoadFrom(dll.FullName); return Assembly.LoadFrom(dll.FullName);
} }
return null; return null;

View File

@ -67,7 +67,7 @@ namespace StardewModdingAPI
return this; return this;
// get dictionary of tokens // get dictionary of tokens
IDictionary<string, string> tokenLookup = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase); IDictionary<string, string> tokenLookup = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
{ {
// from dictionary // from dictionary
if (tokens is IDictionary inputLookup) if (tokens is IDictionary inputLookup)