summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/release-notes.md1
-rw-r--r--src/SMAPI.Web/Controllers/ModsApiController.cs53
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs9
3 files changed, 49 insertions, 14 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 6af726a1..12feb68a 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -4,6 +4,7 @@
* Added support for subfolders under `Mods`, for players who want to organise their mods.
* Moved most SMAPI files into a `smapi-internal` subfolder.
* Moved save backups into a `save-backups` subfolder (instead of `Mods/SaveBackup/backups`). Note that previous backups will be deleted when you update.
+ * Update checks now work even when the mod has no update keys in most cases.
* Fixed installer duplicating bundled mods if you moved them after the last install.
* Fixed crash when a mod manifest is corrupted.
* Fixed error-handling when initialising paths.
diff --git a/src/SMAPI.Web/Controllers/ModsApiController.cs b/src/SMAPI.Web/Controllers/ModsApiController.cs
index 18d55665..3d05da16 100644
--- a/src/SMAPI.Web/Controllers/ModsApiController.cs
+++ b/src/SMAPI.Web/Controllers/ModsApiController.cs
@@ -115,15 +115,10 @@ namespace StardewModdingAPI.Web.Controllers
/// <returns>Returns the mod data if found, else <c>null</c>.</returns>
private async Task<ModEntryModel> GetModData(ModSearchEntryModel search, WikiCompatibilityEntry[] wikiData, bool includeExtendedMetadata)
{
- // resolve update keys
- var updateKeys = new HashSet<string>(search.UpdateKeys ?? new string[0], StringComparer.InvariantCultureIgnoreCase);
+ // crossreference data
ModDataRecord record = this.ModDatabase.Get(search.ID);
- if (record?.Fields != null)
- {
- string defaultUpdateKey = record.Fields.FirstOrDefault(p => p.Key == ModDataFieldKey.UpdateKey && p.IsDefault)?.Value;
- if (!string.IsNullOrWhiteSpace(defaultUpdateKey))
- updateKeys.Add(defaultUpdateKey);
- }
+ WikiCompatibilityEntry wikiEntry = wikiData.FirstOrDefault(entry => entry.ID.Contains(search.ID.Trim(), StringComparer.InvariantCultureIgnoreCase));
+ string[] updateKeys = this.GetUpdateKeys(search.UpdateKeys, record, wikiEntry).ToArray();
// get latest versions
ModEntryModel result = new ModEntryModel { ID = search.ID };
@@ -166,7 +161,6 @@ namespace StardewModdingAPI.Web.Controllers
}
// get unofficial version
- WikiCompatibilityEntry wikiEntry = wikiData.FirstOrDefault(entry => entry.ID.Contains(result.ID.Trim(), StringComparer.InvariantCultureIgnoreCase));
if (wikiEntry?.UnofficialVersion != null && this.IsNewer(wikiEntry.UnofficialVersion, result.Main?.Version) && this.IsNewer(wikiEntry.UnofficialVersion, result.Optional?.Version))
result.Unofficial = new ModEntryVersionModel(wikiEntry.UnofficialVersion, this.WikiCompatibilityPageUrl);
@@ -229,7 +223,7 @@ namespace StardewModdingAPI.Web.Controllers
private async Task<WikiCompatibilityEntry[]> GetWikiDataAsync()
{
ModToolkit toolkit = new ModToolkit();
- return await this.Cache.GetOrCreateAsync($"_wiki", async entry =>
+ return await this.Cache.GetOrCreateAsync("_wiki", async entry =>
{
try
{
@@ -273,11 +267,42 @@ namespace StardewModdingAPI.Web.Controllers
});
}
- /// <summary>Get the requested API version.</summary>
- private ISemanticVersion GetApiVersion()
+ /// <summary>Get update keys based on the available mod metadata, while maintaining the precedence order.</summary>
+ /// <param name="specifiedKeys">The specified update keys.</param>
+ /// <param name="record">The mod's entry in SMAPI's internal database.</param>
+ /// <param name="entry">The mod's entry in the wiki list.</param>
+ public IEnumerable<string> GetUpdateKeys(string[] specifiedKeys, ModDataRecord record, WikiCompatibilityEntry entry)
{
- string actualVersion = (string)this.RouteData.Values["version"];
- return new SemanticVersion(actualVersion);
+ IEnumerable<string> GetRaw()
+ {
+ // specified update keys
+ if (specifiedKeys != null)
+ {
+ foreach (string key in specifiedKeys)
+ yield return key?.Trim();
+ }
+
+ // default update key
+ string defaultKey = record?.GetDefaultUpdateKey();
+ if (defaultKey != null)
+ yield return defaultKey;
+
+ // wiki metadata
+ if (entry != null)
+ {
+ if (entry.NexusID.HasValue)
+ yield return $"Nexus:{entry.NexusID}";
+ if (entry.ChucklefishID.HasValue)
+ yield return $"Chucklefish:{entry.ChucklefishID}";
+ }
+ }
+
+ HashSet<string> seen = new HashSet<string>(StringComparer.InvariantCulture);
+ foreach (string key in GetRaw())
+ {
+ if (!string.IsNullOrWhiteSpace(key) && seen.Add(key))
+ yield return key;
+ }
}
}
}
diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs
index 82ac8837..3949f7dc 100644
--- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs
+++ b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs
@@ -96,6 +96,15 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData
.Distinct();
}
+ /// <summary>Get the default update key for this mod, if any.</summary>
+ public string GetDefaultUpdateKey()
+ {
+ string updateKey = this.Fields.FirstOrDefault(p => p.Key == ModDataFieldKey.UpdateKey && p.IsDefault)?.Value;
+ return !string.IsNullOrWhiteSpace(updateKey)
+ ? updateKey
+ : null;
+ }
+
/// <summary>Get a parsed representation of the <see cref="ModDataRecord.Fields"/> which match a given manifest.</summary>
/// <param name="manifest">The manifest to match.</param>
public ModDataRecordVersionedFields GetVersionedFields(IManifest manifest)