summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SMAPI.Tests/Core/ModResolverTests.cs4
-rw-r--r--src/SMAPI/Framework/IModMetadata.cs2
-rw-r--r--src/SMAPI/Framework/ModLoading/ModMetadata.cs4
-rw-r--r--src/SMAPI/Framework/ModLoading/ModResolver.cs4
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/ModData/MetadataModel.cs (renamed from src/StardewModdingAPI.Toolkit/Framework/ModData/SMetadata.cs)4
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs129
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs152
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs (renamed from src/StardewModdingAPI.Toolkit/Framework/ModData/ParsedModDataRecord.cs)4
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/ModData/ModDatabase.cs103
-rw-r--r--src/StardewModdingAPI.Toolkit/ModToolkit.cs6
10 files changed, 220 insertions, 192 deletions
diff --git a/src/SMAPI.Tests/Core/ModResolverTests.cs b/src/SMAPI.Tests/Core/ModResolverTests.cs
index e63057b3..9e91b993 100644
--- a/src/SMAPI.Tests/Core/ModResolverTests.cs
+++ b/src/SMAPI.Tests/Core/ModResolverTests.cs
@@ -142,7 +142,7 @@ namespace StardewModdingAPI.Tests.Core
{
// arrange
Mock<IModMetadata> mock = this.GetMetadata("Mod A", new string[0], allowStatusChange: true);
- this.SetupMetadataForValidation(mock, new ParsedModDataRecord
+ this.SetupMetadataForValidation(mock, new ModDataRecordVersionedFields
{
Status = ModStatus.AssumeBroken,
AlternativeUrl = "http://example.org"
@@ -526,7 +526,7 @@ namespace StardewModdingAPI.Tests.Core
/// <summary>Set up a mock mod metadata for <see cref="ModResolver.ValidateManifests"/>.</summary>
/// <param name="mod">The mock mod metadata.</param>
/// <param name="modRecord">The extra metadata about the mod from SMAPI's internal data (if any).</param>
- private void SetupMetadataForValidation(Mock<IModMetadata> mod, ParsedModDataRecord modRecord = null)
+ private void SetupMetadataForValidation(Mock<IModMetadata> mod, ModDataRecordVersionedFields modRecord = null)
{
mod.Setup(p => p.Status).Returns(ModMetadataStatus.Found);
mod.Setup(p => p.DataRecord).Returns(() => null);
diff --git a/src/SMAPI/Framework/IModMetadata.cs b/src/SMAPI/Framework/IModMetadata.cs
index 5a8689de..2145105b 100644
--- a/src/SMAPI/Framework/IModMetadata.cs
+++ b/src/SMAPI/Framework/IModMetadata.cs
@@ -20,7 +20,7 @@ namespace StardewModdingAPI.Framework
IManifest Manifest { get; }
/// <summary>Metadata about the mod from SMAPI's internal data (if any).</summary>
- ParsedModDataRecord DataRecord { get; }
+ ModDataRecordVersionedFields DataRecord { get; }
/// <summary>The metadata resolution status.</summary>
ModMetadataStatus Status { get; }
diff --git a/src/SMAPI/Framework/ModLoading/ModMetadata.cs b/src/SMAPI/Framework/ModLoading/ModMetadata.cs
index 4db25932..585debb4 100644
--- a/src/SMAPI/Framework/ModLoading/ModMetadata.cs
+++ b/src/SMAPI/Framework/ModLoading/ModMetadata.cs
@@ -21,7 +21,7 @@ namespace StardewModdingAPI.Framework.ModLoading
public IManifest Manifest { get; }
/// <summary>Metadata about the mod from SMAPI's internal data (if any).</summary>
- public ParsedModDataRecord DataRecord { get; }
+ public ModDataRecordVersionedFields DataRecord { get; }
/// <summary>The metadata resolution status.</summary>
public ModMetadataStatus Status { get; private set; }
@@ -59,7 +59,7 @@ namespace StardewModdingAPI.Framework.ModLoading
/// <param name="directoryPath">The mod's full directory path.</param>
/// <param name="manifest">The mod manifest.</param>
/// <param name="dataRecord">Metadata about the mod from SMAPI's internal data (if any).</param>
- public ModMetadata(string displayName, string directoryPath, IManifest manifest, ParsedModDataRecord dataRecord)
+ public ModMetadata(string displayName, string directoryPath, IManifest manifest, ModDataRecordVersionedFields dataRecord)
{
this.DisplayName = displayName;
this.DirectoryPath = directoryPath;
diff --git a/src/SMAPI/Framework/ModLoading/ModResolver.cs b/src/SMAPI/Framework/ModLoading/ModResolver.cs
index c1bc51ec..174820a1 100644
--- a/src/SMAPI/Framework/ModLoading/ModResolver.cs
+++ b/src/SMAPI/Framework/ModLoading/ModResolver.cs
@@ -51,7 +51,7 @@ namespace StardewModdingAPI.Framework.ModLoading
}
// parse internal data record (if any)
- ParsedModDataRecord dataRecord = modDatabase.GetParsed(manifest);
+ ModDataRecordVersionedFields dataRecord = modDatabase.Get(manifest?.UniqueID)?.GetVersionedFields(manifest);
// get display name
string displayName = manifest?.Name;
@@ -301,7 +301,7 @@ namespace StardewModdingAPI.Framework.ModLoading
string[] failedModNames = (
from entry in dependencies
where entry.IsRequired && entry.Mod == null
- let displayName = modDatabase.GetDisplayNameFor(entry.ID) ?? entry.ID
+ let displayName = modDatabase.Get(entry.ID)?.DisplayName ?? entry.ID
let modUrl = modDatabase.GetModPageUrlFor(entry.ID)
orderby displayName
select modUrl != null
diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/SMetadata.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/MetadataModel.cs
index 9553cca9..ef6d4dd9 100644
--- a/src/StardewModdingAPI.Toolkit/Framework/ModData/SMetadata.cs
+++ b/src/StardewModdingAPI.Toolkit/Framework/ModData/MetadataModel.cs
@@ -3,12 +3,12 @@ using System.Collections.Generic;
namespace StardewModdingAPI.Toolkit.Framework.ModData
{
/// <summary>The SMAPI predefined metadata.</summary>
- internal class SMetadata
+ internal class MetadataModel
{
/********
** Accessors
********/
/// <summary>Extra metadata about mods.</summary>
- public IDictionary<string, ModDataRecord> ModData { get; set; }
+ public IDictionary<string, ModDataModel> ModData { get; set; }
}
}
diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs
new file mode 100644
index 00000000..e2b3ec1d
--- /dev/null
+++ b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace StardewModdingAPI.Toolkit.Framework.ModData
+{
+ /// <summary>The raw mod metadata from SMAPI's internal mod list.</summary>
+ internal class ModDataModel
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The mod's current unique ID.</summary>
+ public string ID { get; set; }
+
+ /// <summary>The former mod IDs (if any).</summary>
+ /// <remarks>
+ /// This uses a custom format which uniquely identifies a mod across multiple versions and
+ /// supports matching other fields if no ID was specified. This doesn't include the latest
+ /// ID, if any. Format rules:
+ /// 1. If the mod's ID changed over time, multiple variants can be separated by the
+ /// <c>|</c> character.
+ /// 2. Each variant can take one of two forms:
+ /// - A simple string matching the mod's UniqueID value.
+ /// - A JSON structure containing any of four manifest fields (ID, Name, Author, and
+ /// EntryDll) to match.
+ /// </remarks>
+ public string FormerIDs { get; set; }
+
+ /// <summary>Maps local versions to a semantic version for update checks.</summary>
+ public IDictionary<string, string> MapLocalVersions { get; set; } = new Dictionary<string, string>();
+
+ /// <summary>Maps remote versions to a semantic version for update checks.</summary>
+ public IDictionary<string, string> MapRemoteVersions { get; set; } = new Dictionary<string, string>();
+
+ /// <summary>This field stores properties that aren't mapped to another field before they're parsed into <see cref="Fields"/>.</summary>
+ [JsonExtensionData]
+ public IDictionary<string, JToken> ExtensionData { get; set; }
+
+ /// <summary>The versioned field data.</summary>
+ /// <remarks>
+ /// This maps field names to values. This should be accessed via <see cref="GetFields"/>.
+ /// Format notes:
+ /// - Each key consists of a field name prefixed with any combination of version range
+ /// and <c>Default</c>, separated by pipes (whitespace trimmed). For example, <c>Name</c>
+ /// will always override the name, <c>Default | Name</c> will only override a blank
+ /// name, and <c>~1.1 | Default | Name</c> will override blank names up to version 1.1.
+ /// - The version format is <c>min~max</c> (where either side can be blank for unbounded), or
+ /// a single version number.
+ /// - The field name itself corresponds to a <see cref="ModDataFieldKey"/> value.
+ /// </remarks>
+ public IDictionary<string, string> Fields { get; set; } = new Dictionary<string, string>();
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Get a parsed representation of the <see cref="Fields"/>.</summary>
+ public IEnumerable<ModDataField> GetFields()
+ {
+ foreach (KeyValuePair<string, string> pair in this.Fields)
+ {
+ // init fields
+ string packedKey = pair.Key;
+ string value = pair.Value;
+ bool isDefault = false;
+ ISemanticVersion lowerVersion = null;
+ ISemanticVersion upperVersion = null;
+
+ // parse
+ string[] parts = packedKey.Split('|').Select(p => p.Trim()).ToArray();
+ ModDataFieldKey fieldKey = (ModDataFieldKey)Enum.Parse(typeof(ModDataFieldKey), parts.Last(), ignoreCase: true);
+ foreach (string part in parts.Take(parts.Length - 1))
+ {
+ // 'default'
+ if (part.Equals("Default", StringComparison.InvariantCultureIgnoreCase))
+ {
+ isDefault = true;
+ continue;
+ }
+
+ // version range
+ if (part.Contains("~"))
+ {
+ string[] versionParts = part.Split(new[] { '~' }, 2);
+ lowerVersion = versionParts[0] != "" ? new SemanticVersion(versionParts[0]) : null;
+ upperVersion = versionParts[1] != "" ? new SemanticVersion(versionParts[1]) : null;
+ continue;
+ }
+
+ // single version
+ lowerVersion = new SemanticVersion(part);
+ upperVersion = new SemanticVersion(part);
+ }
+
+ yield return new ModDataField(fieldKey, value, isDefault, lowerVersion, upperVersion);
+ }
+ }
+
+ /// <summary>Get the former mod IDs.</summary>
+ public IEnumerable<string> GetFormerIDs()
+ {
+ if (this.FormerIDs != null)
+ {
+ foreach (string id in this.FormerIDs.Split('|'))
+ yield return id.Trim();
+ }
+ }
+
+
+ /*********
+ ** Private methods
+ *********/
+ /// <summary>The method invoked after JSON deserialisation.</summary>
+ /// <param name="context">The deserialisation context.</param>
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext context)
+ {
+ if (this.ExtensionData != null)
+ {
+ this.Fields = this.ExtensionData.ToDictionary(p => p.Key, p => p.Value.ToString());
+ this.ExtensionData = null;
+ }
+ }
+ }
+}
diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs
index 97ad0ca4..21c9cfca 100644
--- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs
+++ b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs
@@ -1,107 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Runtime.Serialization;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
namespace StardewModdingAPI.Toolkit.Framework.ModData
{
- /// <summary>Raw mod metadata from SMAPI's internal mod list.</summary>
+ /// <summary>The parsed mod metadata from SMAPI's internal mod list.</summary>
public class ModDataRecord
{
/*********
- ** Properties
- *********/
- /// <summary>This field stores properties that aren't mapped to another field before they're parsed into <see cref="Fields"/>.</summary>
- [JsonExtensionData]
- private IDictionary<string, JToken> ExtensionData;
-
-
- /*********
** Accessors
*********/
+ /// <summary>The mod's default display name.</summary>
+ public string DisplayName { get; }
+
/// <summary>The mod's current unique ID.</summary>
- public string ID { get; set; }
+ public string ID { get; }
/// <summary>The former mod IDs (if any).</summary>
- /// <remarks>
- /// This uses a custom format which uniquely identifies a mod across multiple versions and
- /// supports matching other fields if no ID was specified. This doesn't include the latest
- /// ID, if any. Format rules:
- /// 1. If the mod's ID changed over time, multiple variants can be separated by the
- /// <c>|</c> character.
- /// 2. Each variant can take one of two forms:
- /// - A simple string matching the mod's UniqueID value.
- /// - A JSON structure containing any of four manifest fields (ID, Name, Author, and
- /// EntryDll) to match.
- /// </remarks>
- public string FormerIDs { get; set; }
+ public string[] FormerIDs { get; }
/// <summary>Maps local versions to a semantic version for update checks.</summary>
- public IDictionary<string, string> MapLocalVersions { get; set; } = new Dictionary<string, string>();
+ public IDictionary<string, string> MapLocalVersions { get; }
/// <summary>Maps remote versions to a semantic version for update checks.</summary>
- public IDictionary<string, string> MapRemoteVersions { get; set; } = new Dictionary<string, string>();
+ public IDictionary<string, string> MapRemoteVersions { get; }
/// <summary>The versioned field data.</summary>
- /// <remarks>
- /// This maps field names to values. This should be accessed via <see cref="GetFields"/>.
- /// Format notes:
- /// - Each key consists of a field name prefixed with any combination of version range
- /// and <c>Default</c>, separated by pipes (whitespace trimmed). For example, <c>Name</c>
- /// will always override the name, <c>Default | Name</c> will only override a blank
- /// name, and <c>~1.1 | Default | Name</c> will override blank names up to version 1.1.
- /// - The version format is <c>min~max</c> (where either side can be blank for unbounded), or
- /// a single version number.
- /// - The field name itself corresponds to a <see cref="ModDataFieldKey"/> value.
- /// </remarks>
- public IDictionary<string, string> Fields { get; set; } = new Dictionary<string, string>();
+ public ModDataField[] Fields { get; }
/*********
** Public methods
*********/
- /// <summary>Get a parsed representation of the <see cref="Fields"/>.</summary>
- public IEnumerable<ModDataField> GetFields()
+ /// <summary>Construct an instance.</summary>
+ /// <param name="displayName">The mod's default display name.</param>
+ /// <param name="model">The raw data model.</param>
+ internal ModDataRecord(string displayName, ModDataModel model)
{
- foreach (KeyValuePair<string, string> pair in this.Fields)
- {
- // init fields
- string packedKey = pair.Key;
- string value = pair.Value;
- bool isDefault = false;
- ISemanticVersion lowerVersion = null;
- ISemanticVersion upperVersion = null;
-
- // parse
- string[] parts = packedKey.Split('|').Select(p => p.Trim()).ToArray();
- ModDataFieldKey fieldKey = (ModDataFieldKey)Enum.Parse(typeof(ModDataFieldKey), parts.Last(), ignoreCase: true);
- foreach (string part in parts.Take(parts.Length - 1))
- {
- // 'default'
- if (part.Equals("Default", StringComparison.InvariantCultureIgnoreCase))
- {
- isDefault = true;
- continue;
- }
-
- // version range
- if (part.Contains("~"))
- {
- string[] versionParts = part.Split(new[] { '~' }, 2);
- lowerVersion = versionParts[0] != "" ? new SemanticVersion(versionParts[0]) : null;
- upperVersion = versionParts[1] != "" ? new SemanticVersion(versionParts[1]) : null;
- continue;
- }
-
- // single version
- lowerVersion = new SemanticVersion(part);
- upperVersion = new SemanticVersion(part);
- }
+ this.DisplayName = displayName;
+ this.ID = model.ID;
+ this.FormerIDs = model.GetFormerIDs().ToArray();
+ this.MapLocalVersions = new Dictionary<string, string>(model.MapLocalVersions, StringComparer.InvariantCultureIgnoreCase);
+ this.MapRemoteVersions = new Dictionary<string, string>(model.MapRemoteVersions, StringComparer.InvariantCultureIgnoreCase);
+ this.Fields = model.GetFields().ToArray();
+ }
- yield return new ModDataField(fieldKey, value, isDefault, lowerVersion, upperVersion);
+ /// <summary>Get whether the mod has (or previously had) the given ID.</summary>
+ /// <param name="id">The mod ID.</param>
+ public bool HasID(string id)
+ {
+ // try main ID
+ if (this.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase))
+ return true;
+
+ // try former IDs
+ foreach (string formerID in this.FormerIDs)
+ {
+ if (formerID.Equals(id, StringComparison.InvariantCultureIgnoreCase))
+ return true;
}
+
+ return false;
}
/// <summary>Get a semantic local version for update checks.</summary>
@@ -127,20 +86,39 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData
: version;
}
-
- /*********
- ** Private methods
- *********/
- /// <summary>The method invoked after JSON deserialisation.</summary>
- /// <param name="context">The deserialisation context.</param>
- [OnDeserialized]
- private void OnDeserialized(StreamingContext context)
+ /// <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)
{
- if (this.ExtensionData != null)
+ ModDataRecordVersionedFields parsed = new ModDataRecordVersionedFields { DisplayName = this.DisplayName, DataRecord = this };
+ foreach (ModDataField field in this.Fields.Where(field => field.IsMatch(manifest)))
{
- this.Fields = this.ExtensionData.ToDictionary(p => p.Key, p => p.Value.ToString());
- this.ExtensionData = null;
+ switch (field.Key)
+ {
+ // update key
+ case ModDataFieldKey.UpdateKey:
+ parsed.UpdateKey = field.Value;
+ break;
+
+ // alternative URL
+ case ModDataFieldKey.AlternativeUrl:
+ parsed.AlternativeUrl = field.Value;
+ break;
+
+ // status
+ case ModDataFieldKey.Status:
+ parsed.Status = (ModStatus)Enum.Parse(typeof(ModStatus), field.Value, ignoreCase: true);
+ parsed.StatusUpperVersion = field.UpperVersion;
+ break;
+
+ // status reason phrase
+ case ModDataFieldKey.StatusReasonPhrase:
+ parsed.StatusReasonPhrase = field.Value;
+ break;
+ }
}
+
+ return parsed;
}
}
}
diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ParsedModDataRecord.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs
index 74f11ea5..3601fc53 100644
--- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ParsedModDataRecord.cs
+++ b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs
@@ -1,7 +1,7 @@
namespace StardewModdingAPI.Toolkit.Framework.ModData
{
- /// <summary>A parsed representation of the fields from a <see cref="ModDataRecord"/> for a specific manifest.</summary>
- public class ParsedModDataRecord
+ /// <summary>The versioned fields from a <see cref="ModDataRecord"/> for a specific manifest.</summary>
+ public class ModDataRecordVersionedFields
{
/*********
** Accessors
diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDatabase.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDatabase.cs
index c60d2bcb..a12e3c67 100644
--- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDatabase.cs
+++ b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDatabase.cs
@@ -11,7 +11,7 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData
** Properties
*********/
/// <summary>The underlying mod data records indexed by default display name.</summary>
- private readonly IDictionary<string, ModDataRecord> Records;
+ private readonly ModDataRecord[] Records;
/// <summary>Get an update URL for an update key (if valid).</summary>
private readonly Func<string, string> GetUpdateUrl;
@@ -22,63 +22,23 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData
*********/
/// <summary>Construct an empty instance.</summary>
public ModDatabase()
- : this(new Dictionary<string, ModDataRecord>(), key => null) { }
+ : this(new ModDataRecord[0], key => null) { }
/// <summary>Construct an instance.</summary>
/// <param name="records">The underlying mod data records indexed by default display name.</param>
/// <param name="getUpdateUrl">Get an update URL for an update key (if valid).</param>
- public ModDatabase(IDictionary<string, ModDataRecord> records, Func<string, string> getUpdateUrl)
+ public ModDatabase(IEnumerable<ModDataRecord> records, Func<string, string> getUpdateUrl)
{
- this.Records = records;
+ this.Records = records.ToArray();
this.GetUpdateUrl = getUpdateUrl;
}
- /// <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 ParsedModDataRecord GetParsed(IManifest manifest)
+ /// <summary>Get a mod data record.</summary>
+ /// <param name="modID">The unique mod ID.</param>
+ public ModDataRecord Get(string modID)
{
- // get raw record
- if (!this.TryGetRaw(manifest?.UniqueID, out string displayName, out ModDataRecord record))
- return null;
-
- // parse fields
- ParsedModDataRecord parsed = new ParsedModDataRecord { DisplayName = displayName, DataRecord = record };
- foreach (ModDataField field in record.GetFields().Where(field => field.IsMatch(manifest)))
- {
- switch (field.Key)
- {
- // update key
- case ModDataFieldKey.UpdateKey:
- parsed.UpdateKey = field.Value;
- break;
-
- // alternative URL
- case ModDataFieldKey.AlternativeUrl:
- parsed.AlternativeUrl = field.Value;
- break;
-
- // status
- case ModDataFieldKey.Status:
- parsed.Status = (ModStatus)Enum.Parse(typeof(ModStatus), field.Value, ignoreCase: true);
- parsed.StatusUpperVersion = field.UpperVersion;
- break;
-
- // status reason phrase
- case ModDataFieldKey.StatusReasonPhrase:
- parsed.StatusReasonPhrase = field.Value;
- break;
- }
- }
-
- return parsed;
- }
-
- /// <summary>Get the display name for a given mod ID (if available).</summary>
- /// <param name="id">The unique mod ID.</param>
- public string GetDisplayNameFor(string id)
- {
- return this.TryGetRaw(id, out string displayName, out ModDataRecord _)
- ? displayName
+ return !string.IsNullOrWhiteSpace(modID)
+ ? this.Records.FirstOrDefault(p => p.HasID(modID))
: null;
}
@@ -86,55 +46,14 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData
/// <param name="id">The unique mod ID.</param>
public string GetModPageUrlFor(string id)
{
- // get raw record
- if (!this.TryGetRaw(id, out string _, out ModDataRecord record))
- return null;
-
// get update key
- ModDataField updateKeyField = record.GetFields().FirstOrDefault(p => p.Key == ModDataFieldKey.UpdateKey);
+ ModDataRecord record = this.Get(id);
+ ModDataField updateKeyField = record?.Fields.FirstOrDefault(p => p.Key == ModDataFieldKey.UpdateKey);
if (updateKeyField == null)
return null;
// get update URL
return this.GetUpdateUrl(updateKeyField.Value);
}
-
-
- /*********
- ** Private models
- *********/
- /// <summary>Get a raw data record.</summary>
- /// <param name="id">The mod ID to match.</param>
- /// <param name="displayName">The mod's default display name.</param>
- /// <param name="record">The raw mod record.</param>
- private bool TryGetRaw(string id, out string displayName, out ModDataRecord record)
- {
- if (!string.IsNullOrWhiteSpace(id))
- {
- foreach (var entry in this.Records)
- {
- displayName = entry.Key;
- record = entry.Value;
-
- // try main ID
- if (record.ID != null && record.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase))
- return true;
-
- // try former IDs
- if (record.FormerIDs != null)
- {
- foreach (string part in record.FormerIDs.Split('|'))
- {
- if (part.Trim().Equals(id, StringComparison.InvariantCultureIgnoreCase))
- return true;
- }
- }
- }
- }
-
- displayName = null;
- record = null;
- return false;
- }
}
}
diff --git a/src/StardewModdingAPI.Toolkit/ModToolkit.cs b/src/StardewModdingAPI.Toolkit/ModToolkit.cs
index 1723991e..7b678f3d 100644
--- a/src/StardewModdingAPI.Toolkit/ModToolkit.cs
+++ b/src/StardewModdingAPI.Toolkit/ModToolkit.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using StardewModdingAPI.Toolkit.Framework.Clients.Wiki;
@@ -48,8 +49,9 @@ namespace StardewModdingAPI.Toolkit
/// <param name="getUpdateUrl">Get an update URL for an update key (if valid).</param>
public ModDatabase GetModDatabase(string metadataPath, Func<string, string> getUpdateUrl)
{
- SMetadata metadata = JsonConvert.DeserializeObject<SMetadata>(File.ReadAllText(metadataPath));
- return new ModDatabase(metadata.ModData, getUpdateUrl);
+ MetadataModel metadata = JsonConvert.DeserializeObject<MetadataModel>(File.ReadAllText(metadataPath));
+ ModDataRecord[] records = metadata.ModData.Select(pair => new ModDataRecord(pair.Key, pair.Value)).ToArray();
+ return new ModDatabase(records, getUpdateUrl);
}
/// <summary>Get an update URL for an update key (if valid).</summary>