From 125bcbee56bf40cf82abc7fdb502f8cbc18546cf Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 13 Sep 2019 17:22:45 -0400 Subject: migrate to new project file format --- .../Framework/Clients/WebApi/ModEntryModel.cs | 33 --- .../Clients/WebApi/ModEntryVersionModel.cs | 31 --- .../Clients/WebApi/ModExtendedMetadataModel.cs | 123 ----------- .../Framework/Clients/WebApi/ModSeachModel.cs | 36 ---- .../Clients/WebApi/ModSearchEntryModel.cs | 34 --- .../Framework/Clients/WebApi/WebApiClient.cs | 73 ------- .../Framework/Clients/Wiki/WikiClient.cs | 237 --------------------- .../Clients/Wiki/WikiCompatibilityInfo.cs | 24 --- .../Clients/Wiki/WikiCompatibilityStatus.cs | 27 --- .../Framework/Clients/Wiki/WikiModEntry.cs | 54 ----- .../Framework/Clients/Wiki/WikiModList.cs | 18 -- .../Framework/ModData/MetadataModel.cs | 14 -- .../Framework/ModData/ModDataField.cs | 82 ------- .../Framework/ModData/ModDataFieldKey.cs | 18 -- .../Framework/ModData/ModDataModel.cs | 127 ----------- .../Framework/ModData/ModDataRecord.cs | 147 ------------- .../ModData/ModDataRecordVersionedFields.cs | 54 ----- .../Framework/ModData/ModDatabase.cs | 65 ------ .../Framework/ModData/ModStatus.cs | 18 -- .../Framework/ModData/ModWarning.cs | 36 ---- .../Framework/ModScanning/ModFolder.cs | 64 ------ .../Framework/ModScanning/ModScanner.cs | 183 ---------------- .../Framework/UpdateData/ModRepositoryKey.cs | 21 -- .../Framework/UpdateData/UpdateKey.cs | 73 ------- 24 files changed, 1592 deletions(-) delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryVersionModel.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSearchEntryModel.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityStatus.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModList.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/ModData/MetadataModel.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataField.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataFieldKey.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/ModData/ModDatabase.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/ModData/ModStatus.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/ModData/ModWarning.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/ModScanning/ModFolder.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/ModScanning/ModScanner.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/UpdateData/ModRepositoryKey.cs delete mode 100644 src/StardewModdingAPI.Toolkit/Framework/UpdateData/UpdateKey.cs (limited to 'src/StardewModdingAPI.Toolkit/Framework') diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs deleted file mode 100644 index 8a9c0a25..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi -{ - /// Metadata about a mod. - public class ModEntryModel - { - /********* - ** Accessors - *********/ - /// The mod's unique ID (if known). - public string ID { get; set; } - - /// The main version. - public ModEntryVersionModel Main { get; set; } - - /// The latest optional version, if newer than . - public ModEntryVersionModel Optional { get; set; } - - /// The latest unofficial version, if newer than and . - public ModEntryVersionModel Unofficial { get; set; } - - /// The latest unofficial version for the current Stardew Valley or SMAPI beta, if any (see ). - public ModEntryVersionModel UnofficialForBeta { get; set; } - - /// Optional extended data which isn't needed for update checks. - public ModExtendedMetadataModel Metadata { get; set; } - - /// Whether a Stardew Valley or SMAPI beta which affects mod compatibility is in progress. If this is true, should be used for beta versions of SMAPI instead of . - public bool HasBetaInfo { get; set; } - - /// The errors that occurred while fetching update data. - public string[] Errors { get; set; } = new string[0]; - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryVersionModel.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryVersionModel.cs deleted file mode 100644 index dadb8c10..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryVersionModel.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi -{ - /// Metadata about a version. - public class ModEntryVersionModel - { - /********* - ** Accessors - *********/ - /// The version number. - public ISemanticVersion Version { get; set; } - - /// The mod page URL. - public string Url { get; set; } - - - /********* - ** Public methods - *********/ - /// Construct an instance. - public ModEntryVersionModel() { } - - /// Construct an instance. - /// The version number. - /// The mod page URL. - public ModEntryVersionModel(ISemanticVersion version, string url) - { - this.Version = version; - this.Url = url; - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs deleted file mode 100644 index 989c18b0..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using StardewModdingAPI.Toolkit.Framework.Clients.Wiki; -using StardewModdingAPI.Toolkit.Framework.ModData; - -namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi -{ - /// Extended metadata about a mod. - public class ModExtendedMetadataModel - { - /********* - ** Accessors - *********/ - /**** - ** Mod info - ****/ - /// The mod's unique ID. A mod may have multiple current IDs in rare cases (e.g. due to parallel releases or unofficial updates). - public string[] ID { get; set; } = new string[0]; - - /// The mod's display name. - public string Name { get; set; } - - /// The mod ID on Nexus. - public int? NexusID { get; set; } - - /// The mod ID in the Chucklefish mod repo. - public int? ChucklefishID { get; set; } - - /// The mod ID in the ModDrop mod repo. - public int? ModDropID { get; set; } - - /// The GitHub repository in the form 'owner/repo'. - public string GitHubRepo { get; set; } - - /// The URL to a non-GitHub source repo. - public string CustomSourceUrl { get; set; } - - /// The custom mod page URL (if applicable). - public string CustomUrl { get; set; } - - - /**** - ** Stable compatibility - ****/ - /// The compatibility status. - [JsonConverter(typeof(StringEnumConverter))] - public WikiCompatibilityStatus? CompatibilityStatus { get; set; } - - /// The human-readable summary of the compatibility status or workaround, without HTML formatitng. - public string CompatibilitySummary { get; set; } - - /// The game or SMAPI version which broke this mod, if applicable. - public string BrokeIn { get; set; } - - - /**** - ** Beta compatibility - ****/ - /// The compatibility status for the Stardew Valley beta (if any). - [JsonConverter(typeof(StringEnumConverter))] - public WikiCompatibilityStatus? BetaCompatibilityStatus { get; set; } - - /// The human-readable summary of the compatibility status or workaround for the Stardew Valley beta (if any), without HTML formatitng. - public string BetaCompatibilitySummary { get; set; } - - /// The beta game or SMAPI version which broke this mod, if applicable. - public string BetaBrokeIn { get; set; } - - - /********* - ** Public methods - *********/ - /// Construct an instance. - public ModExtendedMetadataModel() { } - - /// Construct an instance. - /// The mod metadata from the wiki (if available). - /// The mod metadata from SMAPI's internal DB (if available). - public ModExtendedMetadataModel(WikiModEntry wiki, ModDataRecord db) - { - // wiki data - if (wiki != null) - { - this.ID = wiki.ID; - this.Name = wiki.Name.FirstOrDefault(); - this.NexusID = wiki.NexusID; - this.ChucklefishID = wiki.ChucklefishID; - this.ModDropID = wiki.ModDropID; - this.GitHubRepo = wiki.GitHubRepo; - this.CustomSourceUrl = wiki.CustomSourceUrl; - this.CustomUrl = wiki.CustomUrl; - - this.CompatibilityStatus = wiki.Compatibility.Status; - this.CompatibilitySummary = wiki.Compatibility.Summary; - this.BrokeIn = wiki.Compatibility.BrokeIn; - - this.BetaCompatibilityStatus = wiki.BetaCompatibility?.Status; - this.BetaCompatibilitySummary = wiki.BetaCompatibility?.Summary; - this.BetaBrokeIn = wiki.BetaCompatibility?.BrokeIn; - } - - // internal DB data - if (db != null) - { - this.ID = this.ID.Union(db.FormerIDs).ToArray(); - this.Name = this.Name ?? db.DisplayName; - } - } - - /// Get update keys based on the metadata. - public IEnumerable GetUpdateKeys() - { - if (this.NexusID.HasValue) - yield return $"Nexus:{this.NexusID}"; - if (this.ChucklefishID.HasValue) - yield return $"Chucklefish:{this.ChucklefishID}"; - if (this.GitHubRepo != null) - yield return $"GitHub:{this.GitHubRepo}"; - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs deleted file mode 100644 index e352e1cc..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Linq; - -namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi -{ - /// Specifies mods whose update-check info to fetch. - public class ModSearchModel - { - /********* - ** Accessors - *********/ - /// The mods for which to find data. - public ModSearchEntryModel[] Mods { get; set; } - - /// Whether to include extended metadata for each mod. - public bool IncludeExtendedMetadata { get; set; } - - - /********* - ** Public methods - *********/ - /// Construct an empty instance. - public ModSearchModel() - { - // needed for JSON deserialising - } - - /// Construct an instance. - /// The mods to search. - /// Whether to include extended metadata for each mod. - public ModSearchModel(ModSearchEntryModel[] mods, bool includeExtendedMetadata) - { - this.Mods = mods.ToArray(); - this.IncludeExtendedMetadata = includeExtendedMetadata; - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSearchEntryModel.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSearchEntryModel.cs deleted file mode 100644 index bca47647..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSearchEntryModel.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi -{ - /// Specifies the identifiers for a mod to match. - public class ModSearchEntryModel - { - /********* - ** Accessors - *********/ - /// The unique mod ID. - public string ID { get; set; } - - /// The namespaced mod update keys (if available). - public string[] UpdateKeys { get; set; } - - - /********* - ** Public methods - *********/ - /// Construct an empty instance. - public ModSearchEntryModel() - { - // needed for JSON deserialising - } - - /// Construct an instance. - /// The unique mod ID. - /// The namespaced mod update keys (if available). - public ModSearchEntryModel(string id, string[] updateKeys) - { - this.ID = id; - this.UpdateKeys = updateKeys ?? new string[0]; - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs deleted file mode 100644 index 7c3df384..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Newtonsoft.Json; -using StardewModdingAPI.Toolkit.Serialisation; - -namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi -{ - /// Provides methods for interacting with the SMAPI web API. - public class WebApiClient - { - /********* - ** Fields - *********/ - /// The base URL for the web API. - private readonly Uri BaseUrl; - - /// The API version number. - private readonly ISemanticVersion Version; - - /// The JSON serializer settings to use. - private readonly JsonSerializerSettings JsonSettings = new JsonHelper().JsonSettings; - - - /********* - ** Public methods - *********/ - /// Construct an instance. - /// The base URL for the web API. - /// The web API version. - public WebApiClient(string baseUrl, ISemanticVersion version) - { - this.BaseUrl = new Uri(baseUrl); - this.Version = version; - } - - /// Get metadata about a set of mods from the web API. - /// The mod keys for which to fetch the latest version. - /// Whether to include extended metadata for each mod. - public IDictionary GetModInfo(ModSearchEntryModel[] mods, bool includeExtendedMetadata = false) - { - return this.Post( - $"v{this.Version}/mods", - new ModSearchModel(mods, includeExtendedMetadata) - ).ToDictionary(p => p.ID); - } - - - /********* - ** Private methods - *********/ - /// Fetch the response from the backend API. - /// The body content type. - /// The expected response type. - /// The request URL, optionally excluding the base URL. - /// The body content to post. - private TResult Post(string url, TBody content) - { - // note: avoid HttpClient for Mac compatibility - using (WebClient client = new WebClient()) - { - Uri fullUrl = new Uri(this.BaseUrl, url); - string data = JsonConvert.SerializeObject(content); - - client.Headers["Content-Type"] = "application/json"; - client.Headers["User-Agent"] = $"SMAPI/{this.Version}"; - string response = client.UploadString(fullUrl, data); - return JsonConvert.DeserializeObject(response, this.JsonSettings); - } - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs deleted file mode 100644 index 3e9b8ea6..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs +++ /dev/null @@ -1,237 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using HtmlAgilityPack; -using Pathoschild.Http.Client; - -namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki -{ - /// An HTTP client for fetching mod metadata from the wiki. - public class WikiClient : IDisposable - { - /********* - ** Fields - *********/ - /// The underlying HTTP client. - private readonly IClient Client; - - - /********* - ** Public methods - *********/ - /// Construct an instance. - /// The user agent for the wiki API. - /// The base URL for the wiki API. - public WikiClient(string userAgent, string baseUrl = "https://stardewvalleywiki.com/mediawiki/api.php") - { - this.Client = new FluentClient(baseUrl).SetUserAgent(userAgent); - } - - /// Fetch mods from the compatibility list. - public async Task FetchModsAsync() - { - // fetch HTML - ResponseModel response = await this.Client - .GetAsync("") - .WithArguments(new - { - action = "parse", - page = "Modding:Mod_compatibility", - format = "json" - }) - .As(); - string html = response.Parse.Text["*"]; - - // parse HTML - var doc = new HtmlDocument(); - doc.LoadHtml(html); - - // fetch game versions - string stableVersion = doc.DocumentNode.SelectSingleNode("div[@class='game-stable-version']")?.InnerText; - string betaVersion = doc.DocumentNode.SelectSingleNode("div[@class='game-beta-version']")?.InnerText; - if (betaVersion == stableVersion) - betaVersion = null; - - // find mod entries - HtmlNodeCollection modNodes = doc.DocumentNode.SelectNodes("table[@id='mod-list']//tr[@class='mod']"); - if (modNodes == null) - throw new InvalidOperationException("Can't parse wiki compatibility list, no mods found."); - - // parse - WikiModEntry[] mods = this.ParseEntries(modNodes).ToArray(); - return new WikiModList - { - StableVersion = stableVersion, - BetaVersion = betaVersion, - Mods = mods - }; - } - - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - public void Dispose() - { - this.Client?.Dispose(); - } - - - /********* - ** Private methods - *********/ - /// Parse valid mod compatibility entries. - /// The HTML compatibility entries. - private IEnumerable ParseEntries(IEnumerable nodes) - { - foreach (HtmlNode node in nodes) - { - // extract fields - string[] names = this.GetAttributeAsCsv(node, "data-name"); - string[] authors = this.GetAttributeAsCsv(node, "data-author"); - string[] ids = this.GetAttributeAsCsv(node, "data-id"); - string[] warnings = this.GetAttributeAsCsv(node, "data-warnings"); - int? nexusID = this.GetAttributeAsNullableInt(node, "data-nexus-id"); - int? chucklefishID = this.GetAttributeAsNullableInt(node, "data-cf-id"); - int? modDropID = this.GetAttributeAsNullableInt(node, "data-moddrop-id"); - string githubRepo = this.GetAttribute(node, "data-github"); - string customSourceUrl = this.GetAttribute(node, "data-custom-source"); - string customUrl = this.GetAttribute(node, "data-url"); - string anchor = this.GetAttribute(node, "id"); - string contentPackFor = this.GetAttribute(node, "data-content-pack-for"); - - // parse stable compatibility - WikiCompatibilityInfo compatibility = new WikiCompatibilityInfo - { - Status = this.GetAttributeAsEnum(node, "data-status") ?? WikiCompatibilityStatus.Ok, - BrokeIn = this.GetAttribute(node, "data-broke-in"), - UnofficialVersion = this.GetAttributeAsSemanticVersion(node, "data-unofficial-version"), - UnofficialUrl = this.GetAttribute(node, "data-unofficial-url"), - Summary = this.GetInnerHtml(node, "mod-summary")?.Trim() - }; - - // parse beta compatibility - WikiCompatibilityInfo betaCompatibility = null; - { - WikiCompatibilityStatus? betaStatus = this.GetAttributeAsEnum(node, "data-beta-status"); - if (betaStatus.HasValue) - { - betaCompatibility = new WikiCompatibilityInfo - { - Status = betaStatus.Value, - BrokeIn = this.GetAttribute(node, "data-beta-broke-in"), - UnofficialVersion = this.GetAttributeAsSemanticVersion(node, "data-beta-unofficial-version"), - UnofficialUrl = this.GetAttribute(node, "data-beta-unofficial-url"), - Summary = this.GetInnerHtml(node, "mod-beta-summary") - }; - } - } - - // yield model - yield return new WikiModEntry - { - ID = ids, - Name = names, - Author = authors, - NexusID = nexusID, - ChucklefishID = chucklefishID, - ModDropID = modDropID, - GitHubRepo = githubRepo, - CustomSourceUrl = customSourceUrl, - CustomUrl = customUrl, - ContentPackFor = contentPackFor, - Compatibility = compatibility, - BetaCompatibility = betaCompatibility, - Warnings = warnings, - Anchor = anchor - }; - } - } - - /// Get an attribute value. - /// The element whose attributes to read. - /// The attribute name. - private string GetAttribute(HtmlNode element, string name) - { - string value = element.GetAttributeValue(name, null); - if (string.IsNullOrWhiteSpace(value)) - return null; - - return WebUtility.HtmlDecode(value); - } - - /// Get an attribute value and parse it as a comma-delimited list of strings. - /// The element whose attributes to read. - /// The attribute name. - private string[] GetAttributeAsCsv(HtmlNode element, string name) - { - string raw = this.GetAttribute(element, name); - return !string.IsNullOrWhiteSpace(raw) - ? raw.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim()).ToArray() - : new string[0]; - } - - /// Get an attribute value and parse it as an enum value. - /// The enum type. - /// The element whose attributes to read. - /// The attribute name. - private TEnum? GetAttributeAsEnum(HtmlNode element, string name) where TEnum : struct - { - string raw = this.GetAttribute(element, name); - if (raw == null) - return null; - if (!Enum.TryParse(raw, true, out TEnum value) && Enum.IsDefined(typeof(TEnum), value)) - throw new InvalidOperationException($"Unknown {typeof(TEnum).Name} value '{raw}' when parsing compatibility list."); - return value; - } - - /// Get an attribute value and parse it as a semantic version. - /// The element whose attributes to read. - /// The attribute name. - private ISemanticVersion GetAttributeAsSemanticVersion(HtmlNode element, string name) - { - string raw = this.GetAttribute(element, name); - return SemanticVersion.TryParse(raw, out ISemanticVersion version) - ? version - : null; - } - - /// Get an attribute value and parse it as a nullable int. - /// The element whose attributes to read. - /// The attribute name. - private int? GetAttributeAsNullableInt(HtmlNode element, string name) - { - string raw = this.GetAttribute(element, name); - if (raw != null && int.TryParse(raw, out int value)) - return value; - return null; - } - - /// Get the text of an element with the given class name. - /// The metadata container. - /// The field name. - private string GetInnerHtml(HtmlNode container, string className) - { - return container.Descendants().FirstOrDefault(p => p.HasClass(className))?.InnerHtml; - } - - /// The response model for the MediaWiki parse API. - [SuppressMessage("ReSharper", "ClassNeverInstantiated.Local")] - [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")] - private class ResponseModel - { - /// The parse API results. - public ResponseParseModel Parse { get; set; } - } - - /// The inner response model for the MediaWiki parse API. - [SuppressMessage("ReSharper", "ClassNeverInstantiated.Local")] - [SuppressMessage("ReSharper", "CollectionNeverUpdated.Local")] - [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")] - private class ResponseParseModel - { - /// The parsed text. - public IDictionary Text { get; set; } - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs deleted file mode 100644 index 204acd2b..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki -{ - /// Compatibility info for a mod. - public class WikiCompatibilityInfo - { - /********* - ** Accessors - *********/ - /// The compatibility status. - public WikiCompatibilityStatus Status { get; set; } - - /// The human-readable summary of the compatibility status or workaround, without HTML formatting. - public string Summary { get; set; } - - /// The game or SMAPI version which broke this mod (if applicable). - public string BrokeIn { get; set; } - - /// The version of the latest unofficial update, if applicable. - public ISemanticVersion UnofficialVersion { get; set; } - - /// The URL to the latest unofficial update, if applicable. - public string UnofficialUrl { get; set; } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityStatus.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityStatus.cs deleted file mode 100644 index a1d2dfae..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityStatus.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki -{ - /// The compatibility status for a mod. - public enum WikiCompatibilityStatus - { - /// The mod is compatible. - Ok = 0, - - /// The mod is compatible if you use an optional official download. - Optional = 1, - - /// The mod is compatible if you use an unofficial update. - Unofficial = 2, - - /// The mod isn't compatible, but the player can fix it or there's a good alternative. - Workaround = 3, - - /// The mod isn't compatible. - Broken = 4, - - /// The mod is no longer maintained by the author, and an unofficial update or continuation is unlikely. - Abandoned = 5, - - /// The mod is no longer needed and should be removed. - Obsolete = 6 - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs deleted file mode 100644 index cf416cc6..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki -{ - /// A mod entry in the wiki list. - public class WikiModEntry - { - /********* - ** Accessors - *********/ - /// The mod's unique ID. If the mod has alternate/old IDs, they're listed in latest to newest order. - public string[] ID { get; set; } - - /// The mod's display name. If the mod has multiple names, the first one is the most canonical name. - public string[] Name { get; set; } - - /// The mod's author name. If the author has multiple names, the first one is the most canonical name. - public string[] Author { get; set; } - - /// The mod ID on Nexus. - public int? NexusID { get; set; } - - /// The mod ID in the Chucklefish mod repo. - public int? ChucklefishID { get; set; } - - /// The mod ID in the ModDrop mod repo. - public int? ModDropID { get; set; } - - /// The GitHub repository in the form 'owner/repo'. - public string GitHubRepo { get; set; } - - /// The URL to a non-GitHub source repo. - public string CustomSourceUrl { get; set; } - - /// The custom mod page URL (if applicable). - public string CustomUrl { get; set; } - - /// The name of the mod which loads this content pack, if applicable. - public string ContentPackFor { get; set; } - - /// The mod's compatibility with the latest stable version of the game. - public WikiCompatibilityInfo Compatibility { get; set; } - - /// The mod's compatibility with the latest beta version of the game (if any). - public WikiCompatibilityInfo BetaCompatibility { get; set; } - - /// Whether a Stardew Valley or SMAPI beta which affects mod compatibility is in progress. If this is true, should be used for beta versions of SMAPI instead of . - public bool HasBetaInfo => this.BetaCompatibility != null; - - /// The human-readable warnings for players about this mod. - public string[] Warnings { get; set; } - - /// The link anchor for the mod entry in the wiki compatibility list. - public string Anchor { get; set; } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModList.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModList.cs deleted file mode 100644 index 0d614f28..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModList.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki -{ - /// Metadata from the wiki's mod compatibility list. - public class WikiModList - { - /********* - ** Accessors - *********/ - /// The stable game version. - public string StableVersion { get; set; } - - /// The beta game version (if any). - public string BetaVersion { get; set; } - - /// The mods on the wiki. - public WikiModEntry[] Mods { get; set; } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/MetadataModel.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/MetadataModel.cs deleted file mode 100644 index ef6d4dd9..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/MetadataModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; - -namespace StardewModdingAPI.Toolkit.Framework.ModData -{ - /// The SMAPI predefined metadata. - internal class MetadataModel - { - /******** - ** Accessors - ********/ - /// Extra metadata about mods. - public IDictionary ModData { get; set; } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataField.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataField.cs deleted file mode 100644 index b3954693..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataField.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Linq; - -namespace StardewModdingAPI.Toolkit.Framework.ModData -{ - /// A versioned mod metadata field. - public class ModDataField - { - /********* - ** Accessors - *********/ - /// The field key. - public ModDataFieldKey Key { get; } - - /// The field value. - public string Value { get; } - - /// Whether this field should only be applied if it's not already set. - public bool IsDefault { get; } - - /// The lowest version in the range, or null for all past versions. - public ISemanticVersion LowerVersion { get; } - - /// The highest version in the range, or null for all future versions. - public ISemanticVersion UpperVersion { get; } - - - /********* - ** Public methods - *********/ - /// Construct an instance. - /// The field key. - /// The field value. - /// Whether this field should only be applied if it's not already set. - /// The lowest version in the range, or null for all past versions. - /// The highest version in the range, or null for all future versions. - public ModDataField(ModDataFieldKey key, string value, bool isDefault, ISemanticVersion lowerVersion, ISemanticVersion upperVersion) - { - this.Key = key; - this.Value = value; - this.IsDefault = isDefault; - this.LowerVersion = lowerVersion; - this.UpperVersion = upperVersion; - } - - /// Get whether this data field applies for the given manifest. - /// The mod manifest. - public bool IsMatch(IManifest manifest) - { - return - manifest?.Version != null // ignore invalid manifest - && (!this.IsDefault || !this.HasFieldValue(manifest, this.Key)) - && (this.LowerVersion == null || !manifest.Version.IsOlderThan(this.LowerVersion)) - && (this.UpperVersion == null || !manifest.Version.IsNewerThan(this.UpperVersion)); - } - - - /********* - ** Private methods - *********/ - /// Get whether a manifest field has a meaningful value for the purposes of enforcing . - /// The mod manifest. - /// The field key matching . - private bool HasFieldValue(IManifest manifest, ModDataFieldKey key) - { - switch (key) - { - // update key - case ModDataFieldKey.UpdateKey: - return manifest.UpdateKeys != null && manifest.UpdateKeys.Any(p => !string.IsNullOrWhiteSpace(p)); - - // non-manifest fields - case ModDataFieldKey.AlternativeUrl: - case ModDataFieldKey.StatusReasonPhrase: - case ModDataFieldKey.Status: - return false; - - default: - return false; - } - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataFieldKey.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataFieldKey.cs deleted file mode 100644 index 09dd0cc5..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataFieldKey.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace StardewModdingAPI.Toolkit.Framework.ModData -{ - /// The valid field keys. - public enum ModDataFieldKey - { - /// A manifest update key. - UpdateKey, - - /// An alternative URL the player can check for an updated version. - AlternativeUrl, - - /// The mod's predefined compatibility status. - Status, - - /// A reason phrase for the , or null to use the default reason. - StatusReasonPhrase - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs deleted file mode 100644 index 18039762..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs +++ /dev/null @@ -1,127 +0,0 @@ -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 -{ - /// The raw mod metadata from SMAPI's internal mod list. - internal class ModDataModel - { - /********* - ** Accessors - *********/ - /// The mod's current unique ID. - public string ID { get; set; } - - /// The former mod IDs (if any). - /// - /// 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. If the mod's ID changed over time, multiple variants can be separated by the - /// | character. - /// - public string FormerIDs { get; set; } - - /// Maps local versions to a semantic version for update checks. - public IDictionary MapLocalVersions { get; set; } = new Dictionary(); - - /// Maps remote versions to a semantic version for update checks. - public IDictionary MapRemoteVersions { get; set; } = new Dictionary(); - - /// The mod warnings to suppress, even if they'd normally be shown. - public ModWarning SuppressWarnings { get; set; } - - /// This field stores properties that aren't mapped to another field before they're parsed into . - [JsonExtensionData] - public IDictionary ExtensionData { get; set; } - - /// The versioned field data. - /// - /// This maps field names to values. This should be accessed via . - /// Format notes: - /// - Each key consists of a field name prefixed with any combination of version range - /// and Default, separated by pipes (whitespace trimmed). For example, Name - /// will always override the name, Default | Name will only override a blank - /// name, and ~1.1 | Default | Name will override blank names up to version 1.1. - /// - The version format is min~max (where either side can be blank for unbounded), or - /// a single version number. - /// - The field name itself corresponds to a value. - /// - public IDictionary Fields { get; set; } = new Dictionary(); - - - /********* - ** Public methods - *********/ - /// Get a parsed representation of the . - public IEnumerable GetFields() - { - foreach (KeyValuePair 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); - } - } - - /// Get the former mod IDs. - public IEnumerable GetFormerIDs() - { - if (this.FormerIDs != null) - { - foreach (string id in this.FormerIDs.Split('|')) - yield return id.Trim(); - } - } - - - /********* - ** Private methods - *********/ - /// The method invoked after JSON deserialisation. - /// The deserialisation context. - [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 deleted file mode 100644 index 794ad2e4..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace StardewModdingAPI.Toolkit.Framework.ModData -{ - /// The parsed mod metadata from SMAPI's internal mod list. - public class ModDataRecord - { - /********* - ** Accessors - *********/ - /// The mod's default display name. - public string DisplayName { get; } - - /// The mod's current unique ID. - public string ID { get; } - - /// The former mod IDs (if any). - public string[] FormerIDs { get; } - - /// The mod warnings to suppress, even if they'd normally be shown. - public ModWarning SuppressWarnings { get; set; } - - /// Maps local versions to a semantic version for update checks. - public IDictionary MapLocalVersions { get; } - - /// Maps remote versions to a semantic version for update checks. - public IDictionary MapRemoteVersions { get; } - - /// The versioned field data. - public ModDataField[] Fields { get; } - - - /********* - ** Public methods - *********/ - /// Construct an instance. - /// The mod's default display name. - /// The raw data model. - internal ModDataRecord(string displayName, ModDataModel model) - { - this.DisplayName = displayName; - this.ID = model.ID; - this.FormerIDs = model.GetFormerIDs().ToArray(); - this.SuppressWarnings = model.SuppressWarnings; - this.MapLocalVersions = new Dictionary(model.MapLocalVersions, StringComparer.InvariantCultureIgnoreCase); - this.MapRemoteVersions = new Dictionary(model.MapRemoteVersions, StringComparer.InvariantCultureIgnoreCase); - this.Fields = model.GetFields().ToArray(); - } - - /// Get whether the mod has (or previously had) the given ID. - /// The mod ID. - 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; - } - - /// Get a semantic local version for update checks. - /// The remote version to normalise. - public ISemanticVersion GetLocalVersionForUpdateChecks(ISemanticVersion version) - { - return this.MapLocalVersions != null && this.MapLocalVersions.TryGetValue(version.ToString(), out string newVersion) - ? new SemanticVersion(newVersion) - : version; - } - - /// Get a semantic remote version for update checks. - /// The remote version to normalise. - public string GetRemoteVersionForUpdateChecks(string version) - { - // normalise version if possible - if (SemanticVersion.TryParse(version, out ISemanticVersion parsed)) - version = parsed.ToString(); - - // fetch remote version - return this.MapRemoteVersions != null && this.MapRemoteVersions.TryGetValue(version, out string newVersion) - ? newVersion - : version; - } - - /// Get the possible mod IDs. - public IEnumerable GetIDs() - { - return this.FormerIDs - .Concat(new[] { this.ID }) - .Where(p => !string.IsNullOrWhiteSpace(p)) - .Select(p => p.Trim()) - .Distinct(); - } - - /// Get the default update key for this mod, if any. - public string GetDefaultUpdateKey() - { - string updateKey = this.Fields.FirstOrDefault(p => p.Key == ModDataFieldKey.UpdateKey && p.IsDefault)?.Value; - return !string.IsNullOrWhiteSpace(updateKey) - ? updateKey - : null; - } - - /// Get a parsed representation of the which match a given manifest. - /// The manifest to match. - public ModDataRecordVersionedFields GetVersionedFields(IManifest manifest) - { - ModDataRecordVersionedFields parsed = new ModDataRecordVersionedFields { DisplayName = this.DisplayName, DataRecord = this }; - foreach (ModDataField field in this.Fields.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; - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs deleted file mode 100644 index 237f2c66..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace StardewModdingAPI.Toolkit.Framework.ModData -{ - /// The versioned fields from a for a specific manifest. - public class ModDataRecordVersionedFields - { - /********* - ** Accessors - *********/ - /// The underlying data record. - public ModDataRecord DataRecord { get; set; } - - /// The default mod name to display when the name isn't available (e.g. during dependency checks). - public string DisplayName { get; set; } - - /// The update key to apply. - public string UpdateKey { get; set; } - - /// The alternative URL the player can check for an updated version. - public string AlternativeUrl { get; set; } - - /// The predefined compatibility status. - public ModStatus Status { get; set; } = ModStatus.None; - - /// A reason phrase for the , or null to use the default reason. - public string StatusReasonPhrase { get; set; } - - /// The upper version for which the applies (if any). - public ISemanticVersion StatusUpperVersion { get; set; } - - - /********* - ** Public methods - *********/ - /// Get a semantic local version for update checks. - /// The remote version to normalise. - public ISemanticVersion GetLocalVersionForUpdateChecks(ISemanticVersion version) - { - return this.DataRecord.GetLocalVersionForUpdateChecks(version); - } - - /// Get a semantic remote version for update checks. - /// The remote version to normalise. - public ISemanticVersion GetRemoteVersionForUpdateChecks(ISemanticVersion version) - { - if (version == null) - return null; - - string rawVersion = this.DataRecord.GetRemoteVersionForUpdateChecks(version.ToString()); - return rawVersion != null - ? new SemanticVersion(rawVersion) - : version; - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDatabase.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDatabase.cs deleted file mode 100644 index a9da884a..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDatabase.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace StardewModdingAPI.Toolkit.Framework.ModData -{ - /// Handles access to SMAPI's internal mod metadata list. - public class ModDatabase - { - /********* - ** Fields - *********/ - /// The underlying mod data records indexed by default display name. - private readonly ModDataRecord[] Records; - - /// Get an update URL for an update key (if valid). - private readonly Func GetUpdateUrl; - - - /********* - ** Public methods - *********/ - /// Construct an empty instance. - public ModDatabase() - : this(new ModDataRecord[0], key => null) { } - - /// Construct an instance. - /// The underlying mod data records indexed by default display name. - /// Get an update URL for an update key (if valid). - public ModDatabase(IEnumerable records, Func getUpdateUrl) - { - this.Records = records.ToArray(); - this.GetUpdateUrl = getUpdateUrl; - } - - /// Get all mod data records. - public IEnumerable GetAll() - { - return this.Records; - } - - /// Get a mod data record. - /// The unique mod ID. - public ModDataRecord Get(string modID) - { - return !string.IsNullOrWhiteSpace(modID) - ? this.Records.FirstOrDefault(p => p.HasID(modID)) - : null; - } - - /// Get the mod page URL for a mod (if available). - /// The unique mod ID. - public string GetModPageUrlFor(string id) - { - // get update key - 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); - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModStatus.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModStatus.cs deleted file mode 100644 index 09da74bf..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModStatus.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace StardewModdingAPI.Toolkit.Framework.ModData -{ - /// Indicates how SMAPI should treat a mod. - public enum ModStatus - { - /// Don't override the status. - None, - - /// The mod is obsolete and shouldn't be used, regardless of version. - Obsolete, - - /// Assume the mod is not compatible, even if SMAPI doesn't detect any incompatible code. - AssumeBroken, - - /// Assume the mod is compatible, even if SMAPI detects incompatible code. - AssumeCompatible - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModWarning.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModWarning.cs deleted file mode 100644 index d61c427f..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModWarning.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; - -namespace StardewModdingAPI.Toolkit.Framework.ModData -{ - /// Indicates a detected non-error mod issue. - [Flags] - public enum ModWarning - { - /// No issues detected. - None = 0, - - /// SMAPI detected incompatible code in the mod, but was configured to load it anyway. - BrokenCodeLoaded = 1, - - /// The mod affects the save serializer in a way that may make saves unloadable without the mod. - ChangesSaveSerialiser = 2, - - /// The mod patches the game in a way that may impact stability. - PatchesGame = 4, - - /// The mod uses the dynamic keyword which won't work on Linux/Mac. - UsesDynamic = 8, - - /// The mod references specialised 'unvalided update tick' events which may impact stability. - UsesUnvalidatedUpdateTick = 16, - - /// The mod has no update keys set. - NoUpdateKeys = 32, - - /// Uses .NET APIs for filesystem access. - AccessesFilesystem = 64, - - /// Uses .NET APIs for shell or process access. - AccessesShell = 128 - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModScanning/ModFolder.cs b/src/StardewModdingAPI.Toolkit/Framework/ModScanning/ModFolder.cs deleted file mode 100644 index bb467b36..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/ModScanning/ModFolder.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using StardewModdingAPI.Toolkit.Serialisation.Models; -using StardewModdingAPI.Toolkit.Utilities; - -namespace StardewModdingAPI.Toolkit.Framework.ModScanning -{ - /// The info about a mod read from its folder. - public class ModFolder - { - /********* - ** Accessors - *********/ - /// A suggested display name for the mod folder. - public string DisplayName { get; } - - /// The folder containing the mod's manifest.json. - public DirectoryInfo Directory { get; } - - /// The mod manifest. - public Manifest Manifest { get; } - - /// The error which occurred parsing the manifest, if any. - public string ManifestParseError { get; } - - /// Whether the mod should be loaded by default. This is false if it was found within a folder whose name starts with a dot. - public bool ShouldBeLoaded { get; } - - - /********* - ** Public methods - *********/ - /// Construct an instance. - /// The root folder containing mods. - /// The folder containing the mod's manifest.json. - /// The mod manifest. - /// The error which occurred parsing the manifest, if any. - /// Whether the mod should be loaded by default. This should be false if it was found within a folder whose name starts with a dot. - public ModFolder(DirectoryInfo root, DirectoryInfo directory, Manifest manifest, string manifestParseError = null, bool shouldBeLoaded = true) - { - // save info - this.Directory = directory; - this.Manifest = manifest; - this.ManifestParseError = manifestParseError; - this.ShouldBeLoaded = shouldBeLoaded; - - // set display name - this.DisplayName = manifest?.Name; - if (string.IsNullOrWhiteSpace(this.DisplayName)) - this.DisplayName = PathUtilities.GetRelativePath(root.FullName, directory.FullName); - } - - /// Get the update keys for a mod. - /// The mod manifest. - public IEnumerable GetUpdateKeys(Manifest manifest) - { - return - (manifest.UpdateKeys ?? new string[0]) - .Where(p => !string.IsNullOrWhiteSpace(p)) - .ToArray(); - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModScanning/ModScanner.cs b/src/StardewModdingAPI.Toolkit/Framework/ModScanning/ModScanner.cs deleted file mode 100644 index 0ab73d56..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/ModScanning/ModScanner.cs +++ /dev/null @@ -1,183 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using StardewModdingAPI.Toolkit.Serialisation; -using StardewModdingAPI.Toolkit.Serialisation.Models; - -namespace StardewModdingAPI.Toolkit.Framework.ModScanning -{ - /// Scans folders for mod data. - public class ModScanner - { - /********* - ** Fields - *********/ - /// The JSON helper with which to read manifests. - private readonly JsonHelper JsonHelper; - - /// A list of filesystem entry names to ignore when checking whether a folder should be treated as a mod. - private readonly HashSet IgnoreFilesystemEntries = new HashSet(StringComparer.InvariantCultureIgnoreCase) - { - ".DS_Store", - "mcs", - "Thumbs.db" - }; - - /// The extensions for files which an XNB mod may contain. If a mod contains *only* these file extensions, it should be considered an XNB mod. - private readonly HashSet PotentialXnbModExtensions = new HashSet(StringComparer.InvariantCultureIgnoreCase) - { - ".md", - ".png", - ".txt", - ".xnb" - }; - - - /********* - ** Public methods - *********/ - /// Construct an instance. - /// The JSON helper with which to read manifests. - public ModScanner(JsonHelper jsonHelper) - { - this.JsonHelper = jsonHelper; - } - - /// Extract information about all mods in the given folder. - /// The root folder containing mods. - public IEnumerable GetModFolders(string rootPath) - { - DirectoryInfo root = new DirectoryInfo(rootPath); - return this.GetModFolders(root, root); - } - - /// Extract information from a mod folder. - /// The root folder containing mods. - /// The folder to search for a mod. - public ModFolder ReadFolder(DirectoryInfo root, DirectoryInfo searchFolder) - { - // find manifest.json - FileInfo manifestFile = this.FindManifest(searchFolder); - - // set appropriate invalid-mod error - if (manifestFile == null) - { - FileInfo[] files = searchFolder.GetFiles("*", SearchOption.AllDirectories).Where(this.IsRelevant).ToArray(); - if (!files.Any()) - return new ModFolder(root, searchFolder, null, "it's an empty folder."); - if (files.All(file => this.PotentialXnbModExtensions.Contains(file.Extension))) - return new ModFolder(root, searchFolder, null, "it's not a SMAPI mod (see https://smapi.io/xnb for info)."); - return new ModFolder(root, searchFolder, null, "it contains files, but none of them are manifest.json."); - } - - // read mod info - Manifest manifest = null; - string manifestError = null; - { - try - { - if (!this.JsonHelper.ReadJsonFileIfExists(manifestFile.FullName, out manifest) || manifest == null) - manifestError = "its manifest is invalid."; - } - catch (SParseException ex) - { - manifestError = $"parsing its manifest failed: {ex.Message}"; - } - catch (Exception ex) - { - manifestError = $"parsing its manifest failed:\n{ex}"; - } - } - - // normalise display fields - if (manifest != null) - { - manifest.Name = this.StripNewlines(manifest.Name); - manifest.Description = this.StripNewlines(manifest.Description); - manifest.Author = this.StripNewlines(manifest.Author); - } - - return new ModFolder(root, manifestFile.Directory, manifest, manifestError); - } - - - /********* - ** Private methods - *********/ - /// Recursively extract information about all mods in the given folder. - /// The root mod folder. - /// The folder to search for mods. - public IEnumerable GetModFolders(DirectoryInfo root, DirectoryInfo folder) - { - // skip - if (folder.FullName != root.FullName && folder.Name.StartsWith(".")) - yield return new ModFolder(root, folder, null, "ignored folder because its name starts with a dot.", shouldBeLoaded: false); - - // recurse into subfolders - else if (this.IsModSearchFolder(root, folder)) - { - foreach (DirectoryInfo subfolder in folder.EnumerateDirectories()) - { - foreach (ModFolder match in this.GetModFolders(root, subfolder)) - yield return match; - } - } - - // treat as mod folder - else - yield return this.ReadFolder(root, folder); - } - - /// Find the manifest for a mod folder. - /// The folder to search. - private FileInfo FindManifest(DirectoryInfo folder) - { - while (true) - { - // check for manifest in current folder - FileInfo file = new FileInfo(Path.Combine(folder.FullName, "manifest.json")); - if (file.Exists) - return file; - - // check for single subfolder - FileSystemInfo[] entries = folder.EnumerateFileSystemInfos().Take(2).ToArray(); - if (entries.Length == 1 && entries[0] is DirectoryInfo subfolder) - { - folder = subfolder; - continue; - } - - // not found - return null; - } - } - - /// Get whether a given folder should be treated as a search folder (i.e. look for subfolders containing mods). - /// The root mod folder. - /// The folder to search for mods. - private bool IsModSearchFolder(DirectoryInfo root, DirectoryInfo folder) - { - if (root.FullName == folder.FullName) - return true; - - DirectoryInfo[] subfolders = folder.GetDirectories().Where(this.IsRelevant).ToArray(); - FileInfo[] files = folder.GetFiles().Where(this.IsRelevant).ToArray(); - return subfolders.Any() && !files.Any(); - } - - /// Get whether a file or folder is relevant when deciding how to process a mod folder. - /// The file or folder. - private bool IsRelevant(FileSystemInfo entry) - { - return !this.IgnoreFilesystemEntries.Contains(entry.Name); - } - - /// Strip newlines from a string. - /// The input to strip. - private string StripNewlines(string input) - { - return input?.Replace("\r", "").Replace("\n", ""); - } - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/UpdateData/ModRepositoryKey.cs b/src/StardewModdingAPI.Toolkit/Framework/UpdateData/ModRepositoryKey.cs deleted file mode 100644 index f6c402d5..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/UpdateData/ModRepositoryKey.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace StardewModdingAPI.Toolkit.Framework.UpdateData -{ - /// A mod repository which SMAPI can check for updates. - public enum ModRepositoryKey - { - /// An unknown or invalid mod repository. - Unknown, - - /// The Chucklefish mod repository. - Chucklefish, - - /// A GitHub project containing releases. - GitHub, - - /// The ModDrop mod repository. - ModDrop, - - /// The Nexus Mods mod repository. - Nexus - } -} diff --git a/src/StardewModdingAPI.Toolkit/Framework/UpdateData/UpdateKey.cs b/src/StardewModdingAPI.Toolkit/Framework/UpdateData/UpdateKey.cs deleted file mode 100644 index 865ebcf7..00000000 --- a/src/StardewModdingAPI.Toolkit/Framework/UpdateData/UpdateKey.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; - -namespace StardewModdingAPI.Toolkit.Framework.UpdateData -{ - /// A namespaced mod ID which uniquely identifies a mod within a mod repository. - public class UpdateKey - { - /********* - ** Accessors - *********/ - /// The raw update key text. - public string RawText { get; } - - /// The mod repository containing the mod. - public ModRepositoryKey Repository { get; } - - /// The mod ID within the repository. - public string ID { get; } - - /// Whether the update key seems to be valid. - public bool LooksValid { get; } - - - /********* - ** Public methods - *********/ - /// Construct an instance. - /// The raw update key text. - /// The mod repository containing the mod. - /// The mod ID within the repository. - public UpdateKey(string rawText, ModRepositoryKey repository, string id) - { - this.RawText = rawText; - this.Repository = repository; - this.ID = id; - this.LooksValid = - repository != ModRepositoryKey.Unknown - && !string.IsNullOrWhiteSpace(id); - } - - /// Parse a raw update key. - /// The raw update key to parse. - public static UpdateKey Parse(string raw) - { - // split parts - string[] parts = raw?.Split(':'); - if (parts == null || parts.Length != 2) - return new UpdateKey(raw, ModRepositoryKey.Unknown, null); - - // extract parts - string repositoryKey = parts[0].Trim(); - string id = parts[1].Trim(); - if (string.IsNullOrWhiteSpace(id)) - id = null; - - // parse - if (!Enum.TryParse(repositoryKey, true, out ModRepositoryKey repository)) - return new UpdateKey(raw, ModRepositoryKey.Unknown, id); - if (id == null) - return new UpdateKey(raw, repository, null); - - return new UpdateKey(raw, repository, id); - } - - /// Get a string that represents the current object. - public override string ToString() - { - return this.LooksValid - ? $"{this.Repository}:{this.ID}" - : this.RawText; - } - } -} -- cgit