diff --git a/src/StardewModdingAPI.Tests/Core/ModResolverTests.cs b/src/StardewModdingAPI.Tests/Core/ModResolverTests.cs index 198ce190..4dbd1438 100644 --- a/src/StardewModdingAPI.Tests/Core/ModResolverTests.cs +++ b/src/StardewModdingAPI.Tests/Core/ModResolverTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -30,7 +30,7 @@ namespace StardewModdingAPI.Tests.Core Directory.CreateDirectory(rootFolder); // act - IModMetadata[] mods = new ModResolver().ReadManifests(rootFolder, new JsonHelper(), new ModCompatibility[0]).ToArray(); + IModMetadata[] mods = new ModResolver().ReadManifests(rootFolder, new JsonHelper(), new ModDataRecord[0]).ToArray(); // assert Assert.AreEqual(0, mods.Length, 0, $"Expected to find zero manifests, found {mods.Length} instead."); @@ -45,7 +45,7 @@ namespace StardewModdingAPI.Tests.Core Directory.CreateDirectory(modFolder); // act - IModMetadata[] mods = new ModResolver().ReadManifests(rootFolder, new JsonHelper(), new ModCompatibility[0]).ToArray(); + IModMetadata[] mods = new ModResolver().ReadManifests(rootFolder, new JsonHelper(), new ModDataRecord[0]).ToArray(); IModMetadata mod = mods.FirstOrDefault(); // assert @@ -84,13 +84,13 @@ namespace StardewModdingAPI.Tests.Core File.WriteAllText(filename, JsonConvert.SerializeObject(original)); // act - IModMetadata[] mods = new ModResolver().ReadManifests(rootFolder, new JsonHelper(), new ModCompatibility[0]).ToArray(); + IModMetadata[] mods = new ModResolver().ReadManifests(rootFolder, new JsonHelper(), new ModDataRecord[0]).ToArray(); IModMetadata mod = mods.FirstOrDefault(); // assert Assert.AreEqual(1, mods.Length, 0, "Expected to find one manifest."); Assert.IsNotNull(mod, "The loaded manifest shouldn't be null."); - Assert.AreEqual(null, mod.Compatibility, "The compatibility record should be null since we didn't provide one."); + Assert.AreEqual(null, mod.DataRecord, "The data record should be null since we didn't provide one."); Assert.AreEqual(modFolder, mod.DirectoryPath, "The directory path doesn't match."); Assert.AreEqual(ModMetadataStatus.Found, mod.Status, "The status doesn't match."); Assert.AreEqual(null, mod.Error, "The error should be null since parsing should have succeeded."); @@ -136,12 +136,12 @@ namespace StardewModdingAPI.Tests.Core mock.VerifyGet(p => p.Status, Times.Once, "The validation did not check the manifest status."); } - [Test(Description = "Assert that validation fails if the mod has 'assume broken' compatibility.")] - public void ValidateManifests_ModCompatibility_AssumeBroken_Fails() + [Test(Description = "Assert that validation fails if the mod has 'assume broken' status.")] + public void ValidateManifests_ModStatus_AssumeBroken_Fails() { // arrange Mock mock = this.GetMetadata("Mod A", new string[0], allowStatusChange: true); - this.SetupMetadataForValidation(mock, new ModCompatibility { Status = ModStatus.AssumeBroken, UpperVersion = new SemanticVersion("1.0"), UpdateUrls = new[] { "http://example.org" } }); + this.SetupMetadataForValidation(mock, new ModDataRecord { Status = ModStatus.AssumeBroken, UpperVersion = new SemanticVersion("1.0"), UpdateUrls = new[] { "http://example.org" } }); // act new ModResolver().ValidateManifests(new[] { mock.Object }, apiVersion: new SemanticVersion("1.0")); @@ -211,7 +211,7 @@ namespace StardewModdingAPI.Tests.Core // arrange Mock mock = new Mock(MockBehavior.Strict); mock.Setup(p => p.Status).Returns(ModMetadataStatus.Found); - mock.Setup(p => p.Compatibility).Returns(() => null); + mock.Setup(p => p.DataRecord).Returns(() => null); mock.Setup(p => p.Manifest).Returns(manifest); mock.Setup(p => p.DirectoryPath).Returns(modFolder); @@ -523,7 +523,7 @@ namespace StardewModdingAPI.Tests.Core private Mock GetMetadata(IManifest manifest, bool allowStatusChange = false) { Mock mod = new Mock(MockBehavior.Strict); - mod.Setup(p => p.Compatibility).Returns(() => null); + mod.Setup(p => p.DataRecord).Returns(() => null); mod.Setup(p => p.Status).Returns(ModMetadataStatus.Found); mod.Setup(p => p.DisplayName).Returns(manifest.UniqueID); mod.Setup(p => p.Manifest).Returns(manifest); @@ -539,14 +539,14 @@ namespace StardewModdingAPI.Tests.Core /// Set up a mock mod metadata for . /// The mock mod metadata. - /// The compatibility record to set. - private void SetupMetadataForValidation(Mock mod, ModCompatibility compatibility = null) + /// The extra metadata about the mod from SMAPI's internal data (if any). + private void SetupMetadataForValidation(Mock mod, ModDataRecord modRecord = null) { mod.Setup(p => p.Status).Returns(ModMetadataStatus.Found); - mod.Setup(p => p.Compatibility).Returns(() => null); + mod.Setup(p => p.DataRecord).Returns(() => null); mod.Setup(p => p.Manifest).Returns(this.GetManifest()); mod.Setup(p => p.DirectoryPath).Returns(Path.GetTempPath()); - mod.Setup(p => p.Compatibility).Returns(compatibility); + mod.Setup(p => p.DataRecord).Returns(modRecord); } } } diff --git a/src/StardewModdingAPI/Framework/IModMetadata.cs b/src/StardewModdingAPI/Framework/IModMetadata.cs index 56ac25f1..c21734a7 100644 --- a/src/StardewModdingAPI/Framework/IModMetadata.cs +++ b/src/StardewModdingAPI/Framework/IModMetadata.cs @@ -1,4 +1,4 @@ -using StardewModdingAPI.Framework.Models; +using StardewModdingAPI.Framework.Models; using StardewModdingAPI.Framework.ModLoading; namespace StardewModdingAPI.Framework @@ -18,8 +18,8 @@ namespace StardewModdingAPI.Framework /// The mod manifest. IManifest Manifest { get; } - /// Optional metadata about a mod version that SMAPI should assume is compatible or broken, regardless of whether it detects incompatible code. - ModCompatibility Compatibility { get; } + /// >Metadata about the mod from SMAPI's internal data (if any). + ModDataRecord DataRecord { get; } /// The metadata resolution status. ModMetadataStatus Status { get; } diff --git a/src/StardewModdingAPI/Framework/ModLoading/ModMetadata.cs b/src/StardewModdingAPI/Framework/ModLoading/ModMetadata.cs index ab590e10..5055da75 100644 --- a/src/StardewModdingAPI/Framework/ModLoading/ModMetadata.cs +++ b/src/StardewModdingAPI/Framework/ModLoading/ModMetadata.cs @@ -1,4 +1,4 @@ -using StardewModdingAPI.Framework.Models; +using StardewModdingAPI.Framework.Models; namespace StardewModdingAPI.Framework.ModLoading { @@ -17,8 +17,8 @@ namespace StardewModdingAPI.Framework.ModLoading /// The mod manifest. public IManifest Manifest { get; } - /// Optional metadata about a mod version that SMAPI should assume is compatible or broken, regardless of whether it detects incompatible code. - public ModCompatibility Compatibility { get; } + /// Metadata about the mod from SMAPI's internal data (if any). + public ModDataRecord DataRecord { get; } /// The metadata resolution status. public ModMetadataStatus Status { get; private set; } @@ -37,13 +37,13 @@ namespace StardewModdingAPI.Framework.ModLoading /// The mod's display name. /// The mod's full directory path. /// The mod manifest. - /// Optional metadata about a mod version that SMAPI should assume is compatible or broken, regardless of whether it detects incompatible code. - public ModMetadata(string displayName, string directoryPath, IManifest manifest, ModCompatibility compatibility) + /// Metadata about the mod from SMAPI's internal data (if any). + public ModMetadata(string displayName, string directoryPath, IManifest manifest, ModDataRecord dataRecord) { this.DisplayName = displayName; this.DirectoryPath = directoryPath; this.Manifest = manifest; - this.Compatibility = compatibility; + this.DataRecord = dataRecord; } /// Set the mod status. diff --git a/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs b/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs index 02fd85ea..2da10348 100644 --- a/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs +++ b/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs @@ -17,11 +17,11 @@ namespace StardewModdingAPI.Framework.ModLoading /// Get manifest metadata for each folder in the given root path. /// The root path to search for mods. /// The JSON helper with which to read manifests. - /// Metadata about mods that SMAPI should assume is compatible or broken, regardless of whether it detects incompatible code. + /// Metadata about mods from SMAPI's internal data. /// Returns the manifests by relative folder. - public IEnumerable ReadManifests(string rootPath, JsonHelper jsonHelper, IEnumerable compatibilityRecords) + public IEnumerable ReadManifests(string rootPath, JsonHelper jsonHelper, IEnumerable dataRecords) { - compatibilityRecords = compatibilityRecords.ToArray(); + dataRecords = dataRecords.ToArray(); foreach (DirectoryInfo modDir in this.GetModFolders(rootPath)) { @@ -54,15 +54,15 @@ namespace StardewModdingAPI.Framework.ModLoading } // validate metadata - ModCompatibility compatibility = null; + ModDataRecord dataRecord = null; if (manifest != null) { // get unique key for lookups string key = !string.IsNullOrWhiteSpace(manifest.UniqueID) ? manifest.UniqueID : manifest.EntryDll; - // get compatibility record - compatibility = ( - from mod in compatibilityRecords + // get data record + dataRecord = ( + from mod in dataRecords where mod.ID.Any(p => p.Matches(key, manifest)) && (mod.LowerVersion == null || !manifest.Version.IsOlderThan(mod.LowerVersion)) @@ -79,7 +79,7 @@ namespace StardewModdingAPI.Framework.ModLoading ? ModMetadataStatus.Found : ModMetadataStatus.Failed; - yield return new ModMetadata(displayName, modDir.FullName, manifest, compatibility).SetStatus(status, error); + yield return new ModMetadata(displayName, modDir.FullName, manifest, dataRecord).SetStatus(status, error); } } @@ -99,22 +99,22 @@ namespace StardewModdingAPI.Framework.ModLoading // validate compatibility { - ModCompatibility compatibility = mod.Compatibility; - switch (compatibility?.Status) + ModDataRecord dataRecord = mod.DataRecord; + switch (dataRecord?.Status) { case ModStatus.Obsolete: - mod.SetStatus(ModMetadataStatus.Failed, $"it's obsolete: {compatibility.ReasonPhrase}"); + mod.SetStatus(ModMetadataStatus.Failed, $"it's obsolete: {dataRecord.ReasonPhrase}"); continue; case ModStatus.AssumeBroken: { - string reasonPhrase = compatibility.ReasonPhrase ?? "it's no longer compatible"; + string reasonPhrase = dataRecord.ReasonPhrase ?? "it's no longer compatible"; string error = $"{reasonPhrase}. Please check for a "; - if (mod.Manifest.Version.Equals(compatibility.UpperVersion) && compatibility.UpperVersionLabel == null) + if (mod.Manifest.Version.Equals(dataRecord.UpperVersion) && dataRecord.UpperVersionLabel == null) error += "newer version"; else - error += $"version newer than {compatibility.UpperVersionLabel ?? compatibility.UpperVersion.ToString()}"; - error += " at " + string.Join(" or ", compatibility.UpdateUrls); + error += $"version newer than {dataRecord.UpperVersionLabel ?? dataRecord.UpperVersion.ToString()}"; + error += " at " + string.Join(" or ", dataRecord.UpdateUrls); mod.SetStatus(ModMetadataStatus.Failed, error); continue; diff --git a/src/StardewModdingAPI/Framework/Models/ModCompatibilityID.cs b/src/StardewModdingAPI/Framework/Models/ModDataID.cs similarity index 88% rename from src/StardewModdingAPI/Framework/Models/ModCompatibilityID.cs rename to src/StardewModdingAPI/Framework/Models/ModDataID.cs index 98e70116..5b45b507 100644 --- a/src/StardewModdingAPI/Framework/Models/ModCompatibilityID.cs +++ b/src/StardewModdingAPI/Framework/Models/ModDataID.cs @@ -1,10 +1,10 @@ -using System; +using System; using Newtonsoft.Json; namespace StardewModdingAPI.Framework.Models { - /// Uniquely identifies a mod for compatibility checks. - internal class ModCompatibilityID + /// Uniquely identifies a mod in SMAPI's internal data. + internal class ModDataID { /********* ** Accessors @@ -23,11 +23,11 @@ namespace StardewModdingAPI.Framework.Models ** Public methods *********/ /// Construct an instance. - public ModCompatibilityID() { } + public ModDataID() { } /// Construct an instance. - /// The mod ID or a JSON string matching the fields. - public ModCompatibilityID(string data) + /// The mod ID or a JSON string matching the fields. + 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 diff --git a/src/StardewModdingAPI/Framework/Models/ModCompatibility.cs b/src/StardewModdingAPI/Framework/Models/ModDataRecord.cs similarity index 86% rename from src/StardewModdingAPI/Framework/Models/ModCompatibility.cs rename to src/StardewModdingAPI/Framework/Models/ModDataRecord.cs index 7489a306..d40f2c78 100644 --- a/src/StardewModdingAPI/Framework/Models/ModCompatibility.cs +++ b/src/StardewModdingAPI/Framework/Models/ModDataRecord.cs @@ -3,15 +3,15 @@ using StardewModdingAPI.Framework.Serialisation; namespace StardewModdingAPI.Framework.Models { - /// Metadata about a mod version that SMAPI should assume is compatible or broken, regardless of whether it detects incompatible code. - internal class ModCompatibility + /// Metadata about a mod from SMAPI's internal data. + internal class ModDataRecord { /********* ** Accessors *********/ /// The unique mod IDs. [JsonConverter(typeof(SFieldConverter))] - public ModCompatibilityID[] ID { get; set; } + public ModDataID[] ID { get; set; } /// The mod name. public string Name { get; set; } diff --git a/src/StardewModdingAPI/Framework/Models/SConfig.cs b/src/StardewModdingAPI/Framework/Models/SConfig.cs index 720d4a6d..401e1a3a 100644 --- a/src/StardewModdingAPI/Framework/Models/SConfig.cs +++ b/src/StardewModdingAPI/Framework/Models/SConfig.cs @@ -21,7 +21,7 @@ namespace StardewModdingAPI.Framework.Models /// Whether SMAPI should log more information about the game context. public bool VerboseLogging { get; set; } - /// A list of mod versions which should be considered compatible or incompatible regardless of whether SMAPI detects incompatible code. - public ModCompatibility[] ModCompatibility { get; set; } + /// Extra metadata about mods. + public ModDataRecord[] ModData { get; set; } } } diff --git a/src/StardewModdingAPI/Framework/Serialisation/SFieldConverter.cs b/src/StardewModdingAPI/Framework/Serialisation/SFieldConverter.cs index 5419896f..59cc1582 100644 --- a/src/StardewModdingAPI/Framework/Serialisation/SFieldConverter.cs +++ b/src/StardewModdingAPI/Framework/Serialisation/SFieldConverter.cs @@ -27,7 +27,7 @@ namespace StardewModdingAPI.Framework.Serialisation return objectType == typeof(ISemanticVersion) || objectType == typeof(IManifestDependency[]) - || objectType == typeof(ModCompatibilityID[]); + || objectType == typeof(ModDataID[]); } /// Reads the JSON representation of the object. @@ -83,14 +83,14 @@ namespace StardewModdingAPI.Framework.Serialisation } // mod compatibility ID - if (objectType == typeof(ModCompatibilityID[])) + if (objectType == typeof(ModDataID[])) { - List result = new List(); + List result = new List(); foreach (JToken child in JArray.Load(reader).Children()) { result.Add(child is JValue value - ? new ModCompatibilityID(value.Value()) - : child.ToObject() + ? new ModDataID(value.Value()) + : child.ToObject() ); } return result.ToArray(); diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index b22fb02a..63176dd1 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -347,7 +347,7 @@ namespace StardewModdingAPI ModResolver resolver = new ModResolver(); // load manifests - IModMetadata[] mods = resolver.ReadManifests(Constants.ModPath, new JsonHelper(), this.Settings.ModCompatibility).ToArray(); + IModMetadata[] mods = resolver.ReadManifests(Constants.ModPath, new JsonHelper(), this.Settings.ModData).ToArray(); resolver.ValidateManifests(mods, Constants.ApiVersion); // process dependencies @@ -640,7 +640,7 @@ namespace StardewModdingAPI Assembly modAssembly; try { - modAssembly = modAssemblyLoader.Load(metadata, assemblyPath, assumeCompatible: metadata.Compatibility?.Status == ModStatus.AssumeCompatible); + modAssembly = modAssemblyLoader.Load(metadata, assemblyPath, assumeCompatible: metadata.DataRecord?.Status == ModStatus.AssumeCompatible); } catch (IncompatibleInstructionException ex) { diff --git a/src/StardewModdingAPI/StardewModdingAPI.config.json b/src/StardewModdingAPI/StardewModdingAPI.config.json index 7c20a9d9..aa6df389 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.config.json +++ b/src/StardewModdingAPI/StardewModdingAPI.config.json @@ -44,7 +44,7 @@ This file contains advanced configuration for SMAPI. You generally shouldn't cha * load a mod regardless of compatibility checks, add a "Compatibility": "AssumeCompatible" field. * Changing this field is not recommended and may destabilise your game. */ - "ModCompatibility": [ + "ModData": [ { "Name": "AccessChestAnywhere", "ID": [ "AccessChestAnywhere" ], diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj index 818e7263..38064f98 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.csproj +++ b/src/StardewModdingAPI/StardewModdingAPI.csproj @@ -142,7 +142,7 @@ - + @@ -194,7 +194,7 @@ - +