summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/release-notes.md1
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs2
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs3
-rw-r--r--src/SMAPI.Web/Controllers/ModsApiController.cs103
4 files changed, 69 insertions, 40 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 5813298d..90835fa3 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -16,6 +16,7 @@
* Migrated to Harmony 2.0 (see [_migrate to Harmony 2.0_](https://stardewvalleywiki.com/Modding:Migrate_to_Harmony_2.0) for more info).
* Added [update subkeys](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Update_checks#Update_subkeys).
* Added `Multiplayer.PeerConnected` event.
+ * Added ability to override update keys from the compatibility list.
* Added `harmony_summary` console command which lists all current Harmony patches, optionally with a search filter.
* Harmony mods which use the `[HarmonyPatch(type)]` attribute now work crossplatform. Previously SMAPI couldn't rewrite types in custom attributes for compatibility.
* Improved mod rewriting for compatibility:
diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
index c829c0f4..34e2e1b8 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
@@ -105,6 +105,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
string pullRequestUrl = this.GetAttribute(node, "data-pr");
IDictionary<string, string> mapLocalVersions = this.GetAttributeAsVersionMapping(node, "data-map-local-versions");
IDictionary<string, string> mapRemoteVersions = this.GetAttributeAsVersionMapping(node, "data-map-remote-versions");
+ string[] changeUpdateKeys = this.GetAttributeAsCsv(node, "data-change-update-keys");
// parse stable compatibility
WikiCompatibilityInfo compatibility = new WikiCompatibilityInfo
@@ -153,6 +154,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
Warnings = warnings,
PullRequestUrl = pullRequestUrl,
DevNote = devNote,
+ ChangeUpdateKeys = changeUpdateKeys,
MapLocalVersions = mapLocalVersions,
MapRemoteVersions = mapRemoteVersions,
Anchor = anchor
diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
index 474dce3d..21466c6a 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
@@ -63,6 +63,9 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <summary>Special notes intended for developers who maintain unofficial updates or submit pull requests. </summary>
public string DevNote { get; set; }
+ /// <summary>Update keys to add (optionally prefixed by '+') or remove (prefixed by '-').</summary>
+ public string[] ChangeUpdateKeys { get; set; }
+
/// <summary>Maps local versions to a semantic version for update checks.</summary>
public IDictionary<string, string> MapLocalVersions { get; set; }
diff --git a/src/SMAPI.Web/Controllers/ModsApiController.cs b/src/SMAPI.Web/Controllers/ModsApiController.cs
index 028fc613..db669bf9 100644
--- a/src/SMAPI.Web/Controllers/ModsApiController.cs
+++ b/src/SMAPI.Web/Controllers/ModsApiController.cs
@@ -280,56 +280,79 @@ namespace StardewModdingAPI.Web.Controllers
/// <param name="entry">The mod's entry in the wiki list.</param>
private IEnumerable<UpdateKey> GetUpdateKeys(string[] specifiedKeys, ModDataRecord record, WikiModEntry entry)
{
- // get every update key (including duplicates)
- IEnumerable<string> GetRaw()
+ // get unique update keys
+ List<UpdateKey> updateKeys = this.GetUnfilteredUpdateKeys(specifiedKeys, record, entry)
+ .Select(UpdateKey.Parse)
+ .Distinct()
+ .ToList();
+
+ // apply remove overrides from wiki
+ {
+ var removeKeys = new HashSet<UpdateKey>(
+ from key in entry?.ChangeUpdateKeys ?? new string[0]
+ where key.StartsWith('-')
+ select UpdateKey.Parse(key.Substring(1))
+ );
+ if (removeKeys.Any())
+ updateKeys.RemoveAll(removeKeys.Contains);
+ }
+
+ // if the list has both an update key (like "Nexus:2400") and subkey (like "Nexus:2400@subkey") for the same page, the subkey takes priority
{
- // specified update keys
- if (specifiedKeys != null)
+ var removeKeys = new HashSet<UpdateKey>();
+ foreach (var key in updateKeys)
{
- foreach (string key in specifiedKeys)
- {
- if (!string.IsNullOrWhiteSpace(key))
- yield return key.Trim();
- }
+ if (key.Subkey != null)
+ removeKeys.Add(new UpdateKey(key.Site, key.ID, null));
}
+ if (removeKeys.Any())
+ updateKeys.RemoveAll(removeKeys.Contains);
+ }
+
+ return updateKeys;
+ }
+
+ /// <summary>Get every available update key based on the available mod metadata, including duplicates and keys which should be filtered.</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>
+ private IEnumerable<string> GetUnfilteredUpdateKeys(string[] specifiedKeys, ModDataRecord record, WikiModEntry entry)
+ {
+ // specified update keys
+ foreach (string key in specifiedKeys ?? Array.Empty<string>())
+ {
+ if (!string.IsNullOrWhiteSpace(key))
+ yield return key.Trim();
+ }
- // default update key
+ // default update key
+ {
string defaultKey = record?.GetDefaultUpdateKey();
if (!string.IsNullOrWhiteSpace(defaultKey))
yield return defaultKey;
-
- // wiki metadata
- if (entry != null)
- {
- if (entry.NexusID.HasValue)
- yield return UpdateKey.GetString(ModSiteKey.Nexus, entry.NexusID.ToString());
- if (entry.ModDropID.HasValue)
- yield return UpdateKey.GetString(ModSiteKey.ModDrop, entry.ModDropID.ToString());
- if (entry.CurseForgeID.HasValue)
- yield return UpdateKey.GetString(ModSiteKey.CurseForge, entry.CurseForgeID.ToString());
- if (entry.ChucklefishID.HasValue)
- yield return UpdateKey.GetString(ModSiteKey.Chucklefish, entry.ChucklefishID.ToString());
- }
}
- // get unique update keys
- var subkeyRoots = new HashSet<UpdateKey>();
- List<UpdateKey> updateKeys = GetRaw()
- .Select(raw =>
- {
- var key = UpdateKey.Parse(raw);
- if (key.Subkey != null)
- subkeyRoots.Add(new UpdateKey(key.Site, key.ID, null));
- return key;
- })
- .Distinct()
- .ToList();
-
- // if the list has both an update key (like "Nexus:2400") and subkey (like "Nexus:2400@subkey") for the same page, the subkey takes priority
- if (subkeyRoots.Any())
- updateKeys.RemoveAll(subkeyRoots.Contains);
+ // wiki metadata
+ if (entry != null)
+ {
+ if (entry.NexusID.HasValue)
+ yield return UpdateKey.GetString(ModSiteKey.Nexus, entry.NexusID.ToString());
+ if (entry.ModDropID.HasValue)
+ yield return UpdateKey.GetString(ModSiteKey.ModDrop, entry.ModDropID.ToString());
+ if (entry.CurseForgeID.HasValue)
+ yield return UpdateKey.GetString(ModSiteKey.CurseForge, entry.CurseForgeID.ToString());
+ if (entry.ChucklefishID.HasValue)
+ yield return UpdateKey.GetString(ModSiteKey.Chucklefish, entry.ChucklefishID.ToString());
+ }
- return updateKeys;
+ // overrides from wiki
+ foreach (string key in entry?.ChangeUpdateKeys ?? Array.Empty<string>())
+ {
+ if (key.StartsWith('+'))
+ yield return key.Substring(1);
+ else if (!key.StartsWith("-"))
+ yield return key;
+ }
}
}
}