diff options
5 files changed, 196 insertions, 175 deletions
diff --git a/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs b/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs index 2da10348..3674faec 100644 --- a/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs +++ b/src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs @@ -64,7 +64,7 @@ namespace StardewModdingAPI.Framework.ModLoading dataRecord = ( from mod in dataRecords where - mod.ID.Any(p => p.Matches(key, manifest)) + mod.ID.Matches(key, manifest) && (mod.LowerVersion == null || !manifest.Version.IsOlderThan(mod.LowerVersion)) && (mod.UpperVersion == null || !manifest.Version.IsNewerThan(mod.UpperVersion)) select mod 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 { /// <summary>Uniquely identifies a mod in SMAPI's internal data.</summary> + /// <remarks> + /// 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 <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 three manifest fields (ID, Name, and Author) to match. + /// </remarks> internal class ModDataID { /********* - ** Accessors + ** Properties *********/ - /// <summary>The unique mod ID.</summary> - public string ID { get; set; } - - /// <summary>The mod name to disambiguate non-unique IDs, or <c>null</c> to ignore the mod name.</summary> - public string Name { get; set; } - - /// <summary>The author name to disambiguate non-unique IDs, or <c>null</c> to ignore the author.</summary> - public string Author { get; set; } + /// <summary>The unique sets of field values which identify this mod.</summary> + private readonly FieldSnapshot[] Snapshots; /********* @@ -26,17 +32,18 @@ namespace StardewModdingAPI.Framework.Models public ModDataID() { } /// <summary>Construct an instance.</summary> - /// <param name="data">The mod ID or a JSON string matching the <see cref="ModDataID"/> fields.</param> + /// <param name="data">The mod identifier string (see remarks on <see cref="ModDataID"/>).</param> 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<FieldSnapshot>(str) + : new FieldSnapshot { ID = str } + ) + .ToArray(); } /// <summary>Get whether this ID matches a given mod manifest.</summary> @@ -44,14 +51,35 @@ namespace StardewModdingAPI.Framework.Models /// <param name="manifest">The manifest to check.</param> 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 + *********/ + /// <summary>A unique set of fields which identifies the mod.</summary> + private class FieldSnapshot + { + /********* + ** Accessors + *********/ + /// <summary>The unique mod ID.</summary> + public string ID { get; set; } + + /// <summary>The mod name, or <c>null</c> to ignore the mod name.</summary> + public string Name { get; set; } + + /// <summary>The author name, or <c>null</c> to ignore the author.</summary> + public string Author { get; set; } } } } diff --git a/src/StardewModdingAPI/Framework/Models/ModDataRecord.cs b/src/StardewModdingAPI/Framework/Models/ModDataRecord.cs index d40f2c78..8126022d 100644 --- a/src/StardewModdingAPI/Framework/Models/ModDataRecord.cs +++ b/src/StardewModdingAPI/Framework/Models/ModDataRecord.cs @@ -9,9 +9,9 @@ namespace StardewModdingAPI.Framework.Models /********* ** Accessors *********/ - /// <summary>The unique mod IDs.</summary> + /// <summary>The unique mod identifier.</summary> [JsonConverter(typeof(SFieldConverter))] - public ModDataID[] ID { get; set; } + public ModDataID ID { get; set; } /// <summary>The mod name.</summary> public string Name { get; set; } diff --git a/src/StardewModdingAPI/Framework/Serialisation/SFieldConverter.cs b/src/StardewModdingAPI/Framework/Serialisation/SFieldConverter.cs index 59cc1582..d71e138b 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(ModDataID[]); + || objectType == typeof(ModDataID); } /// <summary>Reads the JSON representation of the object.</summary> @@ -83,17 +83,10 @@ namespace StardewModdingAPI.Framework.Serialisation } // mod compatibility ID - if (objectType == typeof(ModDataID[])) + if (objectType == typeof(ModDataID)) { - List<ModDataID> result = new List<ModDataID>(); - foreach (JToken child in JArray.Load(reader).Children()) - { - result.Add(child is JValue value - ? new ModDataID(value.Value<string>()) - : child.ToObject<ModDataID>() - ); - } - return result.ToArray(); + JToken token = JToken.Load(reader); + return new ModDataID(token.Value<string>()); } // unknown diff --git a/src/StardewModdingAPI/StardewModdingAPI.config.json b/src/StardewModdingAPI/StardewModdingAPI.config.json index aa6df389..c93ba130 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.config.json +++ b/src/StardewModdingAPI/StardewModdingAPI.config.json @@ -47,14 +47,14 @@ This file contains advanced configuration for SMAPI. You generally shouldn't cha "ModData": [ { "Name": "AccessChestAnywhere", - "ID": [ "AccessChestAnywhere" ], + "ID": "AccessChestAnywhere", "UpperVersion": "1.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/257", "http://www.nexusmods.com/stardewvalley/mods/518" ], "Notes": "Broke in SDV 1.1." }, { "Name": "AdjustArtisanPrices", - "ID": [ "1e36d4ca-c7ef-4dfb-9927-d27a6c3c8bdc" ], + "ID": "1e36d4ca-c7ef-4dfb-9927-d27a6c3c8bdc", "UpperVersion": "0.0", "UpperVersionLabel": "0.01", "UpdateUrls": [ "http://community.playstarbound.com/resources/3532", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], @@ -62,514 +62,514 @@ This file contains advanced configuration for SMAPI. You generally shouldn't cha }, { "Name": "Advanced Location Loader", - "ID": [ "Entoarox.AdvancedLocationLoader" ], + "ID": "Entoarox.AdvancedLocationLoader", "UpperVersion": "1.2.10", "UpdateUrls": [ "http://community.playstarbound.com/resources/3619" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "AgingMod", - "ID": [ "skn.AgingMod" ], + "ID": "skn.AgingMod", "UpperVersion": "1.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/1129", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Almighty Tool", - "ID": [ "AlmightyTool.dll" ], + "ID": "AlmightyTool.dll", "UpperVersion": "1.1.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/439" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Animal Mood Fix", - "ID": [ "GPeters-AnimalMoodFix" ], + "ID": "GPeters-AnimalMoodFix", "Status": "Obsolete", "ReasonPhrase": "the animal mood bugs were fixed in Stardew Valley 1.2." }, { "Name": "Animal Sitter", - "ID": [ "AnimalSitter.dll" ], + "ID": "AnimalSitter.dll", "UpperVersion": "1.0.8", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/581", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "A Tapper's Dream", - "ID": [ "ddde5195-8f85-4061-90cc-0d4fd5459358" ], + "ID": "ddde5195-8f85-4061-90cc-0d4fd5459358", "UpperVersion": "1.4", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/260", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Better Sprinklers", - "ID": [ "SPDSprinklersMod", /*since 2.3*/ "Speeder.BetterSprinklers" ], + "ID": "SPDSprinklersMod | Speeder.BetterSprinklers", // changed in 2.3 "UpperVersion": "2.3.1-pathoschild-update", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/41", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Birthday Mail", - "ID": [ "005e02dc-d900-425c-9c68-1ff55c5a295d" ], + "ID": "005e02dc-d900-425c-9c68-1ff55c5a295d", "UpperVersion": "1.2.2", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/276", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Build Endurance", - "ID": [ "{'ID':'4be88c18-b6f3-49b0-ba96-f94b1a5be890', 'Name':'BuildEndurance'}" ], // disambiguate from other Alpha_Omegasis mods + "ID": "{ID:'4be88c18-b6f3-49b0-ba96-f94b1a5be890', Name:'BuildEndurance'}", // disambiguate from other Alpha_Omegasis mods "UpperVersion": "1.3", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/445", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Build Health", - "ID": [ "{'ID':'4be88c18-b6f3-49b0-ba96-f94b1a5be890', 'Name':'BuildHealth'}" ], // disambiguate from other Alpha_Omegasis mods + "ID": "{ID:'4be88c18-b6f3-49b0-ba96-f94b1a5be890', Name:'BuildHealth'}", // disambiguate from other Alpha_Omegasis mods "UpperVersion": "1.3", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/446", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Buy Cooking Recipes", - "ID": [ "Denifia.BuyRecipes" ], + "ID": "Denifia.BuyRecipes", "UpperVersion": "1.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/1126", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Buy Back Collectables", - "ID": [ "BuyBackCollectables" ], + "ID": "BuyBackCollectables", "UpperVersion": "1.3", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/507", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Chest Label System", - "ID": [ "SPDChestLabel" ], + "ID": "SPDChestLabel", "UpperVersion": "1.6", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/242", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.1." }, { "Name": "Chest Pooling", - "ID": [ "ChestPooling.dll" ], + "ID": "ChestPooling.dll", "UpperVersion": "1.2", "UpdateUrls": [ "http://community.playstarbound.com/threads/111988" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Chests Anywhere", - "ID": [ "ChestsAnywhere", /*since 1.9*/ "Pathoschild.ChestsAnywhere" ], + "ID": "ChestsAnywhere | Pathoschild.ChestsAnywhere", // changed in 1.9 "UpperVersion": "1.9-beta", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/518" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Choose Baby Gender", - "ID": [ "ChooseBabyGender.dll" ], + "ID": "ChooseBabyGender.dll", "UpperVersion": "1.0.2", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/590", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "CJB Automation", - "ID": [ "CJBAutomation" ], + "ID": "CJBAutomation", "UpperVersion": "1.4", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/211", "http://www.nexusmods.com/stardewvalley/mods/1063" ], "Notes": "Broke in SDV 1.2." }, { "Name": "CJB Cheats Menu", - "ID": [ "CJBCheatsMenu" ], + "ID": "CJBCheatsMenu", "UpperVersion": "1.12", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/4" ], "Notes": "Broke in SDV 1.1." }, { "Name": "CJB Item Spawner", - "ID": [ "CJBItemSpawner" ], + "ID": "CJBItemSpawner", "UpperVersion": "1.5", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/93" ], "Notes": "Broke in SDV 1.1." }, { "Name": "CJB Show Item Sell Price", - "ID": [ "CJBShowItemSellPrice" ], + "ID": "CJBShowItemSellPrice", "UpperVersion": "1.6", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/93" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Climates of Ferngill", - "ID": [ "KoihimeNakamura.ClimatesOfFerngill" ], + "ID": "KoihimeNakamura.ClimatesOfFerngill", "UpperVersion": "1.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/604", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Cold Weather Haley", - "ID": [ "LordXamon.ColdWeatherHaleyPRO" ], + "ID": "LordXamon.ColdWeatherHaleyPRO", "UpperVersion": "1.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/1169", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Colored Chests", - "ID": [ "4befde5c-731c-4853-8e4b-c5cdf946805f" ], + "ID": "4befde5c-731c-4853-8e4b-c5cdf946805f", "Status": "Obsolete", "ReasonPhrase": "colored chests were added in Stardew Valley 1.1." }, { "Name": "Combat with Farm Implements", - "ID": [ "SPDFarmingImplementsInCombat" ], + "ID": "SPDFarmingImplementsInCombat", "UpperVersion": "1.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/313", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Configurable Shipping Dates", - "ID": [ "ConfigurableShippingDates" ], + "ID": "ConfigurableShippingDates", "UpperVersion": "1.1.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/675", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Cooking Skill", - "ID": [ "CookingSkill", /*since 1.0.4–6*/ "spacechase0.CookingSkill" ], + "ID": "CookingSkill | spacechase0.CookingSkill", // changed in 1.0.4–6 "UpperVersion": "1.0.6", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/522" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "CrabNet", - "ID": [ "CrabNet.dll" ], + "ID": "CrabNet.dll", "UpperVersion": "1.0.4", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/584", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Customize Exterior", - "ID": [ "CustomizeExterior" ], + "ID": "CustomizeExterior", "UpperVersion": "1.0.2", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/1099" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Customizable Traveling Cart Days", - "ID": [ "TravelingCartYyeahdude" ], + "ID": "TravelingCartYyeahdude", "UpperVersion": "1.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/567", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Daily News", - "ID": [ "bashNinja.DailyNews" ], + "ID": "bashNinja.DailyNews", "UpperVersion": "1.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/1141", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Dynamic Checklist", - "ID": [ "gunnargolf.DynamicChecklist" ], + "ID": "gunnargolf.DynamicChecklist", "UpperVersion": "1.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/1145", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Dynamic Machines", - "ID": [ "DynamicMachines" ], + "ID": "DynamicMachines", "UpperVersion": "1.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/374", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Empty Hands", - "ID": [ "QuicksilverFox.EmptyHands" ], + "ID": "QuicksilverFox.EmptyHands", "UpperVersion": "1.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/1176", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Enemy Health Bars", - "ID": [ "SPDHealthBar" ], + "ID": "SPDHealthBar", "UpperVersion": "1.7", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/193", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Entoarox Framework", - "ID": [ "eacdb74b-4080-4452-b16b-93773cda5cf9", /*since ???*/ "Entoarox.EntoaroxFramework" ], + "ID": "eacdb74b-4080-4452-b16b-93773cda5cf9 | Entoarox.EntoaroxFramework", // changed in ??? "UpperVersion": "1.7.9", "UpdateUrls": [ "http://community.playstarbound.com/resources/4228" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Extended Fridge", - "ID": [ "Mystra007ExtendedFridge" ], + "ID": "Mystra007ExtendedFridge", "UpperVersion": "1.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/485", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Extended Greenhouse", - "ID": [ "ExtendedGreenhouse" ], + "ID": "ExtendedGreenhouse", "UpperVersion": "1.0.2", "UpdateUrls": [ "http://community.playstarbound.com/resources/4303", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Fall 28 Snow Day", - "ID": [ "{ID:'7ad4f6f7-c3de-4729-a40f-7a11d2b2a358', Name:'Fall28 Snow Day'}" ], // disambiguate from other mods by Alpha_Omegasis + "ID": "{ID:'7ad4f6f7-c3de-4729-a40f-7a11d2b2a358', Name:'Fall28 Snow Day'}", // disambiguate from other mods by Alpha_Omegasis "UpperVersion": "1.3", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/486", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Farm Automation: Barn Door Automation", - "ID": [ "FarmAutomation.BarnDoorAutomation.dll" ], + "ID": "FarmAutomation.BarnDoorAutomation.dll", "UpperVersion": "1.0", "UpdateUrls": [ "http://community.playstarbound.com/threads/111931", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Farm Automation: Item Collector", - "ID": [ "FarmAutomation.ItemCollector.dll" ], + "ID": "FarmAutomation.ItemCollector.dll", "UpperVersion": "1.0", "UpdateUrls": [ "http://community.playstarbound.com/threads/111931", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Farm Automation Unofficial: Item Collector", - "ID": [ "Maddy99.FarmAutomation.ItemCollector" ], + "ID": "Maddy99.FarmAutomation.ItemCollector", "UpperVersion": "0.5", "UpdateUrls": [ "http://community.playstarbound.com/threads/125172", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Farm Expansion", - "ID": [ "3888bdfd-73f6-4776-8bb7-8ad45aea1915", /*since 2.0*/ "AdvizeFarmExpansionMod-2-0", /*since 2.0.5*/ "AdvizeFarmExpansionMod-2-0-5" ], + "ID": "3888bdfd-73f6-4776-8bb7-8ad45aea1915 | AdvizeFarmExpansionMod-2-0 | AdvizeFarmExpansionMod-2-0-5", // changed in 2.0 and 2.0.5 "UpperVersion": "2.0.5", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/130", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Farm Resource Generator", - "ID": [ "FarmResourceGenerator.dll" ], + "ID": "FarmResourceGenerator.dll", "UpperVersion": "1.0.4", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/647", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Faster Run", - "ID": [ "FasterRun.dll" ], + "ID": "FasterRun.dll", "UpperVersion": "1.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/733", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "FlorenceMod", - "ID": [ "FlorenceMod.dll" ], + "ID": "FlorenceMod.dll", "UpperVersion": "1.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/591", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Forage at the Farm", - "ID": [ "ForageAtTheFarm" ], + "ID": "ForageAtTheFarm", "UpperVersion": "1.5.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/673", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Instant Geode", - "ID": [ "InstantGeode" ], + "ID": "InstantGeode", "UpperVersion": "1.12", "UpdateUrls": [ "http://community.playstarbound.com/threads/109038", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Gate Opener", - "ID": [ "GateOpener.dll", /*since 1.1*/ "mralbobo.GateOpener" ], + "ID": "GateOpener.dll | mralbobo.GateOpener", // changed in 1.1 "UpperVersion": "1.0.1", "UpdateUrls": [ "http://community.playstarbound.com/threads/111988" ], "Notes": "Broke in SDV 1.2." }, { "Name": "GenericShopExtender", - "ID": [ "GenericShopExtender" ], + "ID": "GenericShopExtender", "UpperVersion": "0.1.2", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/814", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Get Dressed", - "ID": [ "GetDressed.dll", /*since 3.3*/ "Advize.GetDressed" ], + "ID": "GetDressed.dll | Advize.GetDressed", // changed in 3.3 "UpperVersion": "3.3", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/331" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Gift Taste Helper", - "ID": [ "8008db57-fa67-4730-978e-34b37ef191d6" ], + "ID": "8008db57-fa67-4730-978e-34b37ef191d6", "UpperVersion": "2.3.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/229" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Happy Animals", - "ID": [ "HappyAnimals" ], + "ID": "HappyAnimals", "UpperVersion": "1.0.3", "UpdateUrls": [ "https://community.playstarbound.com/threads/126655", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Happy Birthday", - "ID": [ "{ID:'HappyBirthday', Author:'Alpha_Omegasis'}" ], // disambiguate from Oxyligen's fork + "ID": "{ID:'HappyBirthday', Author:'Alpha_Omegasis'}", // disambiguate from Oxyligen's fork "UpperVersion": "1.3", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/520", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Harvest With Scythe", - "ID": [ "965169fd-e1ed-47d0-9f12-b104535fb4bc" ], + "ID": "965169fd-e1ed-47d0-9f12-b104535fb4bc", "UpperVersion": "1.0.6", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/236", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Hunger for Food", - "ID": [ "HungerForFoodByTigerle" ], + "ID": "HungerForFoodByTigerle", "UpperVersion": "0.1.2", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/810", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Improved Quality of Life", - "ID": [ "Demiacle.ImprovedQualityOfLife" ], + "ID": "Demiacle.ImprovedQualityOfLife", "UpperVersion": "1.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/1025", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Less Strict Over-Exertion (AntiExhaustion)", - "ID": [ "BALANCEMOD_AntiExhaustion" ], + "ID": "BALANCEMOD_AntiExhaustion", "UpperVersion": "1.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/637", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Lookup Anything", - "ID": [ "LookupAnything", /*since 1.10.1*/ "Pathoschild.LookupAnything" ], + "ID": "LookupAnything | Pathoschild.LookupAnything", // changed in 1.10.1 "UpperVersion": "1.10.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/541" ], "Notes": "Broke in SDV 1.2." }, { "Name": "Loved Labels", - "ID": [ "LovedLabels.dll" ], + "ID": "LovedLabels.dll", "UpperVersion": "2.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/279" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Luck Skill", - "ID": [ "LuckSkill", /*since 0.1.4*/ "spacechase0.LuckSkill" ], + "ID": "LuckSkill | spacechase0.LuckSkill", // changed in 0.1.4 "UpperVersion": "0.1.4", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/521" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "MailOrderPigs", - "ID": [ "MailOrderPigs.dll" ], + "ID": "MailOrderPigs.dll", "UpperVersion": "1.0.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/632", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Makeshift Multiplayer", - "ID": [ "StardewValleyMP", /*since 0.3*/ "spacechase0.StardewValleyMP" ], + "ID": "StardewValleyMP | spacechase0.StardewValleyMP", // changed in 0.3 "UpperVersion": "0.3.6", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/501", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Message Box [API]? (ChatMod)", - "ID": [ "Kithio:ChatMod" ], + "ID": "Kithio:ChatMod", "UpperVersion": "1.0", "UpdateUrls": [ "http://community.playstarbound.com/resources/message-box-api.4296", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Modder Serialization Utility", - "ID": [ "SerializerUtils-0-1" ], + "ID": "SerializerUtils-0-1", "Status": "Obsolete", "ReasonPhrase": "it's no longer maintained or used." }, { "Name": "More Artifact Spots", - "ID": [ "451" ], + "ID": "451", "UpperVersion": "1.0.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/451", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "More Pets", - "ID": [ "821ce8f6-e629-41ad-9fde-03b54f68b0b6MOREPETS", /* since 1.3 */ "Entoarox.MorePets" ], + "ID": "821ce8f6-e629-41ad-9fde-03b54f68b0b6MOREPETS | Entoarox.MorePets", // changed in 1.3 "UpperVersion": "1.3.2", "UpdateUrls": [ "http://community.playstarbound.com/resources/4288" ], "Notes": "Overhauled for SMAPI 1.11+ compatibility." }, { "Name": "More Rain", - "ID": [ "{ID:'4108e859-333c-4fec-a1a7-d2e18c1019fe', Name:'More_Rain'}" ], // disambiguate from other mods by Alpha_Omegasis + "ID": "{ID:'4108e859-333c-4fec-a1a7-d2e18c1019fe', Name:'More_Rain'}", // disambiguate from other mods by Alpha_Omegasis "UpperVersion": "1.4", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/441", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Multiple Sprites and Portraits On Rotation (File Loading)", - "ID": [ "FileLoading" ], + "ID": "FileLoading", "UpperVersion": "1.12", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/1094", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Museum Rearranger", - "ID": [ "{ID:'7ad4f6f7-c3de-4729-a40f-7a11d2b2a358', Name:'Museum Rearranger'}" ], // disambiguate from other mods by Alpha_Omegasis + "ID": "{ID:'7ad4f6f7-c3de-4729-a40f-7a11d2b2a358', Name:'Museum Rearranger'}", // disambiguate from other mods by Alpha_Omegasis "UpperVersion": "1.3", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/428", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "New Machines", - "ID": [ "F70D4FAB-0AB2-4B78-9F1B-AF2CA2236A59" ], + "ID": "F70D4FAB-0AB2-4B78-9F1B-AF2CA2236A59", "UpperVersion": "4.2.1343", "UpdateUrls": [ "http://community.playstarbound.com/resources/3683", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Night Owl", - "ID": [ "{'ID':'SaveAnywhere', 'Name':'Stardew_NightOwl'}" ], // disambiguate from Save Anywhere + "ID": "{ID:'SaveAnywhere', Name:'Stardew_NightOwl'}", // disambiguate from Save Anywhere "UpperVersion": "2.1", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/433", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "No Debug Mode", - "ID": [ "NoDebugMode" ], + "ID": "NoDebugMode", "Status": "Obsolete", "ReasonPhrase": "debug mode was removed in SMAPI 1.0." }, { "Name": "NoSoilDecay", - "ID": [ "289dee03-5f38-4d8e-8ffc-e440198e8610" ], + "ID": "289dee03-5f38-4d8e-8ffc-e440198e8610", "UpperVersion": "0.5", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/237", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.2, and uses Assembly.GetExecutingAssembly().Location." }, { "Name": "NPC Map Locations", - "ID": [ "NPCMapLocationsMod" ], + "ID": "NPCMapLocationsMod", "LowerVersion": "1.42", "UpperVersion": "1.43", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/239" ], @@ -577,293 +577,293 @@ This file contains advanced configuration for SMAPI. You generally shouldn't cha }, { "Name": "NPC Speak", - "ID": [ "NpcEcho.dll" ], + "ID": "NpcEcho.dll", "UpperVersion": "1.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/694", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0" }, { "Name": "OmniFarm", - "ID": [ "BlueMod_OmniFarm" ], + "ID": "BlueMod_OmniFarm", "UpperVersion": "2.0.1", "UpdateUrls": [ "http://community.playstarbound.com/threads/127299", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0" }, { "Name": "Part of the Community", - "ID": [ "SB_PotC" ], + "ID": "SB_PotC", "UpperVersion": "1.0.8", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/923" ], "Notes": "Broke in SDV 1.2." }, { "Name": "PelicanFiber", - "ID": [ "PelicanFiber.dll" ], + "ID": "PelicanFiber.dll", "UpperVersion": "3.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/631", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "PelicanTTS", - "ID": [ "Platonymous.PelicanTTS" ], + "ID": "Platonymous.PelicanTTS", "UpperVersion": "1.6", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/1079", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "Persival's BundleMod", - "ID": [ "BundleMod.dll" ], + "ID": "BundleMod.dll", "UpperVersion": "1.0", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/438", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.1." }, { "Name": "Point-and-Plant", - "ID": [ "PointAndPlant.dll" ], + "ID": "PointAndPlant.dll", "UpperVersion": "1.0.2", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/572", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.2." }, { "Name": "PrairieKingMadeEasy", - "ID": [ "PrairieKingMadeEasy.dll" ], + "ID": "PrairieKingMadeEasy.dll", "UpperVersion": "1.0", "UpdateUrls": [ "http://community.playstarbound.com/resources/3594", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SDV 1.2." }, { "Name": "RainRandomizer", - "ID": [ "RainRandomizer.dll" ], + "ID": "RainRandomizer.dll", "UpperVersion": "1.0.3", "UpdateUrls": [ "http://community.playstarbound.com/threads/111526", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "RelationshipsEnhanced", - "ID": [ "relationshipsenhanced" ], + "ID": "relationshipsenhanced", "UpperVersion": "1.0", "UpdateUrls": [ "http://community.playstarbound.com/resources/4435", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke in SMAPI 2.0." }, { "Name": "RelationShipStatus", - "ID": [ "relationshipstatus" ], + "ID": "relationshipstatus", "UpperVersion": "1.0.5", "UpdateUrls": [ "http://www.nexusmods.com/stardewvalley/mods/751", "http://stardewvalleywiki.com/Modding:SMAPI_2.0" ], "Notes": "Broke i |
