summaryrefslogtreecommitdiff
path: root/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2018-06-27 00:40:31 -0400
committerJesse Plamondon-Willard <github@jplamondonw.com>2018-06-27 00:40:31 -0400
commit82306a2c50f4d3df33d8ce62ca49628baf0cc3b7 (patch)
treea266bd5180a59c0730434dff7bb4041f75b6e68e /src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs
parent5f19e4f2035c36f9c6c882da3767d6f29409db1c (diff)
downloadSMAPI-82306a2c50f4d3df33d8ce62ca49628baf0cc3b7.tar.gz
SMAPI-82306a2c50f4d3df33d8ce62ca49628baf0cc3b7.tar.bz2
SMAPI-82306a2c50f4d3df33d8ce62ca49628baf0cc3b7.zip
encapsulate mod DB a bit better for use outside SMAPI (#532)
Diffstat (limited to 'src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs')
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs152
1 files changed, 65 insertions, 87 deletions
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;
}
}
}