From 33af789e2eb4da101cead531b77c29ecf4933549 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 23 Sep 2017 22:50:35 -0400 Subject: abstract mod IDs with multiple variants (#361) --- .../Framework/Models/ModDataID.cs | 76 +++++++++++++++------- 1 file changed, 52 insertions(+), 24 deletions(-) (limited to 'src/StardewModdingAPI/Framework/Models/ModDataID.cs') diff --git a/src/StardewModdingAPI/Framework/Models/ModDataID.cs b/src/StardewModdingAPI/Framework/Models/ModDataID.cs index 5b45b507..d19434fa 100644 --- a/src/StardewModdingAPI/Framework/Models/ModDataID.cs +++ b/src/StardewModdingAPI/Framework/Models/ModDataID.cs @@ -1,22 +1,28 @@ using System; +using System.Linq; using Newtonsoft.Json; namespace StardewModdingAPI.Framework.Models { /// Uniquely identifies a mod in SMAPI's internal data. + /// + /// This represents a custom format which uniquely identifies a mod across all versions, even + /// if its field values change or it doesn't specify a unique ID. This is mapped to a string + /// with the following format: + /// + /// 1. If the mod's identifier changed over time, multiple variants can be separated by the | + /// 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 three manifest fields (ID, Name, and Author) to match. + /// internal class ModDataID { /********* - ** Accessors + ** Properties *********/ - /// The unique mod ID. - public string ID { get; set; } - - /// The mod name to disambiguate non-unique IDs, or null to ignore the mod name. - public string Name { get; set; } - - /// The author name to disambiguate non-unique IDs, or null to ignore the author. - public string Author { get; set; } + /// The unique sets of field values which identify this mod. + private readonly FieldSnapshot[] Snapshots; /********* @@ -26,17 +32,18 @@ namespace StardewModdingAPI.Framework.Models public ModDataID() { } /// Construct an instance. - /// The mod ID or a JSON string matching the fields. + /// The mod identifier string (see remarks on ). public ModDataID(string data) { - // JSON can be stuffed into the ID string as a convenience hack to keep JSON mod lists - // formatted readably. The tradeoff is that the format is a bit more magical, but that's - // probably acceptable since players aren't meant to edit it. It's also fairly clear what - // the JSON strings do, if not necessarily how. - if (data.StartsWith("{")) - JsonConvert.PopulateObject(data, this); - else - this.ID = data; + this.Snapshots = + ( + from string part in data.Split('|') + let str = part.Trim() + select str.StartsWith("{") + ? JsonConvert.DeserializeObject(str) + : new FieldSnapshot { ID = str } + ) + .ToArray(); } /// Get whether this ID matches a given mod manifest. @@ -44,14 +51,35 @@ namespace StardewModdingAPI.Framework.Models /// The manifest to check. public bool Matches(string id, IManifest manifest) { - return - this.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase) + return this.Snapshots.Any(snapshot => + snapshot.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase) && ( - this.Author == null - || this.Author.Equals(manifest.Author, StringComparison.InvariantCultureIgnoreCase) - || (manifest.ExtraFields.ContainsKey("Authour") && this.Author.Equals(manifest.ExtraFields["Authour"].ToString(), StringComparison.InvariantCultureIgnoreCase)) + snapshot.Author == null + || snapshot.Author.Equals(manifest.Author, StringComparison.InvariantCultureIgnoreCase) + || (manifest.ExtraFields.ContainsKey("Authour") && snapshot.Author.Equals(manifest.ExtraFields["Authour"].ToString(), StringComparison.InvariantCultureIgnoreCase)) ) - && (this.Name == null || this.Name.Equals(manifest.Name, StringComparison.InvariantCultureIgnoreCase)); + && (snapshot.Name == null || snapshot.Name.Equals(manifest.Name, StringComparison.InvariantCultureIgnoreCase)) + ); + } + + + /********* + ** Private models + *********/ + /// A unique set of fields which identifies the mod. + private class FieldSnapshot + { + /********* + ** Accessors + *********/ + /// The unique mod ID. + public string ID { get; set; } + + /// The mod name, or null to ignore the mod name. + public string Name { get; set; } + + /// The author name, or null to ignore the author. + public string Author { get; set; } } } } -- cgit