summaryrefslogtreecommitdiff
path: root/src/SMAPI
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI')
-rw-r--r--src/SMAPI/Framework/IModMetadata.cs2
-rw-r--r--src/SMAPI/Framework/ModLoading/ModMetadata.cs4
-rw-r--r--src/SMAPI/Framework/ModLoading/ModResolver.cs24
-rw-r--r--src/SMAPI/Framework/Models/ModCompatibility.cs55
-rw-r--r--src/SMAPI/Framework/Models/ModDataField.cs82
-rw-r--r--src/SMAPI/Framework/Models/ModDataFieldKey.cs18
-rw-r--r--src/SMAPI/Framework/Models/ModDataID.cs85
-rw-r--r--src/SMAPI/Framework/Models/ModDataRecord.cs220
-rw-r--r--src/SMAPI/Framework/Models/ParsedModDataRecord.cs48
-rw-r--r--src/SMAPI/Framework/Serialisation/SmapiConverters/ModCompatibilityArrayConverter.cs61
-rw-r--r--src/SMAPI/Framework/Serialisation/SmapiConverters/ModDataIdConverter.cs19
-rw-r--r--src/SMAPI/Program.cs2
-rw-r--r--src/SMAPI/StardewModdingAPI.config.json1731
-rw-r--r--src/SMAPI/StardewModdingAPI.csproj7
14 files changed, 1095 insertions, 1263 deletions
diff --git a/src/SMAPI/Framework/IModMetadata.cs b/src/SMAPI/Framework/IModMetadata.cs
index a36994fd..41484567 100644
--- a/src/SMAPI/Framework/IModMetadata.cs
+++ b/src/SMAPI/Framework/IModMetadata.cs
@@ -19,7 +19,7 @@ namespace StardewModdingAPI.Framework
IManifest Manifest { get; }
/// <summary>>Metadata about the mod from SMAPI's internal data (if any).</summary>
- ModDataRecord DataRecord { get; }
+ ParsedModDataRecord DataRecord { get; }
/// <summary>The metadata resolution status.</summary>
ModMetadataStatus Status { get; }
diff --git a/src/SMAPI/Framework/ModLoading/ModMetadata.cs b/src/SMAPI/Framework/ModLoading/ModMetadata.cs
index 30fe211b..1a71920e 100644
--- a/src/SMAPI/Framework/ModLoading/ModMetadata.cs
+++ b/src/SMAPI/Framework/ModLoading/ModMetadata.cs
@@ -18,7 +18,7 @@ namespace StardewModdingAPI.Framework.ModLoading
public IManifest Manifest { get; }
/// <summary>Metadata about the mod from SMAPI's internal data (if any).</summary>
- public ModDataRecord DataRecord { get; }
+ public ParsedModDataRecord DataRecord { get; }
/// <summary>The metadata resolution status.</summary>
public ModMetadataStatus Status { get; private set; }
@@ -41,7 +41,7 @@ namespace StardewModdingAPI.Framework.ModLoading
/// <param name="directoryPath">The mod's full directory path.</param>
/// <param name="manifest">The mod manifest.</param>
/// <param name="dataRecord">Metadata about the mod from SMAPI's internal data (if any).</param>
- public ModMetadata(string displayName, string directoryPath, IManifest manifest, ModDataRecord dataRecord)
+ public ModMetadata(string displayName, string directoryPath, IManifest manifest, ParsedModDataRecord dataRecord)
{
this.DisplayName = displayName;
this.DirectoryPath = directoryPath;
diff --git a/src/SMAPI/Framework/ModLoading/ModResolver.cs b/src/SMAPI/Framework/ModLoading/ModResolver.cs
index 9802d9e9..6671e880 100644
--- a/src/SMAPI/Framework/ModLoading/ModResolver.cs
+++ b/src/SMAPI/Framework/ModLoading/ModResolver.cs
@@ -53,18 +53,15 @@ namespace StardewModdingAPI.Framework.ModLoading
error = $"parsing its manifest failed:\n{ex.GetLogSummary()}";
}
- // get internal data record (if any)
- ModDataRecord dataRecord = null;
+ // parse internal data record (if any)
+ ParsedModDataRecord dataRecord = null;
if (manifest != null)
{
- string key = !string.IsNullOrWhiteSpace(manifest.UniqueID) ? manifest.UniqueID : manifest.EntryDll;
- dataRecord = dataRecords.FirstOrDefault(record => record.ID.Matches(key, manifest));
+ ModDataRecord rawDataRecord = dataRecords.FirstOrDefault(p => p.Matches(manifest));
+ if (rawDataRecord != null)
+ dataRecord = rawDataRecord.ParseFieldsFor(manifest);
}
- // add default update keys
- if (manifest != null && manifest.UpdateKeys == null && dataRecord?.UpdateKeys != null)
- manifest.UpdateKeys = dataRecord.UpdateKeys;
-
// build metadata
string displayName = !string.IsNullOrWhiteSpace(manifest?.Name)
? manifest.Name
@@ -93,17 +90,16 @@ namespace StardewModdingAPI.Framework.ModLoading
continue;
// validate compatibility
- ModCompatibility compatibility = mod.DataRecord?.GetCompatibility(mod.Manifest.Version);
- switch (compatibility?.Status)
+ switch (mod.DataRecord?.Status)
{
case ModStatus.Obsolete:
- mod.SetStatus(ModMetadataStatus.Failed, $"it's obsolete: {compatibility.ReasonPhrase}");
+ mod.SetStatus(ModMetadataStatus.Failed, $"it's obsolete: {mod.DataRecord.StatusReasonPhrase}");
continue;
case ModStatus.AssumeBroken:
{
// get reason
- string reasonPhrase = compatibility.ReasonPhrase ?? "it's no longer compatible";
+ string reasonPhrase = mod.DataRecord.StatusReasonPhrase ?? "it's no longer compatible";
// get update URLs
List<string> updateUrls = new List<string>();
@@ -124,10 +120,10 @@ namespace StardewModdingAPI.Framework.ModLoading
// build error
string error = $"{reasonPhrase}. Please check for a ";
- if (mod.Manifest.Version.Equals(compatibility.UpperVersion))
+ if (mod.DataRecord.StatusUpperVersion == null || mod.Manifest.Version.Equals(mod.DataRecord.StatusUpperVersion))
error += "newer version";
else
- error += $"version newer than {compatibility.UpperVersion}";
+ error += $"version newer than {mod.DataRecord.StatusUpperVersion}";
error += " at " + string.Join(" or ", updateUrls);
mod.SetStatus(ModMetadataStatus.Failed, error);
diff --git a/src/SMAPI/Framework/Models/ModCompatibility.cs b/src/SMAPI/Framework/Models/ModCompatibility.cs
deleted file mode 100644
index 54737e6c..00000000
--- a/src/SMAPI/Framework/Models/ModCompatibility.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using System;
-
-namespace StardewModdingAPI.Framework.Models
-{
- /// <summary>Specifies the compatibility of a given mod version range.</summary>
- internal class ModCompatibility
- {
- /*********
- ** Accessors
- *********/
- /// <summary>The lowest version in the range, or <c>null</c> for all past versions.</summary>
- public ISemanticVersion LowerVersion { get; }
-
- /// <summary>The highest version in the range, or <c>null</c> for all future versions.</summary>
- public ISemanticVersion UpperVersion { get; }
-
- /// <summary>The mod compatibility.</summary>
- public ModStatus Status { get; }
-
- /// <summary>The reason phrase to show in log output, or <c>null</c> to use the default value.</summary>
- /// <example>For example, "this version is incompatible with the latest version of the game".</example>
- public string ReasonPhrase { get; }
-
-
- /*********
- ** Public methods
- *********/
- /// <summary>Construct an instance.</summary>
- /// <param name="versionRange">A version range, which consists of two version strings separated by a '~' character. Either side can be left blank for an unbounded range.</param>
- /// <param name="status">The mod compatibility.</param>
- /// <param name="reasonPhrase">The reason phrase to show in log output, or <c>null</c> to use the default value.</param>
- public ModCompatibility(string versionRange, ModStatus status, string reasonPhrase)
- {
- // extract version strings
- string[] versions = versionRange.Split('~');
- if (versions.Length != 2)
- throw new FormatException($"Could not parse '{versionRange}' as a version range. It must have two version strings separated by a '~' character (either side can be left blank for an unbounded range).");
-
- // initialise
- this.LowerVersion = !string.IsNullOrWhiteSpace(versions[0]) ? new SemanticVersion(versions[0]) : null;
- this.UpperVersion = !string.IsNullOrWhiteSpace(versions[1]) ? new SemanticVersion(versions[1]) : null;
- this.Status = status;
- this.ReasonPhrase = reasonPhrase;
- }
-
- /// <summary>Get whether a given version is contained within this compatibility range.</summary>
- /// <param name="version">The version to check.</param>
- public bool MatchesVersion(ISemanticVersion version)
- {
- return
- (this.LowerVersion == null || !version.IsOlderThan(this.LowerVersion))
- && (this.UpperVersion == null || !version.IsNewerThan(this.UpperVersion));
- }
- }
-}
diff --git a/src/SMAPI/Framework/Models/ModDataField.cs b/src/SMAPI/Framework/Models/ModDataField.cs
new file mode 100644
index 00000000..0812b39b
--- /dev/null
+++ b/src/SMAPI/Framework/Models/ModDataField.cs
@@ -0,0 +1,82 @@
+using System.Linq;
+
+namespace StardewModdingAPI.Framework.Models
+{
+ /// <summary>A versioned mod metadata field.</summary>
+ internal class ModDataField
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The field key.</summary>
+ public ModDataFieldKey Key { get; }
+
+ /// <summary>The field value.</summary>
+ public string Value { get; }
+
+ /// <summary>Whether this field should only be applied if it's not already set.</summary>
+ public bool IsDefault { get; }
+
+ /// <summary>The lowest version in the range, or <c>null</c> for all past versions.</summary>
+ public ISemanticVersion LowerVersion { get; }
+
+ /// <summary>The highest version in the range, or <c>null</c> for all future versions.</summary>
+ public ISemanticVersion UpperVersion { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="key">The field key.</param>
+ /// <param name="value">The field value.</param>
+ /// <param name="isDefault">Whether this field should only be applied if it's not already set.</param>
+ /// <param name="lowerVersion">The lowest version in the range, or <c>null</c> for all past versions.</param>
+ /// <param name="upperVersion">The highest version in the range, or <c>null</c> for all future versions.</param>
+ 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;
+ }
+
+ /// <summary>Get whether this data field applies for the given manifest.</summary>
+ /// <param name="manifest">The mod manifest.</param>
+ 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
+ *********/
+ /// <summary>Get whether a manifest field has a meaningful value for the purposes of enforcing <see cref="IsDefault"/>.</summary>
+ /// <param name="manifest">The mod manifest.</param>
+ /// <param name="key">The field key matching <see cref="ModDataFieldKey"/>.</param>
+ private bool HasFieldValue(IManifest manifest, ModDataFieldKey key)
+ {
+ switch (key)
+ {
+ // update key
+ case ModDataFieldKey.UpdateKey:
+ return manifest.UpdateKeys != null && manifest.UpdateKeys.Any();
+
+ // non-manifest fields
+ case ModDataFieldKey.AlternativeUrl:
+ case ModDataFieldKey.StatusReasonPhrase:
+ case ModDataFieldKey.Status:
+ return false;
+
+ default:
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/Models/ModDataFieldKey.cs b/src/SMAPI/Framework/Models/ModDataFieldKey.cs
new file mode 100644
index 00000000..5767afc9
--- /dev/null
+++ b/src/SMAPI/Framework/Models/ModDataFieldKey.cs
@@ -0,0 +1,18 @@
+namespace StardewModdingAPI.Framework.Models
+{
+ /// <summary>The valid field keys.</summary>
+ public enum ModDataFieldKey
+ {
+ /// <summary>A manifest update key.</summary>
+ UpdateKey,
+
+ /// <summary>An alternative URL the player can check for an updated version.</summary>
+ AlternativeUrl,
+
+ /// <summary>The mod's predefined compatibility status.</summary>
+ Status,
+
+ /// <summary>A reason phrase for the <see cref="Status"/>, or <c>null</c> to use the default reason.</summary>
+ StatusReasonPhrase
+ }
+}
diff --git a/src/SMAPI/Framework/Models/ModDataID.cs b/src/SMAPI/Framework/Models/ModDataID.cs
deleted file mode 100644
index d19434fa..00000000
--- a/src/SMAPI/Framework/Models/ModDataID.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-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
- {
- /*********
- ** Properties
- *********/
- /// <summary>The unique sets of field values which identify this mod.</summary>
- private readonly FieldSnapshot[] Snapshots;
-
-
- /*********
- ** Public methods
- *********/
- /// <summary>Construct an instance.</summary>
- public ModDataID() { }
-
- /// <summary>Construct an instance.</summary>
- /// <param name="data">The mod identifier string (see remarks on <see cref="ModDataID"/>).</param>
- public ModDataID(string 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>
- /// <param name="id">The mod's unique ID, or a substitute ID if it isn't set in the manifest.</param>
- /// <param name="manifest">The manifest to check.</param>
- public bool Matches(string id, IManifest manifest)
- {
- return this.Snapshots.Any(snapshot =>
- snapshot.ID.Equals(id, 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))
- )
- && (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/SMAPI/Framework/Models/ModDataRecord.cs b/src/SMAPI/Framework/Models/ModDataRecord.cs
index 580acb70..2c26741c 100644
--- a/src/SMAPI/Framework/Models/ModDataRecord.cs
+++ b/src/SMAPI/Framework/Models/ModDataRecord.cs
@@ -1,49 +1,188 @@
+using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
+using System.Runtime.Serialization;
using Newtonsoft.Json;
-using StardewModdingAPI.Framework.Serialisation.SmapiConverters;
+using Newtonsoft.Json.Linq;
namespace StardewModdingAPI.Framework.Models
{
- /// <summary>Metadata about a mod from SMAPI's internal data.</summary>
+ /// <summary>Raw mod metadata from SMAPI's internal mod list.</summary>
internal class ModDataRecord
{
/*********
- ** Accessors
+ ** Properties
*********/
- /// <summary>The unique mod identifier.</summary>
- [JsonConverter(typeof(ModDataIdConverter))]
- public ModDataID ID { get; set; }
+ /// <summary>This field stores properties that aren't mapped to another field before they're parsed into <see cref="Fields"/>.</summary>
+ [JsonExtensionData]
+ private IDictionary<string, JToken> ExtensionData;
- /// <summary>A value to inject into <see cref="IManifest.UpdateKeys"/> field if it's not already set.</summary>
- public string[] UpdateKeys { get; set; }
- /// <summary>The URL where the player can get an unofficial or alternative version of the mod if the official version isn't compatible.</summary>
- public string AlternativeUrl { get; set; }
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The mod's current unique ID.</summary>
+ public string ID { get; set; }
- /// <summary>The compatibility of given mod versions (if any).</summary>
- [JsonConverter(typeof(ModCompatibilityArrayConverter))]
- public ModCompatibility[] Compatibility { get; set; } = new ModCompatibility[0];
+ /// <summary>The former mod IDs (if any).</summary>
+ /// <remarks>
+ /// This uses a custom format which uniquely identifies a mod across multiple versions and
+ /// supports matching other fields if no ID was specified. This doesn't include the latest
+ /// ID, if any. Format rules:
+ /// 1. If the mod's ID changed over time, multiple variants can be separated by the
+ /// <c>|</c> character.
+ /// 2. Each variant can take one of two forms:
+ /// - A simple string matching the mod's UniqueID value.
+ /// - A JSON structure containing any of four manifest fields (ID, Name, Author, and
+ /// EntryDll) to match.
+ /// </remarks>
+ public string FormerIDs { get; set; }
- /// <summary>Map local versions to a semantic version for update checks.</summary>
+ /// <summary>Maps local versions to a semantic version for update checks.</summary>
public IDictionary<string, string> MapLocalVersions { get; set; } = new Dictionary<string, string>();
- /// <summary>Map remote versions to a semantic version for update checks.</summary>
+ /// <summary>Maps remote versions to a semantic version for update checks.</summary>
public IDictionary<string, string> MapRemoteVersions { get; set; } = new Dictionary<string, string>();
+ /// <summary>The versioned field data.</summary>
+ /// <remarks>
+ /// This maps field names to values. This should be accessed via <see cref="GetFields"/>.
+ /// Format notes:
+ /// - Each key consists of a field name prefixed with any combination of version range
+ /// and <c>Default</c>, separated by pipes (whitespace trimmed). For example, <c>Name</c>
+ /// will always override the name, <c>Default | Name</c> will only override a blank
+ /// name, and <c>~1.1 | Default | Name</c> will override blank names up to version 1.1.
+ /// - The version format is <c>min~max</c> (where either side can be blank for unbounded), or
+ /// a single version number.
+ /// - The field name itself corresponds to a <see cref="ModDataFieldKey"/> value.
+ /// </remarks>
+ public IDictionary<string, string> Fields { get; set; } = new Dictionary<string, string>();
+
/*********
** Public methods
*********/
- /// <summary>Get the compatibility record for a given version, if any.</summary>
- /// <param name="version">The mod version to check.</param>
- public ModCompatibility GetCompatibility(ISemanticVersion version)
+ /// <summary>Get whether the manifest matches the <see cref="FormerIDs"/> field.</summary>
+ /// <param name="manifest">The mod manifest to check.</param>
+ public bool Matches(IManifest manifest)
+ {
+ // try main ID
+ if (this.ID != null && this.ID.Equals(manifest.UniqueID, StringComparison.InvariantCultureIgnoreCase))
+ return true;
+
+ // try former IDs
+ if (this.FormerIDs != null)
+ {
+ foreach (string part in this.FormerIDs.Split('|'))
+ {
+ // packed field snapshot
+ if (part.StartsWith("{"))
+ {
+ FieldSnapshot snapshot = JsonConvert.DeserializeObject<FieldSnapshot>(part);
+ bool isMatch =
+ (snapshot.ID == null || snapshot.ID.Equals(manifest.UniqueID, StringComparison.InvariantCultureIgnoreCase))
+ && (snapshot.EntryDll == null || snapshot.EntryDll.Equals(manifest.EntryDll, 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))
+ )
+ && (snapshot.Name == null || snapshot.Name.Equals(manifest.Name, StringComparison.InvariantCultureIgnoreCase));
+
+ if (isMatch)
+ return true;
+ }
+
+ // plain ID
+ else if (part.Equals(manifest.UniqueID, StringComparison.InvariantCultureIgnoreCase))
+ return true;
+ }
+ }
+
+ // no match
+ return false;
+ }
+
+ /// <summary>Get a parsed representation of the <see cref="Fields"/>.</summary>
+ public IEnumerable<ModDataField> GetFields()
{
- return this.Compatibility.FirstOrDefault(p => p.MatchesVersion(version));
+ foreach (KeyValuePair<string, string> pair in this.Fields)
+ {
+ // init fields
+ string packedKey = pair.Key;
+ string value = pair.Value;
+ bool isDefault = false;
+ ISemanticVersion lowerVersion = null;
+ ISemanticVersion upperVersion = null;
+
+ // parse
+ string[] parts = packedKey.Split('|').Select(p => p.Trim()).ToArray();
+ ModDataFieldKey fieldKey = (ModDataFieldKey)Enum.Parse(typeof(ModDataFieldKey), parts.Last(), ignoreCase: true);
+ foreach (string part in parts.Take(parts.Length - 1))
+ {
+ // 'default'
+ if (part.Equals("Default", StringComparison.InvariantCultureIgnoreCase))
+ {
+ isDefault = true;
+ continue;
+ }
+
+ // version range
+ if (part.Contains("~"))
+ {
+ string[] versionParts = part.Split(new[] { '~' }, 2);
+ lowerVersion = versionParts[0] != "" ? new SemanticVersion(versionParts[0]) : null;
+ upperVersion = versionParts[1] != "" ? new SemanticVersion(versionParts[1]) : null;
+ continue;
+ }
+
+ // single version
+ lowerVersion = new SemanticVersion(part);
+ upperVersion = new SemanticVersion(part);
+ }
+
+ yield return new ModDataField(fieldKey, value, isDefault, lowerVersion, upperVersion);
+ }
+ }
+
+ /// <summary>Get a parsed representation of the <see cref="Fields"/> which match a given manifest.</summary>
+ /// <param name="manifest">The manifest to match.</param>
+ public ParsedModDataRecord ParseFieldsFor(IManifest manifest)
+ {
+ ParsedModDataRecord parsed = new ParsedModDataRecord { DataRecord = this };
+ foreach (ModDataField field in this.GetFields().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;
}
/// <summary>Get a semantic local version for update checks.</summary>
- /// <param name="version">The local version to normalise.</param>
+ /// <param name="version">The remote version to normalise.</param>
public string GetLocalVersionForUpdateChecks(string version)
{
return this.MapLocalVersions != null && this.MapLocalVersions.TryGetValue(version, out string newVersion)
@@ -59,5 +198,46 @@ namespace StardewModdingAPI.Framework.Models
? newVersion
: version;
}
+
+
+ /*********
+ ** Private methods
+ *********/
+ /// <summary>The method invoked after JSON deserialisation.</summary>
+ /// <param name="context">The deserialisation context.</param>
+ [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;
+ }
+ }
+
+
+ /*********
+ ** Private models
+ *********/
+ /// <summary>A unique set of fields which identifies the mod.</summary>
+ [SuppressMessage("ReSharper", "ClassNeverInstantiated.Local", Justification = "Used via JSON deserialisation.")]
+ [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local", Justification = "Used via JSON deserialisation.")]
+ private class FieldSnapshot
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The unique mod ID (or <c>null</c> to ignore it).</summary>
+ public string ID { get; set; }
+
+ /// <summary>The entry DLL (or <c>null</c> to ignore it).</summary>
+ public string EntryDll { get; set; }
+
+ /// <summary>The mod name (or <c>null</c> to ignore it).</summary>
+ public string Name { get; set; }
+
+ /// <summary>The author name (or <c>null</c> to ignore it).</summary>
+ public string Author { get; set; }
+ }
}
}
diff --git a/src/SMAPI/Framework/Models/ParsedModDataRecord.cs b/src/SMAPI/Framework/Models/ParsedModDataRecord.cs
new file mode 100644
index 00000000..0abc7b89
--- /dev/null
+++ b/src/SMAPI/Framework/Models/ParsedModDataRecord.cs
@@ -0,0 +1,48 @@
+namespace StardewModdingAPI.Framework.Models
+{
+ /// <summary>A parsed representation of the fields from a <see cref="ModDataRecord"/> for a specific manifest.</summary>
+ internal class ParsedModDataRecord
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The underlying data record.</summary>
+ public ModDataRecord DataRecord { get; set; }
+
+ /// <summary>The update key to apply.</summary>
+ public string UpdateKey { get; set; }
+
+ /// <summary>The mod version to apply.</summary>
+ public ISemanticVersion Version { get; set; }
+
+ /// <summary>The alternative URL the player can check for an updated version.</summary>
+ public string AlternativeUrl { get; set; }
+
+ /// <summary>The predefined compatibility status.</summary>
+ public ModStatus Status { get; set; } = ModStatus.None;
+
+ /// <summary>A reason phrase for the <see cref="Status"/>, or <c>null</c> to use the default reason.</summary>
+ public string StatusReasonPhrase { get; set; }
+
+ /// <summary>The upper version for which the <see cref="Status"/> applies (if any).</summary>
+ public ISemanticVersion StatusUpperVersion { get; set; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Get a semantic local version for update checks.</summary>
+ /// <param name="version">The remote version to normalise.</param>
+ public string GetLocalVersionForUpdateChecks(string version)
+ {
+ return this.DataRecord.GetLocalVersionForUpdateChecks(version);
+ }
+
+ /// <summary>Get a semantic remote version for update checks.</summary>
+ /// <param name="version">The remote version to normalise.</param>
+ public string GetRemoteVersionForUpdateChecks(string version)
+ {
+ return this.DataRecord.GetRemoteVersionForUpdateChecks(version);
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/Serialisation/SmapiConverters/ModCompatibilityArrayConverter.cs b/src/SMAPI/Framework/Serialisation/SmapiConverters/ModCompatibilityArrayConverter.cs
deleted file mode 100644
index 3232dde4..00000000
--- a/src/SMAPI/Framework/Serialisation/SmapiConverters/ModCompatibilityArrayConverter.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using StardewModdingAPI.Framework.Models;
-
-namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters
-{
- /// <summary>Handles deserialisation of <see cref="ModCompatibility"/> arrays.</summary>
- internal class ModCompatibilityArrayConverter : JsonConverter
- {
- /*********
- ** Accessors
- *********/
- /// <summary>Whether this converter can write JSON.</summary>
- public override bool CanWrite => false;
-
-
- /*********
- ** Public methods
- *********/
- /// <summary>Get whether this instance can convert the specified object type.</summary>
- /// <param name="objectType">The object type.</param>
- public override bool CanConvert(Type objectType)
- {
- return objectType == typeof(ModCompatibility[]);
- }
-
-
- /*********
- ** Protected methods
- *********/
- /// <summary>Read the JSON representation of the object.</summary>
- /// <param name="reader">The JSON reader.</param>
- /// <param name="objectType">The object type.</param>
- /// <param name="existingValue">The object being read.</param>
- /// <param name="serializer">The calling serializer.</param>
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
- {
- List<ModCompatibility> result = new List<ModCompatibility>();
- foreach (JProperty property in JObject.Load(reader).Properties())
- {
- string range = property.Name;
- ModStatus status = (ModStatus)Enum.Parse(typeof(ModStatus), property.Value.Value<string>(nameof(ModCompatibility.Status)));
- string reasonPhrase = property.Value.Value<string>(nameof(ModCompatibility.ReasonPhrase));
-
- result.Add(new ModCompatibility(range, status, reasonPhrase));
- }
- return result.ToArray();
- }
-
- /// <summary>Writes the JSON representation of the object.</summary>
- /// <param name="writer">The JSON writer.</param>
- /// <param name="value">The value.</param>
- /// <param name="serializer">The calling serializer.</param>
- public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
- {
- throw new InvalidOperationException("This converter does not write JSON.");
- }
- }
-}
diff --git a/src/SMAPI/Framework/Serialisation/SmapiConverters/ModDataIdConverter.cs b/src/SMAPI/Framework/Serialisation/SmapiConverters/ModDataIdConverter.cs
deleted file mode 100644
index 8a10db47..00000000
--- a/src/SMAPI/Framework/Serialisation/SmapiConverters/ModDataIdConverter.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using StardewModdingAPI.Framework.Models;
-
-namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters
-{
- /// <summary>Handles deserialisation of <see cref="ModDataID"/>.</summary>
- internal class ModDataIdConverter : SimpleReadOnlyConverter<ModDataID>
- {
- /*********
- ** Protected methods
- *********/
- /// <summary>Read a JSON string.</summary>
- /// <param name="str">The JSON string value.</param>
- /// <param name="path">The path to the current JSON node.</param>
- protected override ModDataID ReadString(string str, string path)
- {
- return new ModDataID(str);
- }
- }
-}
diff --git a/src/SMAPI/Program.cs b/src/SMAPI/Program.cs
index c7da581d..b5ce3033 100644
--- a/src/SMAPI/Program.cs
+++ b/src/SMAPI/Program.cs
@@ -679,7 +679,7 @@ namespace StardewModdingAPI
Assembly modAssembly;
try
{
- modAssembly = modAssemblyLoader.Load(metadata, assemblyPath, assumeCompatible: metadata.DataRecord?.GetCompatibility(metadata.Manifest.Version)?.Status == ModStatus.AssumeCompatible);
+ modAssembly = modAssemblyLoader.Load(metadata, assemblyPath, assumeCompatible: metadata.DataRecord?.Status == ModStatus.AssumeCompatible);
}
catch (IncompatibleInstructionException ex)
{
diff --git a/src/SMAPI/StardewModdingAPI.config.json b/src/SMAPI/StardewModdingAPI.config.json
index 18a9f978..ca0c20b1 100644
--- a/src/SMAPI/StardewModdingAPI.config.json
+++ b/src/SMAPI/StardewModdingAPI.config.json
@@ -39,2041 +39,1770 @@ This file contains advanced configuration for SMAPI. You generally shouldn't cha
"VerboseLogging": false,
/**
- * Extra metadata about some SMAPI mods. All fields except 'ID' are optional.
+ * Metadata about some SMAPI mods used in compatibility, update, and dependency checks. This
+ * field shouldn't be edited by players in most cases.
*
- * - 'ID' uniquely identifies the mod across all versions, even if its manifest fields changed or
- * the mod doesn't have a unique ID. The format is as follows:
- * - If the mod's identifier changed over time, multiple variants are separated by |.
- * - Each variant can take one of two forms: a simple string matching the mod's UniqueID,
- * or a JSON structure containing any of three manifest fields (ID, Name, and Author) to
- * match.
+ * Standard fields
+ * ===============
+ * The predefined fields are documented below (only 'ID' is required).
*
- * - 'UpdateKeys' specifies the value of the equivalent manifest field if it's not already set.
- * This is used to enable update checks for older mods that haven't been updated to use it yet.
+ * - ID: the mod's latest unique ID (if any).
*
- * - 'AlternativeUrl' specifies a URL where the player can find an unofficial update or
- * alternative if the mod is no longer compatible.
+ * - FormerIDs: uniquely identifies the mod across multiple versions, and supports matching
+ * other fields if no ID was specified. This doesn't include the latest ID, if any.
+ * Format rules:
+ * 1. If the mod's ID changed over time, multiple variants can be separated by the '|'
+ * character.
+ * 2. Each variant can take one of two forms:
+ * - A simple string matching the mod's UniqueID value.
+ * - A JSON structure containing any of four manifest fields (ID, Name, Author, and
+ * EntryDll) to match.
*
- * - 'Compatibility' overrides SMAPI's normal compatibility detection. The keys are version
- * ranges in the form lower~upper, where either side can be blank for an unbounded range. (For
- * example, "~1.0" means all versions up to 1.0 inclusively.) The values have two fields:
- * - 'Status' specifies the compatibility. Valid values are Obsolete (SMAPI won't load it
- * because the mod should no longer be used), AssumeBroken (SMAPI won't load it because
- * the specified version isn't compatible), or AssumeCompatible (SMAPI will load it even
- * if it detects incompatible code).
- * - 'ReasonPhrase' (optional) specifies a message to show to the player explaining why the
- * mod isn't loaded. This has no effect for AssumeCompatible.
+ * - MapLocalVersions and MapRemoteVersions crrect local manifest versions and remote versions
+ * during update checks. For example, if the API returns version '1.1-1078' where '1078' is
+ * intended to be a build number, MapRemoteVersions can map it to '1.1' when comparing to the
+ * mod's current version. This is only meant to support legacy mods with injected update keys.
*
- * - 'MapLocalVersions' and 'MapRemoteVersions' substitute versions for update checks. For
- * example, if the API returns version '1.1-1078', MapRemoteVersions can map it to '1.1' when
- * comparing to the mod's current version. This is only intended to support legacy mods with
- * injected update keys.
+ * Versioned metadata
+ * ==================
+ * Each record can also specify extra metadata using the field keys below.
+ *
+ * Each key consists of a field name prefixed with any combination of version range and 'Default',
+ * separated by pipes (whitespace trimmed). For example, 'UpdateKey' will always override,
+ * 'Default | UpdateKey' will only override if the mod has no update keys, and
+ * '~1.1 | Default | Name' will do the same up to version 1.1.
+ *
+ * The version format is 'min~max' (where either side can be blank for unbounded), or a single
+ * version number.
+ *
+ * These are the valid field names:
+ *
+ * - UpdateKey: the update key to set in the mod's manifest. This is used to enable update
+ * checks for older mods that haven't been updated to use it yet.
+ *
+ * - Status: overrides compatibility checks. The possible values are Obsolete (SMAPI won't load
+ * it because the mod should no longer be used), AssumeBroken (SMAPI won't load it because
+ * the specified version isn't compatible), or AssumeCompatible (SMAPI will try to load it
+ * even if it detects incompatible code).
+ *
+ * - StatusReasonPhrase: a message to show to the player explaining why the mod can't be loaded
+ * (if applicable). If blank, will default to a generic not-compatible message.
+ *
+ * - AlternativeUrl: a URL where the player can find an unofficial update or alternative if the
+ * mod is no longer compatible.
*/
"ModData": [
{
// AccessChestAnywhere
"ID": "AccessChestAnywhere",
- "UpdateKeys": [ "Nexus:257" ],
- "AlternativeUrl": "https://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.1": { "Status": "AssumeBroken" } // broke in SDV 1.1
- },
- "MapLocalVersions": {
- "1.1-1078": "1.1"
- }
+ "MapLocalVersions": { "1.1-1078": "1.1" },
+ "Default | UpdateKey": "Nexus:257",
+ "~1.1 | Status": "AssumeBroken",
+ "~1.1 | AlternativeUrl": "https://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// AdjustArtisanPrices
"ID": "1e36d4ca-c7ef-4dfb-9927-d27a6c3c8bdc",
- "UpdateKeys": [ "Chucklefish:3532" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~0.1": { "Status": "AssumeBroken" } // broke in SMAPI 1.9
- }
+ "Default | UpdateKey": "Chucklefish:3532",
+ "~0.1 | Status": "AssumeBroken",
+ "~0.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Adjust Monster
"ID": "mmanlapat.AdjustMonster",
- "UpdateKeys": [ "Nexus:1161" ]
+ "Default | UpdateKey": "Nexus:1161"
},
{
// Advanced Location Loader
"ID": "Entoarox.AdvancedLocationLoader",
- //"UpdateKeys": [ "Chucklefish:3619" ], // Entoarox opted out of mod update checks
- "Compatibility": {
- "~1.2.10": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ //"Default | UpdateKey": "Chucklefish:3619", // Entoarox opted out of mod update checks
+ "~1.2.10 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Adventure Shop Inventory
"ID": "HammurabiAdventureShopInventory",
- "UpdateKeys": [ "Chucklefish:4608" ]
+ "Default | UpdateKey": "Chucklefish:4608"
},
{
// AgingMod
"ID": "skn.AgingMod",
- "UpdateKeys": [ "Nexus:1129" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:1129",
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// All Crops All Seasons
- "ID": "29ee8246-d67b-4242-a340-35a9ae0d5dd7 | community.AllCropsAllSeasons", // changed in 1.3
- "UpdateKeys": [ "Nexus:170" ]
+ "ID": "community.AllCropsAllSeasons",
+ "FormerIDs": "29ee8246-d67b-4242-a340-35a9ae0d5dd7", // changed in 1.3
+ "Default | UpdateKey": "Nexus:170"
},
{
// All Professions
- "ID": "8c37b1a7-4bfb-4916-9d8a-9533e6363ea3 | community.AllProfessions", // changed in 1.2
- "UpdateKeys": [ "Nexus:174" ]
+ "ID": "community.AllProfessions",
+ "FormerIDs": "8c37b1a7-4bfb-4916-9d8a-9533e6363ea3", // changed in 1.2
+ "Default | UpdateKey": "Nexus:174"
},
{
// Almighty Tool
- "ID": "AlmightyTool.dll | 439", // changed in 1.2.1
- "UpdateKeys": [ "Nexus:439" ],
- "Compatibility": {
- "~1.1.1": { "Status": "AssumeBroken" } // broke in SDV 1.2
- },
- "MapRemoteVersions": {
- "1.21": "1.2.1"
- }
+ "ID": "439",
+ "FormerIDs": "{EntryDLL: 'AlmightyTool.dll'}", // changed in 1.2.1
+ "MapRemoteVersions": { "1.21": "1.2.1" },
+ "Default | UpdateKey": "Nexus:439",
+ "~1.1.1 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Animal Mood Fix
"ID": "GPeters-AnimalMoodFix",
- "Compatibility": {
- "~": {
- "Status": "Obsolete",
- "ReasonPhrase": "the animal mood bugs were fixed in Stardew Valley 1.2."
- }
- }
+ "~ | Status": "Obsolete",
+ "~ | StatusReasonPhrase": "the animal mood bugs were fixed in Stardew Valley 1.2."
},
{
// Animal Sitter
- "ID": "AnimalSitter.dll | jwdred.AnimalSitter", // changed in 1.0.9
- "UpdateKeys": [ "Nexus:581" ],
- "Compatibility": {
- "~1.0.8": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "jwdred.AnimalSitter",
+ "FormerIDs": "{EntryDLL: 'AnimalSitter.dll'}", // changed in 1.0.9
+ "Default | UpdateKey": "Nexus:581",
+ "~1.0.8 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// A Tapper's Dream
"ID": "ddde5195-8f85-4061-90cc-0d4fd5459358",
- "UpdateKeys": [ "Nexus:260" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.4": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:260",
+ "~1.4 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.4 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Auto Animal Doors
"ID": "AaronTaggart.AutoAnimalDoors",
- "UpdateKeys": [ "Nexus:1019" ],
- "MapRemoteVersions": {
- "1.1.1": "1.1" // manifest not updated
- }
+ "MapRemoteVersions": { "1.1.1": "1.1" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:1019"
},
{
// Auto-Eat
- "ID": "BALANCEMOD_AutoEat | Permamiss.AutoEat", // changed in 1.1.1
- "UpdateKeys": [ "Nexus:643" ]
+ "ID": "Permamiss.AutoEat",
+ "FormerIDs": "BALANCEMOD_AutoEat", // changed in 1.1.1
+ "Default | UpdateKey": "Nexus:643"
},
{
// AutoGate
"ID": "AutoGate",
- "UpdateKeys": [ "Nexus:820" ]
+ "Default | UpdateKey": "Nexus:820"
},
{
// Automate
"ID": "Pathoschild.Automate",
- "UpdateKeys": [ "Nexus:1063" ]
+ "Default | UpdateKey": "Nexus:1063"
},
{
// Automated Doors
- "ID": "1abcfa07-2cf4-4dc3-a6e9-6068b642112b | azah.automated-doors", // changed in 1.4.1
- "UpdateKeys": [ "GitHub:azah/AutomatedDoors" ],
- "MapLocalVersions": {
- "1.4.1-1": "1.4.1"
- }
+ "ID": "azah.automated-doors",
+ "FormerIDs": "1abcfa07-2cf4-4dc3-a6e9-6068b642112b", // changed in 1.4.1
+ "MapLocalVersions": { "1.4.1-1": "1.4.1" },
+ "Default | UpdateKey": "GitHub:azah/AutomatedDoors"
},
{
// AutoSpeed
- "ID": "{ID:'4be88c18-b6f3-49b0-ba96-f94b1a5be890', Name:'AutoSpeed'} | Omegasis.AutoSpeed", // changed in 1.4; disambiguate from other Alpha_Omegasis mods
- "UpdateKeys": [ "Nexus:443" ] // added in 1.4.1
+ "ID": "Omegasis.AutoSpeed",
+ "FormerIDs": "{ID:'4be88c18-b6f3-49b0-ba96-f94b1a5be890', Name:'AutoSpeed'}", // changed in 1.4; disambiguate from other Alpha_Omegasis mods
+ "Default | UpdateKey": "Nexus:443" // added in 1.4.1
},
{
// Basic Sprinkler Improved
"ID": "lrsk_sdvm_bsi.0117171308",
- "UpdateKeys": [ "Nexus:833" ],
- "MapRemoteVersions": {
- "1.0.2": "1.0.1-release" // manifest not updated
- }
+ "MapRemoteVersions": { "1.0.2": "1.0.1-release" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:833"
},
{
// Better Hay
"ID": "cat.betterhay",
- "UpdateKeys": [ "Nexus:1430" ]
+ "Default | UpdateKey": "Nexus:1430"
},
{
// Better Quality More Seasons
"ID": "SB_BQMS",
- "UpdateKeys": [ "Nexus:935" ]
+ "Default | UpdateKey": "Nexus:935"
},
{
// Better Quarry
"ID": "BetterQuarry",
- "UpdateKeys": [ "Nexus:771" ]
+ "Default | UpdateKey": "Nexus:771"
},
{
// Better Ranching
"ID": "BetterRanching",
- "UpdateKeys": [ "Nexus:859" ]
+ "Default | UpdateKey": "Nexus:859"
},
{
// Better Shipping Box
"ID": "Kithio:BetterShippingBox",
- "UpdateKeys": [ "Chucklefish:4302" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.2": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapLocalVersions": {
- "1.0.1": "1.0.2"
- }
+ "MapLocalVersions": { "1.0.1": "1.0.2" },
+ "Default | UpdateKey": "Chucklefish:4302",
+ "~1.0.2 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.2 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Better Sprinklers
- "ID": "SPDSprinklersMod | Speeder.BetterSprinklers", // changed in 2.3
- "UpdateKeys": [ "Nexus:41" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~2.3.1-pathoschild-update": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Speeder.BetterSprinklers",
+ "FormerIDs": "SPDSprinklersMod", // changed in 2.3
+ "Default | UpdateKey": "Nexus:41",
+ "~2.3.1-pathoschild-update | Status": "AssumeBroken", // broke in SDV 1.2
+ "~2.3.1-pathoschild-update | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Billboard Anywhere
- "ID": "{ID:'7ad4f6f7-c3de-4729-a40f-7a11d2b2a358', Name:'Billboard Anywhere'} | Omegasis.BillboardAnywhere", // changed in 1.4; disambiguate from other mods by Alpha_Omegasis
- "UpdateKeys": [ "Nexus:492" ] // added in 1.4.1
+ "ID": "Omegasis.BillboardAnywhere",
+ "FormerIDs": "{ID:'7ad4f6f7-c3de-4729-a40f-7a11d2b2a358', Name:'Billboard Anywhere'}", // changed in 1.4; disambiguate from other mods by Alpha_Omegasis
+ "Default | UpdateKey": "Nexus:492" // added in 1.4.1
},
{
// Birthday Mail
- "ID": "005e02dc-d900-425c-9c68-1ff55c5a295d | KathrynHazuka.BirthdayMail", // changed in 1.2.3-pathoschild-update
- "UpdateKeys": [ "Nexus:276" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.2.2": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "KathrynHazuka.BirthdayMail",
+ "FormerIDs": "005e02dc-d900-425c-9c68-1ff55c5a295d", // changed in 1.2.3-pathoschild-update
+ "Default | UpdateKey": "Nexus:276",
+ "~1.2.2 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.2.2 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Breed Like Rabbits
"ID": "dycedarger.breedlikerabbits",
- "UpdateKeys": [ "Nexus:948" ]
+ "Default | UpdateKey": "Nexus:948"
},
{
// Build Endurance
- "ID": "{ID:'4be88c18-b6f3-49b0-ba96-f94b1a5be890', Name:'BuildEndurance'} | Omegasis.BuildEndurance", // changed in 1.4; disambiguate from other Alpha_Omegasis mods
- "UpdateKeys": [ "Nexus:445" ], // added in 1.4.1
- "Compatibility": {
- "~1.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Omegasis.BuildEndurance",
+ "FormerIDs": "{ID:'4be88c18-b6f3-49b0-ba96-f94b1a5be890', Name:'BuildEndurance'}", // changed in 1.4; disambiguate from other Alpha_Omegasis mods
+ "Default | UpdateKey": "Nexus:445", // added in 1.4.1
+ "~1.3 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Build Health
- "ID": "{ID:'4be88c18-b6f3-49b0-ba96-f94b1a5be890', Name:'BuildHealth'} | Omegasis.BuildHealth", // changed in 1.4; disambiguate from other Alpha_Omegasis mods
- "UpdateKeys": [ "Nexus:446" ], // added in 1.4.1
- "Compatibility": {
- "~1.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Omegasis.BuildHealth",
+ "FormerIDs": "{ID:'4be88c18-b6f3-49b0-ba96-f94b1a5be890', Name:'BuildHealth'}", // changed in 1.4; disambiguate from other Alpha_Omegasis mods
+ "Default | UpdateKey": "Nexus:446", // added in 1.4.1
+ "~1.3 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Butcher Mod
"ID": "DIGUS.BUTCHER",
- "UpdateKeys": [ "Nexus:1538" ]
+ "Default | UpdateKey": "Nexus:1538"
},
{
// Buy Cooking Recipes
"ID": "Denifia.BuyRecipes",
- "UpdateKeys": [ "Nexus:1126" ], // added in 1.0.1 (2017-10-04)
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:1126", // added in 1.0.1 (2017-10-04)
+ "~1.0 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Buy Back Collectables
- "ID": "BuyBackCollectables | Omegasis.BuyBackCollectables", // changed in 1.4
- "UpdateKeys": [ "Nexus:507" ], // added in 1.4.1
- "Compatibility": {
- "~1.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Omegasis.BuyBackCollectables",
+ "FormerIDs": "BuyBackCollectables", // changed in 1.4
+ "Default | UpdateKey": "Nexus:507", // added in 1.4.1
+ "~1.3 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Carry Chest
"ID": "spacechase0.CarryChest",
- "UpdateKeys": [ "Nexus:1333" ]
+ "Default | UpdateKey": "Nexus:1333"
},
{
// Casks Anywhere
"ID": "CasksAnywhere",
- "UpdateKeys": [ "Nexus:878" ],
- "MapLocalVersions": {
- "1.1-alpha": "1.1"
- }
+ "MapLocalVersions": { "1.1-alpha": "1.1" },
+ "Default | UpdateKey": "Nexus:878"
},
{
// Categorize Chests
"ID": "CategorizeChests",
- "UpdateKeys": [ "Nexus:1300" ]
+ "Default | UpdateKey": "Nexus:1300"
},
{
// ChefsCloset
"ID": "Duder.ChefsCloset",
- "UpdateKeys": [ "Nexus:1030" ],
- "MapLocalVersions": {
- "1.3-1": "1.3"
- }
+ "MapLocalVersions": { "1.3-1": "1.3" },
+ "Default | UpdateKey": "Nexus:1030"
},
{
// Chest Label System
- "ID": "SPDChestLabel | Speeder.ChestLabel", // changed in 1.5.1-pathoschild-update
- "UpdateKeys": [ "Nexus:242" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.6": { "Status": "AssumeBroken" } // broke in SDV 1.1
- }
+ "ID": "Speeder.ChestLabel",
+ "FormerIDs": "SPDChestLabel", // changed in 1.5.1-pathoschild-update
+ "Default | UpdateKey": "Nexus:242",
+ "~1.6 | Status": "AssumeBroken", // broke in SDV 1.1
+ "~1.6 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Chest Pooling
- "ID": "ChestPooling.dll | mralbobo.ChestPooling", // changed in 1.3
- "UpdateKeys": [ "GitHub:mralbobo/stardew-chest-pooling" ],
- "Compatibility": {
- "~1.2": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "mralbobo.ChestPooling",
+ "FormerIDs": "{EntryDLL: 'ChestPooling.dll'}", // changed in 1.3
+ "Default | UpdateKey": "GitHub:mralbobo/stardew-chest-pooling",
+ "~1.2 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Chests Anywhere
- "ID": "ChestsAnywhere | Pathoschild.ChestsAnywhere", // changed in 1.9
- "UpdateKeys": [ "Nexus:518" ],
- "Compatibility": {
- "~1.9-beta": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Pathoschild.ChestsAnywhere",
+ "FormerIDs": "ChestsAnywhere", // changed in 1.9
+ "Default | UpdateKey": "Nexus:518",
+ "~1.9-beta | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Choose Baby Gender
"ID": "ChooseBabyGender.dll",
- "UpdateKeys": [ "Nexus:590" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.2": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:590",
+ "~1.0.2 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.2 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// CJB Automation
"ID": "CJBAutomation",
- "UpdateKeys": [ "Nexus:211" ],
- "AlternativeUrl": "http://www.nexusmods.com/stardewvalley/mods/1063",
- "Compatibility": {
- "~1.4": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "Default | UpdateKey": "Nexus:211",
+ "~1.4 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.4 | AlternativeUrl": "http://www.nexusmods.com/stardewvalley/mods/1063"
},
{
// CJB Cheats Menu
- "ID": "CJBCheatsMenu | CJBok.CheatsMenu", // changed in 1.14
- "UpdateKeys": [ "Nexus:4" ],
- "Compatibility": {
- "~1.12": { "Status": "AssumeBroken" } // broke in SDV 1.1
- }
+ "ID": "CJBok.CheatsMenu",
+ "FormerIDs": "CJBCheatsMenu", // changed in 1.14
+ "Default | UpdateKey": "Nexus:4",
+ "~1.12 | Status": "AssumeBroken" // broke in SDV 1.1
},
{
// CJB Item Spawner
- "ID": "CJBItemSpawner | CJBok.ItemSpawner", // changed in 1.7
- "UpdateKeys": [ "Nexus:93" ],
- "Compatibility": {
- "~1.5": { "Status": "AssumeBroken" } // broke in SDV 1.1
- }
+ "ID": "CJBok.ItemSpawner",
+ "FormerIDs": "CJBItemSpawner", // changed in 1.7
+ "Default | UpdateKey": "Nexus:93",
+ "~1.5 | Status": "AssumeBroken" // broke in SDV 1.1
},
{
// CJB Show Item Sell Price
- "ID": "CJBShowItemSellPrice | CJBok.ShowItemSellPrice", // changed in 1.7
- "UpdateKeys": [ "Nexus:5" ],
- "Compatibility": {
- "~1.6": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "CJBok.ShowItemSellPrice",
+ "FormerIDs": "CJBShowItemSellPrice", // changed in 1.7
+ "Default | UpdateKey": "Nexus:5",
+ "~1.6 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Clean Farm
"ID": "tstaples.CleanFarm",
- "UpdateKeys": [ "Nexus:794" ]
+ "Default | UpdateKey": "Nexus:794"
},
{
// Climates of Ferngill
"ID": "KoihimeNakamura.ClimatesOfFerngill",
- "UpdateKeys": [ "Nexus:604" ],
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:604",
+ "~1.0 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Cold Weather Haley
"ID": "LordXamon.ColdWeatherHaleyPRO",
- "UpdateKeys": [ "Nexus:1169" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:1169",
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Colored Chests
"ID": "4befde5c-731c-4853-8e4b-c5cdf946805f",
- "Compatibility": {
- "~": {
- "Status": "Obsolete",
- "ReasonPhrase": "colored chests were added in Stardew Valley 1.1."
- }
- }
+ "~ | Status": "Obsolete",
+ "~ | StatusReasonPhrase": "colored chests were added in Stardew Valley 1.1."
},
{
// Combat with Farm Implements
"ID": "SPDFarmingImplementsInCombat",
- "UpdateKeys": [ "Nexus:313" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:313",
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Community Bundle Item Tooltip
"ID": "musbah.bundleTooltip",
- "UpdateKeys": [ "Nexus:1329" ]
+ "Default | UpdateKey": "Nexus:1329"
},
{
// Concentration on Farming
"ID": "punyo.ConcentrationOnFarming",
- "UpdateKeys": [ "Nexus:1445" ]
+ "Default | UpdateKey": "Nexus:1445"
},
{
// Configurable Machines
"ID": "21da6619-dc03-4660-9794-8e5b498f5b97",
- "UpdateKeys": [ "Nexus:280" ],
- "MapLocalVersions": {
- "1.2-beta": "1.2"
- }
+ "MapLocalVersions": { "1.2-beta": "1.2" },
+ "Default | UpdateKey": "Nexus:280"
},
{
// Configurable Shipping Dates
"ID": "ConfigurableShippingDates",
- "UpdateKeys": [ "Nexus:675" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.1.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:675",
+ "~1.1.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.1.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Cooking Skill
- "ID": "CookingSkill | spacechase0.CookingSkill", // changed in 1.0.4–6
- "UpdateKeys": [ "Nexus:522" ],
- "Compatibility": {
- "~1.0.6": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "spacechase0.CookingSkill",
+ "FormerIDs": "CookingSkill", // changed in 1.0.4–6
+ "Default | UpdateKey": "Nexus:522",
+ "~1.0.6 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// CrabNet
- "ID": "CrabNet.dll | jwdred.CrabNet", // changed in 1.0.5
- "UpdateKeys": [ "Nexus:584" ],
- "Compatibility": {
- "~1.0.4": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "jwdred.CrabNet",
+ "FormerIDs": "{EntryDLL: 'CrabNet.dll'}", // changed in 1.0.5
+ "Default | UpdateKey": "Nexus:584",
+ "~1.0.4 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Current Location
"ID": "CurrentLocation102120161203",
- "UpdateKeys": [ "Nexus:638" ]
+ "Default | UpdateKey": "Nexus:638"
},
{
// Custom Critters
"ID": "spacechase0.CustomCritters",
- "UpdateKeys": [ "Nexus:1255" ]
+ "Default | UpdateKey": "Nexus:1255"
},
{
// Custom Element Handler
"ID": "Platonymous.CustomElementHandler",
- "UpdateKeys": [ "Nexus:1068" ] // added in 1.3.1
+ "Default | UpdateKey": "Nexus:1068" // added in 1.3.1
},
{
// Custom Farming
"ID": "Platonymous.CustomFarming",
- "UpdateKeys": [ "Nexus:991" ] // added in 0.6.1
+ "Default | UpdateKey": "Nexus:991" // added in 0.6.1
},
{
// Custom Farming Automate Bridge
"ID": "Platonymous.CFAutomate",
- "Compatibility": {
- "~1.0.1": { "Status": "AssumeBroken" } // no longer compatible with Automate
- },
- "AlternativeUrl": "https://www.nexusmods.com/stardewvalley/mods/991"
+ "~1.0.1 | Status": "AssumeBroken", // no longer compatible with Automate
+ "~1.0.1 | AlternativeUrl": "https://www.nexusmods.com/stardewvalley/mods/991"
},
{
// Custom Farm Types
"ID": "spacechase0.CustomFarmTypes",
- "UpdateKeys": [ "Nexus:1140" ]
+ "Default | UpdateKey": "Nexus:1140"
},
{
// Custom Furniture
"ID": "Platonymous.CustomFurniture",
- "UpdateKeys": [ "Nexus:1254" ] // added in 0.4.1
+ "Default | UpdateKey": "Nexus:1254" // added in 0.4.1
},
{
// Customize Exterior
- "ID": "CustomizeExterior | spacechase0.CustomizeExterior", // changed in 1.0.3
- "UpdateKeys": [ "Nexus:1099" ],
- "Compatibility": {
- "~1.0.2": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "spacechase0.CustomizeExterior",
+ "FormerIDs": "CustomizeExterior", // changed in 1.0.3
+ "Default | UpdateKey": "Nexus:1099",
+ "~1.0.2 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Customizable Cart Redux
"ID": "KoihimeNakamura.CCR",
- "UpdateKeys": [ "Nexus:1402" ],
- "MapLocalVersions": {
- "1.1-20170917": "1.1"
- }
+ "MapLocalVersions": { "1.1-20170917": "1.1" },
+ "Default | UpdateKey": "Nexus:1402"
},
{
// Customizable Traveling Cart Days
"ID": "TravelingCartYyeahdude",
- "UpdateKeys": [ "Nexus:567" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:567",
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Custom Linens
"ID": "Mevima.CustomLinens",
- "UpdateKeys": [ "Nexus:1027" ],
- "MapRemoteVersions": {
- "1.1": "1.0" // manifest not updated
- }
+ "MapRemoteVersions": { "1.1": "1.0" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:1027"
},
{
// Custom Shops Redux
"ID": "Omegasis.CustomShopReduxGui",
- "UpdateKeys": [ "Nexus:1378" ] // added in 1.4.1
+ "Default | UpdateKey": "Nexus:1378" // added in 1.4.1
},
{
// Custom TV
"ID": "Platonymous.CustomTV",
- "UpdateKeys": [ "Nexus:1139" ] // added in 1.0.6
+ "Default | UpdateKey": "Nexus:1139" // added in 1.0.6
},
{
// Daily Luck Message
"ID": "Schematix.DailyLuckMessage",
- "UpdateKeys": [ "Nexus:1327" ]
+ "Default | UpdateKey": "Nexus:1327"
},
{
// Daily News
"ID": "bashNinja.DailyNews",
- "UpdateKeys": [ "Nexus:1141" ],
- "Compatibility": {
- "~1.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:1141",
+ "~1.1 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Daily Quest Anywhere
- "ID": "DailyQuest | Omegasis.DailyQuestAnywhere", // changed in 1.4
- "UpdateKeys": [ "Nexus:513" ] // added in 1.4.1
+ "ID": "Omegasis.DailyQuestAnywhere",
+ "FormerIDs": "DailyQuest", // changed in 1.4
+ "Default | UpdateKey": "Nexus:513" // added in 1.4.1
},
{
// Debug Mode
- "ID": "Pathoschild.Stardew.DebugMode | Pathoschild.DebugMode", // changed in 1.4
- "UpdateKeys": [ "Nexus:679" ]
+ "ID": "Pathoschild.DebugMode",
+ "FormerIDs": "Pathoschild.Stardew.DebugMode", // changed in 1.4
+ "Default | UpdateKey": "Nexus:679"
},
{
// Dynamic Checklist
"ID": "gunnargolf.DynamicChecklist",
- "UpdateKeys": [ "Nexus:1145" ], // added in 1.0.1-pathoschild-update
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:1145", // added in 1.0.1-pathoschild-update
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Dynamic Horses
"ID": "Bpendragon-DynamicHorses",
- "UpdateKeys": [ "Nexus:874" ],
- "MapRemoteVersions": {
- "1.2": "1.1-release" // manifest not updated
- }
+ "MapRemoteVersions": { "1.2": "1.1-release" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:874"
},
{
// Dynamic Machines
"ID": "DynamicMachines",
- "UpdateKeys": [ "Nexus:374" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.1.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapLocalVersions": {
- "1.1": "1.1.1"
- }
+ "MapLocalVersions": { "1.1": "1.1.1" },
+ "Default | UpdateKey": "Nexus:374",
+ "~1.1.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.1.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Dynamic NPC Sprites
"ID": "BashNinja.DynamicNPCSprites",
- "UpdateKeys": [ "Nexus:1183" ]
+ "Default | UpdateKey": "Nexus:1183"
},
{
// Easier Farming
"ID": "cautiouswafffle.EasierFarming",
- "UpdateKeys": [ "Nexus:1426" ]
+ "Default | UpdateKey": "Nexus:1426"
},
{
// Empty Hands
"ID": "QuicksilverFox.EmptyHands",
- "UpdateKeys": [ "Nexus:1176" ], // added in 1.0.1-pathoschild-update
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:1176", // added in 1.0.1-pathoschild-update
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Enemy Health Bars
- "ID": "SPDHealthBar | Speeder.HealthBars", // changed in 1.7.1-pathoschild-update
- "UpdateKeys": [ "Nexus:193" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.7": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Speeder.HealthBars",
+ "FormerIDs": "SPDHealthBar", // changed in 1.7.1-pathoschild-update
+ "Default | UpdateKey": "Nexus:193",
+ "~1.7 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.7 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Entoarox Framework
- "ID": "eacdb74b-4080-4452-b16b-93773cda5cf9 | Entoarox.EntoaroxFramework", // changed in ???
- //"UpdateKeys": [ "Chucklefish:4228" ], // Entoarox opted out of mod update checks
- "Compatibility": {
- "~1.7.9": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Entoarox.EntoaroxFramework",
+ "FormerIDs": "eacdb74b-4080-4452-b16b-93773cda5cf9", // changed in ???
+ //"Default | UpdateKey": "Chucklefish:4228", // Entoarox opted out of mod update checks
+ "~1.7.9 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Expanded Fridge / Dynamic Expanded Fridge
"ID": "Uwazouri.ExpandedFridge",
- "UpdateKeys": [ "Nexus:1191" ]
+ "Default | UpdateKey": "Nexus:1191"
},
{
// Experience Bars
- "ID": "ExperienceBars | spacechase0.ExperienceBars", // changed in 1.0.2
- "UpdateKeys": [ "Nexus:509" ]
+ "ID": "spacechase0.ExperienceBars",
+ "FormerIDs": "ExperienceBars", // changed in 1.0.2
+ "Default | UpdateKey": "Nexus:509"
},
{
// Extended Bus System
"ID": "ExtendedBusSystem",
- "UpdateKeys": [ "Chucklefish:4373" ]
+ "Default | UpdateKey": "Chucklefish:4373"
},
{
// Extended Fridge
- "ID": "Mystra007ExtendedFridge | Crystalmir.ExtendedFridge", // changed in 1.0.1
- "UpdateKeys": [ "Nexus:485" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Crystalmir.ExtendedFridge",
+ "FormerIDs": "Mystra007ExtendedFridge", // changed in 1.0.1
+ "Default | UpdateKey": "Nexus:485",
+ "~1.0 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Extended Greenhouse
"ID": "ExtendedGreenhouse",
- "UpdateKeys": [ "Chucklefish:4303" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.2": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "Default | UpdateKey": "Chucklefish:4303",
+ "~1.0.2 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.0.2 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Extended Minecart
- "ID": "{ID:'EntoaroxFurnitureAnywhere', Name:'Extended Minecart'} | Entoarox.ExtendedMinecart" // changed in 1.6.1
- //"UpdateKeys": [ "Chucklefish:4359" ] // Entoarox opted out of mod update checks
+ "ID": "Entoarox.ExtendedMinecart",
+ "FormerIDs": "{ID:'EntoaroxFurnitureAnywhere', Name:'Extended Minecart'}" // changed in 1.6.1
+ //"Default | UpdateKey": "Chucklefish:4359" // Entoarox opted out of mod update checks
},
{
// Extended Reach
"ID": "spacechase0.ExtendedReach",
- "UpdateKeys": [ "Nexus:1493" ]
+ "Default | UpdateKey": "Nexus:1493"
},
{
// Fall 28 Snow Day
- "ID": "{ID:'7ad4f6f7-c3de-4729-a40f-7a11d2b2a358', Name:'Fall28 Snow Day'} | Omegasis.Fall28SnowDay", // changed in 1.4; disambiguate from other mods by Alpha_Omegasis
- "UpdateKeys": [ "Nexus:486" ], // added in 1.4.1
- "Compatibility": {
- "~1.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Omegasis.Fall28SnowDay",
+ "FormerIDs": "{ID:'7ad4f6f7-c3de-4729-a40f-7a11d2b2a358', Name:'Fall28 Snow Day'}", // changed in 1.4; disambiguate from other mods by Alpha_Omegasis
+ "Default | UpdateKey": "Nexus:486", // added in 1.4.1
+ "~1.3 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Farm Automation: Barn Door Automation
"ID": "FarmAutomation.BarnDoorAutomation.dll",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Farm Automation: Item Collector
"ID": "FarmAutomation.ItemCollector.dll",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "~1.0 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Farm Automation Unofficial: Item Collector
"ID": "Maddy99.FarmAutomation.ItemCollector",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~0.5": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "~0.5 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~0.5 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Farm Expansion
- "ID": "3888bdfd-73f6-4776-8bb7-8ad45aea1915 | AdvizeFarmExpansionMod-2-0 | AdvizeFarmExpansionMod-2-0-5 | Advize.FarmExpansion", // changed in 2.0, 2.0.5, and 3.0
- "UpdateKeys": [ "Nexus:130" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~2.0.5": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Advize.FarmExpansion",
+ "FormerIDs": "3888bdfd-73f6-4776-8bb7-8ad45aea1915 | AdvizeFarmExpansionMod-2-0 | AdvizeFarmExpansionMod-2-0-5", // changed in 2.0, 2.0.5, and 3.0
+ "Default | UpdateKey": "Nexus:130",
+ "~2.0.5 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~2.0.5 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Farm Resource Generator
"ID": "FarmResourceGenerator.dll",
- "UpdateKeys": [ "Nexus:647" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.4": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:647",
+ "~1.0.4 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.4 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Fast Animations
"ID": "Pathoschild.FastAnimations",
- "UpdateKeys": [ "Nexus:1089" ]
+ "Default | UpdateKey": "Nexus:1089"
},
{
// Faster Paths
- "ID": "{ID:'821ce8f6-e629-41ad-9fde-03b54f68b0b6', Name:'Faster Paths'} | 615f85f8-5c89-44ee-aecc-c328f172e413 | Entoarox.FasterPaths" // changed in 1.2 and 1.3; disambiguate from Shop Expander
- // "UpdateKeys": [ "Chucklefish:3641" ] // Entoarox opted out of mod update checks
+ "ID": "Entoarox.FasterPaths",
+ "FormerIDs": "{ID:'821ce8f6-e629-41ad-9fde-03b54f68b0b6', Name:'Faster Paths'} | 615f85f8-5c89-44ee-aecc-c328f172e413" // changed in 1.2 and 1.3; disambiguate from Shop Expander
+ // "Default | UpdateKey": "Chucklefish:3641" // Entoarox opted out of mod update checks
},
{
// Faster Run
- "ID": "FasterRun.dll | KathrynHazuka.FasterRun", // changed in 1.1.1-pathoschild-update
- "UpdateKeys": [ "Nexus:733" ], // added in 1.1.1-pathoschild-update
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "KathrynHazuka.FasterRun",
+ "FormerIDs": "{EntryDLL: 'FasterRun.dll'}", // changed in 1.1.1-pathoschild-update
+ "Default | UpdateKey": "Nexus:733", // added in 1.1.1-pathoschild-update
+ "~1.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Fishing Adjust
"ID": "shuaiz.FishingAdjustMod",
- "UpdateKeys": [ "Nexus:1350" ]
+ "Default | UpdateKey": "Nexus:1350"
},
{
// Fishing Tuner Redux
"ID": "HammurabiFishingTunerRedux",
- "UpdateKeys": [ "Chucklefish:4578" ]
+ "Default | UpdateKey": "Chucklefish:4578"
},
{
// FlorenceMod
"ID": "FlorenceMod.dll",
- "UpdateKeys": [ "Nexus:591" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapLocalVersions": {
- "1.0.1": "1.1"
- }
+ "MapLocalVersions": { "1.0.1": "1.1" },
+ "Default | UpdateKey": "Nexus:591",
+ "~1.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Flower Color Picker
"ID": "spacechase0.FlowerColorPicker",
- "UpdateKeys": [ "Nexus:1229" ]
+ "Default | UpdateKey": "Nexus:1229"
},
{
// Forage at the Farm
"ID": "ForageAtTheFarm",
- "UpdateKeys": [ "Nexus:673" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.5.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:673",
+ "~1.5.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.5.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Furniture Anywhere
- "ID": "{ID:'EntoaroxFurnitureAnywhere', Name:'Furniture Anywhere'} | Entoarox.FurnitureAnywhere" // changed in 1.1; disambiguate from Extended Minecart
- // "UpdateKeys": [ "Chucklefish:4324" ] // Entoarox opted out of mod update checks
+ "ID": "Entoarox.FurnitureAnywhere",
+ "FormerIDs": "{ID:'EntoaroxFurnitureAnywhere', Name:'Furniture Anywhere'}" // changed in 1.1; disambiguate from Extended Minecart
+ // "Default | UpdateKey": "Chucklefish:4324" // Entoarox opted out of mod update checks
},
{
// Game Reminder
"ID": "mmanlapat.GameReminder",
- "UpdateKeys": [ "Nexus:1153" ]
+ "Default | UpdateKey": "Nexus:1153"
},
{
// Gate Opener
- "ID": "GateOpener.dll | mralbobo.GateOpener", // changed in 1.1
- "UpdateKeys": [ "GitHub:mralbobo/stardew-gate-opener" ],
- "Compatibility": {
- "~1.0.1": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "mralbobo.GateOpener",
+ "FormerIDs": "{EntryDLL: 'GateOpener.dll'}", // changed in 1.1
+ "Default | UpdateKey": "GitHub:mralbobo/stardew-gate-opener",
+ "~1.0.1 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// GenericShopExtender
"ID": "GenericShopExtender",
- "UpdateKeys": [ "Nexus:814" ], // added in 0.1.3
- "Compatibility": {
- "~0.1.2": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:814", // added in 0.1.3
+ "~0.1.2 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Geode Info Menu
"ID": "cat.geodeinfomenu",
- "UpdateKeys": [ "Nexus:1448" ]
+ "Default | UpdateKey": "Nexus:1448"
},
{
// Get Dressed
- "ID": "GetDressed.dll | Advize.GetDressed", // changed in 3.3
- "UpdateKeys": [ "Nexus:331" ],
- "Compatibility": {
- "~3.3": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Advize.GetDressed",
+ "FormerIDs": "{EntryDLL: 'GetDressed.dll'}", // changed in 3.3
+ "Default | UpdateKey": "Nexus:331",
+ "~3.3 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Giant Crop Ring
"ID": "cat.giantcropring",
- "UpdateKeys": [ "Nexus:1182" ]
+ "Default | UpdateKey": "Nexus:1182"
},
{
// Gift Taste Helper
- "ID": "8008db57-fa67-4730-978e-34b37ef191d6 | tstaples.GiftTasteHelper", // changed in 2.5
- "UpdateKeys": [ "Nexus:229" ],
- "Compatibility": {
- "~2.3.1": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "tstaples.GiftTasteHelper",
+ "FormerIDs": "8008db57-fa67-4730-978e-34b37ef191d6", // changed in 2.5
+ "Default | UpdateKey": "Nexus:229",
+ "~2.3.1 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Grandfather's Gift
"ID": "ShadowDragon.GrandfathersGift",
- "UpdateKeys": [ "Nexus:985" ]
+ "Default | UpdateKey": "Nexus:985"
},
{
// Happy Animals
"ID": "HappyAnimals",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "~1.0.3 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.3 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Happy Birthday (Omegasis)
- "ID": "{ID:'HappyBirthday', Author:'Alpha_Omegasis'} | Omegasis.HappyBirthday", // changed in 1.4; disambiguate from Oxyligen's fork
- "UpdateKeys": [ "Nexus:520" ], // added in 1.4.1
- "Compatibility": {
- "~1.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Omegasis.HappyBirthday",
+ "FormerIDs": "{ID:'HappyBirthday', Author:'Alpha_Omegasis'}", // changed in 1.4; disambiguate from Oxyligen's fork
+ "Default | UpdateKey": "Nexus:520", // added in 1.4.1
+ "~1.3 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Happy Birthday (Oxyligen fork)
"ID": "{ID:'HappyBirthday', Author:'Alpha_Omegasis/Oxyligen'}", // disambiguate from Oxyligen's fork
- "UpdateKeys": [ "Nexus:1064" ]
+ "Default | UpdateKey": "Nexus:1064"
},
{
// Harp of Yoba Redux
"ID": "Platonymous.HarpOfYobaRedux",
- "UpdateKeys": [ "Nexus:914" ] // added in 2.0.3
+ "Default | UpdateKey": "Nexus:914" // added in 2.0.3
},
{
// Harvest Moon Witch Princess
"ID": "Sasara.WitchPrincess",
- "UpdateKeys": [ "Nexus:1157" ]
+ "Default | UpdateKey": "Nexus:1157"
},
{
// Harvest With Scythe
"ID": "965169fd-e1ed-47d0-9f12-b104535fb4bc",
- "UpdateKeys": [ "Nexus:236" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.6": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:236",
+ "~1.0.6 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.6 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Horse Whistle (icepuente)
"ID": "icepuente.HorseWhistle",
- "UpdateKeys": [ "Nexus:1131" ]
+ "Default | UpdateKey": "Nexus:1131"
},
{
// Hunger (Yyeadude)
"ID": "HungerYyeadude",
- "UpdateKeys": [ "Nexus:613" ]
+ "Default | UpdateKey": "Nexus:613"
},
{
// Hunger for Food (Tigerle)
"ID": "HungerForFoodByTigerle",
- "UpdateKeys": [ "Nexus:810" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~0.1.2": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:810",
+ "~0.1.2 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~0.1.2 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Hunger Mod (skn)
"ID": "skn.HungerMod",
- "UpdateKeys": [ "Nexus:1127" ],
- "MapRemoteVersions": {
- "1.2.1": "1.0" // manifest not updated
- }
+ "MapRemoteVersions": { "1.2.1": "1.0" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:1127"
},
{
// Idle Pause
"ID": "Veleek.IdlePause",
- "UpdateKeys": [ "Nexus:1092" ],
- "MapRemoteVersions": {
- "1.2": "1.1" // manifest not updated
- }
+ "MapRemoteVersions": { "1.2": "1.1" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:1092"
},
{
// Improved Quality of Life
"ID": "Demiacle.ImprovedQualityOfLife",
- "UpdateKeys": [ "Nexus:1025" ],
- "Compatibility": {
- "~1.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:1025",
+ "~1.1 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Instant Geode
"ID": "InstantGeode",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.12": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "~1.12 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.12 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Instant Grow Trees
- "ID": "dc50c58b-c7d8-4e60-86cc-e27b5d95ee59 | community.InstantGrowTrees", // changed in 1.2
- "UpdateKeys": [ "Nexus:173" ]
+ "ID": "community.InstantGrowTrees",
+ "FormerIDs": "dc50c58b-c7d8-4e60-86cc-e27b5d95ee59", // changed in 1.2
+ "Default | UpdateKey": "Nexus:173"
},
{
// Interaction Helper
"ID": "HammurabiInteractionHelper",
- "UpdateKeys": [ "Chucklefish:4640" ], // added in 1.0.4-pathoschild-update
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Chucklefish:4640", // added in 1.0.4-pathoschild-update
+ "~1.0.3 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.3 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Item Auto Stacker
"ID": "cat.autostacker",
- "UpdateKeys": [ "Nexus:1184" ],
- "MapRemoteVersions": {
- "1.0.1": "1.0" // manifest not updated
- }
+ "MapRemoteVersions": { "1.0.1": "1.0" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:1184"
},
{
// Jiggly Junimo Bundles
- "ID": "JJB.dll | Greger.JigglyJunimoBundles", // changed in 1.1.2-pathoschild-update
- "UpdateKeys": [ "GitHub:gr3ger/Stardew_JJB" ], // added in 1.0.4-pathoschild-update
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
+ "ID": "Greger.JigglyJunimoBundles",
+ "FormerIDs": "{EntryDLL: 'JJB.dll'}", // changed in 1.1.2-pathoschild-update
+ "Default | UpdateKey": "GitHub:gr3ger/Stardew_JJB" // added in 1.0.4-pathoschild-update
},
{
// Junimo Farm
"ID": "Platonymous.JunimoFarm",
- "UpdateKeys": [ "Nexus:984" ], // added in 1.1.3
- "MapRemoteVersions": {
- "1.1.2": "1.1.1" // manifest not updated
- }
+ "MapRemoteVersions": { "1.1.2": "1.1.1" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:984" // added in 1.1.3
},
{
// Less Strict Over-Exertion (AntiExhaustion)
"ID": "BALANCEMOD_AntiExhaustion",
- "UpdateKeys": [ "Nexus:637" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapLocalVersions": {
- "0.0": "1.1"
- }
+ "MapLocalVersions": { "0.0": "1.1" },
+ "Default | UpdateKey": "Nexus:637",
+ "~1.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Level Extender
"ID": "Devin Lematty.Level Extender",
- "UpdateKeys": [ "Nexus:1471" ],
- "MapRemoteVersions": {
- "1.1": "1.0" // manifest not updated
- }
+ "MapRemoteVersions": { "1.1": "1.0" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:1471"
},
{
// Level Up Notifications
"ID": "Level Up Notifications",
- "UpdateKeys": [ "Nexus:855" ]
+ "Default | UpdateKey": "Nexus:855"
},
{
// Location and Music Logging
"ID": "Brandy Lover.LMlog",
- "UpdateKeys": [ "Nexus:1366" ]
+ "Default | UpdateKey": "Nexus:1366"
},
{
// Longevity
"ID": "RTGOAT.Longevity",
- "UpdateKeys": [ "Nexus:649" ]
+ "Default | UpdateKey": "Nexus:649"
},
{
// Lookup Anything
- "ID": "LookupAnything | Pathoschild.LookupAnything", // changed in 1.10.1
- "UpdateKeys": [ "Nexus:541" ],
- "Compatibility": {
- "~1.10.1": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Pathoschild.LookupAnything",
+ "FormerIDs": "LookupAnything", // changed in 1.10.1
+ "Default | UpdateKey": "Nexus:541",
+ "~1.10.1 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Love Bubbles
"ID": "LoveBubbles",
- "UpdateKeys": [ "Nexus:1318" ]
+ "Default | UpdateKey": "Nexus:1318"
},
{
// Loved Labels
"ID": "LovedLabels.dll",
- "UpdateKeys": [ "Nexus:279" ],
- "Compatibility": {
- "~2.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:279",
+ "~2.0 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Luck Skill
- "ID": "LuckSkill | spacechase0.LuckSkill", // changed in 0.1.4
- "UpdateKeys": [ "Nexus:521" ],
- "Compatibility": {
- "~0.1.4": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "spacechase0.LuckSkill",
+ "FormerIDs": "LuckSkill", // changed in 0.1.4
+ "Default | UpdateKey": "Nexus:521",
+ "~0.1.4 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Mail Framework
"ID": "DIGUS.MailFrameworkMod",
- "UpdateKeys": [ "Nexus:1536" ]
+ "Default | UpdateKey": "Nexus:1536"
},
{
// MailOrderPigs
- "ID": "MailOrderPigs.dll | jwdred.MailOrderPigs", // changed in 1.0.2
- "UpdateKeys": [ "Nexus:632" ],
- "Compatibility": {
- "~1.0.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "jwdred.MailOrderPigs",
+ "FormerIDs": "{EntryDLL: 'MailOrderPigs.dll'}", // changed in 1.0.2
+ "Default | UpdateKey": "Nexus:632",
+ "~1.0.1 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Makeshift Multiplayer
- "ID": "StardewValleyMP | spacechase0.StardewValleyMP", // changed in 0.3
- "UpdateKeys": [ "Nexus:501" ],
- "Compatibility": {
- "~0.3.6": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "spacechase0.StardewValleyMP",
+ "FormerIDs": "StardewValleyMP", // changed in 0.3
+ "Default | UpdateKey": "Nexus:501",
+ "~0.3.6 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Map Image Exporter
- "ID": "MapImageExporter | spacechase0.MapImageExporter", // changed in 1.0.2
- "UpdateKeys": [ "Nexus:1073" ]
+ "ID": "spacechase0.MapImageExporter",
+ "FormerIDs": "MapImageExporter", // changed in 1.0.2
+ "Default | UpdateKey": "Nexus:1073"
},
{
// Message Box [API]? (ChatMod)
"ID": "Kithio:ChatMod",
- "UpdateKeys": [ "Chucklefish:4296" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Chucklefish:4296",
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Mining at the Farm
"ID": "MiningAtTheFarm",
- "UpdateKeys": [ "Nexus:674" ]
+ "Default | UpdateKey": "Nexus:674"
},
{
// Mining With Explosives
"ID": "MiningWithExplosives",
- "UpdateKeys": [ "Nexus:770" ]
+ "Default | UpdateKey": "Nexus:770"
},
{
// Modder Serialization Utility
"ID": "SerializerUtils-0-1",
- "Compatibility": {
- "~": {
- "Status": "Obsolete",
- "ReasonPhrase": "it's no longer maintained or used."
- }
- }
+ "~ | Status": "Obsolete",
+ "~ | StatusReasonPhrase": "it's no longer maintained or used."
},
{
// More Artifact Spots
"ID": "451",
- "UpdateKeys": [ "Nexus:451" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:451",
+ "~1.0.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// More Map Layers
"ID": "Platonymous.MoreMapLayers",
- "UpdateKeys": [ "Nexus:1134" ] // added in 1.1.1
+ "Default | UpdateKey": "Nexus:1134" // added in 1.1.1
},
{
// More Pets
- "ID": "821ce8f6-e629-41ad-9fde-03b54f68b0b6MOREPETS | Entoarox.MorePets", // changed in 1.3
- // "UpdateKeys": [ "Chucklefish:4288" ], // Entoarox opted out of mod update checks
- "Compatibility": {
- "~1.3.2": { "Status": "AssumeBroken" } // overhauled for SMAPI 1.11+ compatibility
- }
+ "ID": "Entoarox.MorePets",
+ "FormerIDs": "821ce8f6-e629-41ad-9fde-03b54f68b0b6MOREPETS", // changed in 1.3
+ // "Default | UpdateKey": "Chucklefish:4288", // Entoarox opted out of mod update checks
+ "~1.3.2 | Status": "AssumeBroken" // overhauled for SMAPI 1.11+ compatibility
},
{
// More Rain
- "ID": "{ID:'4108e859-333c-4fec-a1a7-d2e18c1019fe', Name:'More_Rain'} | Omegasis.MoreRain", // changed in 1.5; disambiguate from other mods by Alpha_Omegasis
- "UpdateKeys": [ "Nexus:441" ], // added in 1.5.1
- "Compatibility": {
- "~1.4": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Omegasis.MoreRain",
+ "FormerIDs": "{ID:'4108e859-333c-4fec-a1a7-d2e18c1019fe', Name:'More_Rain'}", // changed in 1.5; disambiguate from other mods by Alpha_Omegasis
+ "Default | UpdateKey": "Nexus:441", // added in 1.5.1
+ "~1.4 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// More Weapons
"ID": "Joco80.MoreWeapons",
- "UpdateKeys": [ "Nexus:1168" ]
+ "Default | UpdateKey": "Nexus:1168"
},
{
// Move Faster
"ID": "shuaiz.MoveFasterMod",
- "UpdateKeys": [ "Nexus:1351" ]
+ "Default | UpdateKey": "Nexus:1351"
},
{
// Multiple Sprites and Portraits On Rotation (File Loading)
"ID": "FileLoading",
- "UpdateKeys": [ "Nexus:1094" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.12": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapLocalVersions": {
- "1.1": "1.12"
- }
+ "MapLocalVersions": { "1.1": "1.12" },
+ "Default | UpdateKey": "Nexus:1094",
+ "~1.12 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.12 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Museum Rearranger
- "ID": "{ID:'7ad4f6f7-c3de-4729-a40f-7a11d2b2a358', Name:'Museum Rearranger'} | Omegasis.MuseumRearranger", // changed in 1.4; disambiguate from other mods by Alpha_Omegasis
- "UpdateKeys": [ "Nexus:428" ], // added in 1.4.1
- "Compatibility": {
- "~1.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Omegasis.MuseumRearranger",
+ "FormerIDs": "{ID:'7ad4f6f7-c3de-4729-a40f-7a11d2b2a358', Name:'Museum Rearranger'}", // changed in 1.4; disambiguate from other mods by Alpha_Omegasis
+ "Default | UpdateKey": "Nexus:428", // added in 1.4.1
+ "~1.3 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// New Machines
"ID": "F70D4FAB-0AB2-4B78-9F1B-AF2CA2236A59",
- "UpdateKeys": [ "Chucklefish:3683" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~4.2.1343": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Chucklefish:3683",
+ "~4.2.1343 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~4.2.1343 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Night Owl
- "ID": "{ID:'SaveAnywhere', Name:'Stardew_NightOwl'} | Omegasis.NightOwl", // changed in 1.4; disambiguate from Save Anywhere
- "UpdateKeys": [ "Nexus:433" ], // added in 1.4.1
- "Compatibility": {
- "~1.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapLocalVersions": {
- "2.1": "1.3" // 1.3 had wrong version in manifest
- }
+ "ID": "Omegasis.NightOwl",
+ "FormerIDs": "{ID:'SaveAnywhere', Name:'Stardew_NightOwl'}", // changed in 1.4; disambiguate from Save Anywhere
+ "MapLocalVersions": { "2.1": "1.3" }, // 1.3 had wrong version in manifest
+ "Default | UpdateKey": "Nexus:433", // added in 1.4.1
+ "~1.3 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// No Kids Ever
"ID": "Hangy.NoKidsEver",
- "UpdateKeys": [ "Nexus:1464" ]
+ "Default | UpdateKey": "Nexus:1464"
},
{
// No Debug Mode
"ID": "NoDebugMode",
- "Compatibility": {
- "~": {
- "Status": "Obsolete",
- "ReasonPhrase": "debug mode was removed in SMAPI 1.0."
- }
- }
+ "~ | Status": "Obsolete",
+ "~ | StatusReasonPhrase": "debug mode was removed in SMAPI 1.0."
},
{
// No Fence Decay
"ID": "cat.nofencedecay",
- "UpdateKeys": [ "Nexus:1180" ]
+ "Default | UpdateKey": "Nexus:1180"
},
{
// No More Pets
- "ID": "NoMorePets | Omegasis.NoMorePets", // changed in 1.4
- "UpdateKeys": [ "Nexus:506" ] // added in 1.4.1
+ "ID": "Omegasis.NoMorePets",
+ "FormerIDs": "NoMorePets", // changed in 1.4
+ "Default | UpdateKey": "Nexus:506" // added in 1.4.1
},
{
// NoSoilDecay
"ID": "289dee03-5f38-4d8e-8ffc-e440198e8610",
- "UpdateKeys": [ "Nexus:237" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~0.5": { "Status": "AssumeBroken" } // broke in SDV 1.2, and uses Assembly.GetExecutingAssembly().Location
- }
+ "Default | UpdateKey": "Nexus:237",
+ "~0.5 | Status": "AssumeBroken", // broke in SDV 1.2 and uses Assembly.GetExecutingAssembly().Location
+ "~0.5 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// No Soil Decay Redux
"ID": "Platonymous.NoSoilDecayRedux",
- "UpdateKeys": [ "Nexus:1084" ] // added in 1.1.9
+ "Default | UpdateKey": "Nexus:1084" // added in 1.1.9
},
{
// NPC Map Locations
"ID": "NPCMapLocationsMod",
- "UpdateKeys": [ "Nexus:239" ],
- "Compatibility": {
- "1.42~1.43": {
- "Status": "AssumeBroken",
- "ReasonPhrase": "this version has an update check error which crashes the game."
- }
- }
+ "Default | UpdateKey": "Nexus:239",
+ "1.42~1.43 | Status": "AssumeBroken",
+ "1.42~1.43 | StatusReasonPhrase": "this version has an update check error which crashes the game."
},
{
// NPC Speak
"ID": "NpcEcho.dll",
- "UpdateKeys": [ "Nexus:694" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:694",
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Object Time Left
"ID": "spacechase0.ObjectTimeLeft",
- "UpdateKeys": [ "Nexus:1315" ]
+ "Default | UpdateKey": "Nexus:1315"
},
{
// OmniFarm
- "ID": "BlueMod_OmniFarm | PhthaloBlue.OmniFarm", // changed in 2.0.2-pathoschild-update
- "UpdateKeys": [ "GitHub:lambui/StardewValleyMod_OmniFarm" ],
- "Compatibility": {
- "~2.0.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "PhthaloBlue.OmniFarm",
+ "FormerIDs": "BlueMod_OmniFarm", // changed in 2.0.2-pathoschild-update
+ "Default | UpdateKey": "GitHub:lambui/StardewValleyMod_OmniFarm",
+ "~2.0.1 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Out of Season Bonuses / Seasonal Items
"ID": "midoriarmstrong.seasonalitems",
- "UpdateKeys": [ "Nexus:1452" ]
+ "Default | UpdateKey": "Nexus:1452"
},
{
// Part of the Community
"ID": "SB_PotC",
- "UpdateKeys": [ "Nexus:923" ],
- "Compatibility": {
- "~1.0.8": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "Default | UpdateKey": "Nexus:923",
+ "~1.0.8 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// PelicanFiber
- "ID": "PelicanFiber.dll | jwdred.PelicanFiber", // changed in 3.0.1
- "UpdateKeys": [ "Nexus:631" ],
- "Compatibility": {
- "~3.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapRemoteVersions": {
- "3.0.2": "3.0.1" // didn't change manifest version
- }
+ "ID": "jwdred.PelicanFiber",
+ "FormerIDs": "{EntryDLL: 'PelicanFiber.dll'}", // changed in 3.0.1
+ "MapRemoteVersions": { "3.0.2": "3.0.1" }, // didn't change manifest version
+ "Default | UpdateKey": "Nexus:631",
+ "~3.0 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// PelicanTTS
"ID": "Platonymous.PelicanTTS",
- "UpdateKeys": [ "Nexus:1079" ], // added in 1.6.1
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.6": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:1079", // added in 1.6.1
+ "~1.6 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.6 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Persia the Mermaid - Standalone Custom NPC
"ID": "63b9f419-7449-42db-ab2e-440b4d05c073",
- "UpdateKeys": [ "Nexus:1419" ]
+ "Default | UpdateKey": "Nexus:1419"
},
{
// Persival's BundleMod
"ID": "BundleMod.dll",
- "UpdateKeys": [ "Nexus:438" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SDV 1.1
- }
+ "Default | UpdateKey": "Nexus:438",
+ "~1.0 | Status": "AssumeBroken", // broke in SDV 1.1
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Plant on Grass
"ID": "Demiacle.PlantOnGrass",
- "UpdateKeys": [ "Nexus:1026" ]
+ "Default | UpdateKey": "Nexus:1026"
},
{
// Point-and-Plant
- "ID": "PointAndPlant.dll | jwdred.PointAndPlant", // changed in 1.0.3
- "UpdateKeys": [ "Nexus:572" ],
- "Compatibility": {
- "~1.0.2": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "jwdred.PointAndPlant",
+ "FormerIDs": "{EntryDLL: 'PointAndPlant.dll'}", // changed in 1.0.3
+ "Default | UpdateKey": "Nexus:572",
+ "~1.0.2 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Pony Weight Loss Program
"ID": "BadNetCode.PonyWeightLossProgram",
- "UpdateKeys": [ "Nexus:1232" ]
+ "Default | UpdateKey": "Nexus:1232"
},
{
// Portraiture
"ID": "Platonymous.Portraiture",
- "UpdateKeys": [ "Nexus:999" ] // added in 1.3.1
+ "Default | UpdateKey": "Nexus:999" // added in 1.3.1
},
{
// Prairie King Made Easy
- "ID": "PrairieKingMadeEasy.dll | Mucchan.PrairieKingMadeEasy", // changed in 1.0.1
- "UpdateKeys": [ "Chucklefish:3594" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Mucchan.PrairieKingMadeEasy",
+ "FormerIDs": "{EntryDLL: 'PrairieKingMadeEasy.dll'}", // changed in 1.0.1
+ "Default | UpdateKey": "Chucklefish:3594",
+ "~1.0 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Quest Delay
"ID": "BadNetCode.QuestDelay",
- "UpdateKeys": [ "Nexus:1239" ]
+ "Default | UpdateKey": "Nexus:1239"
},
{
// Rain Randomizer
"ID": "RainRandomizer.dll",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "~1.0.3 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.3 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Recatch Legendary Fish
- "ID": "b3af8c31-48f0-43cf-8343-3eb08bcfa1f9 | community.RecatchLegendaryFish", // changed in 1.3
- "UpdateKeys": [ "Nexus:172" ]
+ "ID": "community.RecatchLegendaryFish",
+ "FormerIDs": "b3af8c31-48f0-43cf-8343-3eb08bcfa1f9", // changed in 1.3
+ "Default | UpdateKey": "Nexus:172"
},
{
// Regeneration
"ID": "HammurabiRegeneration",
- "UpdateKeys": [ "Chucklefish:4584" ]
+ "Default | UpdateKey": "Chucklefish:4584"
},
{
// Relationship Bar UI
"ID": "RelationshipBar",
- "UpdateKeys": [ "Nexus:1009" ]
+ "Default | UpdateKey": "Nexus:1009"
},
{
// RelationshipsEnhanced
"ID": "relationshipsenhanced",
- "UpdateKeys": [ "Chucklefish:4435" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Chucklefish:4435",
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Relationship Status
"ID": "relationshipstatus",
- "UpdateKeys": [ "Nexus:751" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.5": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapRemoteVersions": {
- "1.0.5": "1.0.4" // not updated in manifest
- }
+ "MapRemoteVersions": { "1.0.5": "1.0.4" }, // not updated in manifest
+ "Default | UpdateKey": "Nexus:751",
+ "~1.0.5 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.5 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Rented Tools
"ID": "JarvieK.RentedTools",
- "UpdateKeys": [ "Nexus:1307" ]
+ "Default | UpdateKey": "Nexus:1307"
},
{
// Replanter
- "ID": "Replanter.dll | jwdred.Replanter", // changed in 1.0.5
- "UpdateKeys": [ "Nexus:589" ],
- "Compatibility": {
- "~1.0.4": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "jwdred.Replanter",
+ "FormerIDs": "{EntryDLL: 'Replanter.dll'}", // changed in 1.0.5
+ "Default | UpdateKey": "Nexus:589",
+ "~1.0.4 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// ReRegeneration
"ID": "lrsk_sdvm_rerg.0925160827",
- "UpdateKeys": [ "Chucklefish:4465" ],
- "MapLocalVersions": {
- "1.1.2-release": "1.1.2"
- }
+ "MapLocalVersions": { "1.1.2-release": "1.1.2" },
+ "Default | UpdateKey": "Chucklefish:4465"
},
{
// Reseed
"ID": "Roc.Reseed",
- "UpdateKeys": [ "Nexus:887" ]
+ "Default | UpdateKey": "Nexus:887"
},
{
// Reusable Wallpapers and Floors (Wallpaper Retain)
"ID": "dae1b553-2e39-43e7-8400-c7c5c836134b",
- "UpdateKeys": [ "Nexus:356" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.5": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:356",
+ "~1.5 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.5 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Ring of Fire
"ID": "Platonymous.RingOfFire",
- "UpdateKeys": [ "Nexus:1166" ] // added in 1.0.1
+ "Default | UpdateKey": "Nexus:1166" // added in 1.0.1
},
{
// Rope Bridge
"ID": "RopeBridge",
- "UpdateKeys": [ "Nexus:824" ]
+ "Default | UpdateKey": "Nexus:824"
},
{
// Rotate Toolbar
"ID": "Pathoschild.RotateToolbar",
- "UpdateKeys": [ "Nexus:1100" ]
+ "Default | UpdateKey": "Nexus:1100"
},
{
// Rush Orders
- "ID": "RushOrders | spacechase0.RushOrders", // changed in 1.1
- "UpdateKeys": [ "Nexus:605" ],
- "Compatibility": {
- "~1.1": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "spacechase0.RushOrders",
+ "FormerIDs": "RushOrders", // changed in 1.1
+ "Default | UpdateKey": "Nexus:605",
+ "~1.1 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Save Anywhere
- "ID": "{ID:'SaveAnywhere', Name:'Save Anywhere'} | Omegasis.SaveAnywhere", // changed in 2.5; disambiguate from Night Owl
- "UpdateKeys": [ "Nexus:444" ], // added in 2.6.1
- "Compatibility": {
- "~2.4": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Omegasis.SaveAnywhere",
+ "FormerIDs": "{ID:'SaveAnywhere', Name:'Save Anywhere'}", // changed in 2.5; disambiguate from Night Owl
+ "Default | UpdateKey": "Nexus:444", // added in 2.6.1
+ "~2.4 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Save Backup
- "ID": "{ID:'4be88c18-b6f3-49b0-ba96-f94b1a5be890', Name:'Stardew_Save_Backup'} | Omegasis.SaveBackup", // changed in 1.3; disambiguate from other Alpha_Omegasis mods
- "UpdateKeys": [ "Nexus:435" ], // added in 1.3.1
- "Compatibility": {
- "~1.2": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Omegasis.SaveBackup",
+ "FormerIDs": "{ID:'4be88c18-b6f3-49b0-ba96-f94b1a5be890', Name:'Stardew_Save_Backup'}", // changed in 1.3; disambiguate from other Alpha_Omegasis mods
+ "Default | UpdateKey": "Nexus:435", // added in 1.3.1
+ "~1.2 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Scroll to Blank
"ID": "caraxian.scroll.to.blank",
- "UpdateKeys": [ "Chucklefish:4405" ]
+ "Default | UpdateKey": "Chucklefish:4405"
},
{
// Scythe Harvesting
- "ID": "ScytheHarvesting | mmanlapat.ScytheHarvesting", // changed in 1.6
- "UpdateKeys": [ "Nexus:1106" ]
+ "ID": "mmanlapat.ScytheHarvesting",
+ "FormerIDs": "ScytheHarvesting", // changed in 1.6
+ "Default | UpdateKey": "Nexus:1106"
},
{
// Seasonal Immersion
- "ID": "EntoaroxSeasonalHouse | EntoaroxSeasonalBuildings | EntoaroxSeasonalImmersion | Entoarox.SeasonalImmersion", // changed in 1.1, 1.6 or earlier, and 1.7
- // "UpdateKeys": [ "Chucklefish:4262" ], // Entoarox opted out of mod update checks
- "Compatibility": {
- "~1.8.2": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Entoarox.SeasonalImmersion",
+ "FormerIDs": "EntoaroxSeasonalHouse | EntoaroxSeasonalBuildings | EntoaroxSeasonalImmersion", // changed in 1.1, 1.6 or earlier, and 1.7
+ // "Default | UpdateKey": "Chucklefish:4262", // Entoarox opted out of mod update checks
+ "~1.8.2 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Seed Bag
"ID": "Platonymous.SeedBag",
- "UpdateKeys": [ "Nexus:1133" ] // added in 1.1.2
+ "Default | UpdateKey": "Nexus:1133" // added in 1.1.2
},
{
// Self Service
"ID": "JarvieK.SelfService",
- "UpdateKeys": [ "Nexus:1304" ],
- "MapRemoteVersions": {
- "0.2.1": "0.2" // manifest not updated
- }
+ "MapRemoteVersions": { "0.2.1": "0.2" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:1304"
},
{
// Send Items
"ID": "Denifia.SendItems",
- "UpdateKeys": [ "Nexus:1087" ], // added in 1.0.3 (2017-10-04)
- "Compatibility": {
- "~1.0.2": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:1087", // added in 1.0.3 (2017-10-04)
+ "~1.0.2 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Shed Notifications (BuildingsNotifications)
"ID": "TheCroak.BuildingsNotifications",
- "UpdateKeys": [ "Nexus:620" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~0.4.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:620",
+ "~0.4.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~0.4.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Shenandoah Project
"ID": "Shenandoah Project",
- "UpdateKeys": [ "Nexus:756" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.1.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapRemoteVersions": {
- "1.1.1": "1.1" // not updated in manifest
- }
+ "MapRemoteVersions": { "1.1.1": "1.1" }, // not updated in manifest
+ "Default | UpdateKey": "Nexus:756",
+ "~1.1.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.1.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Ship Anywhere
"ID": "spacechase0.ShipAnywhere",
- "UpdateKeys": [ "Nexus:1379" ]
+ "Default | UpdateKey": "Nexus:1379"
},
{
// Shipment Tracker
"ID": "7e474181-e1a0-40f9-9c11-d08a3dcefaf3",
- "UpdateKeys": [ "Nexus:321" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:321",
+ "~1.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Shop Expander
- "ID": "{ID:'821ce8f6-e629-41ad-9fde-03b54f68b0b6', Name:'Shop Expander'} | EntoaroxShopExpander | Entoarox.ShopExpander", // changed in 1.5 and 1.5.2; disambiguate from Faster Paths
- // "UpdateKeys": [ "Chucklefish:4381" ], // Entoarox opted out of mod update checks
- "Compatibility": {
- "~1.5.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Entoarox.ShopExpander",
+ "FormerIDs": "{ID:'821ce8f6-e629-41ad-9fde-03b54f68b0b6', Name:'Shop Expander'} | EntoaroxShopExpander", // changed in 1.5 and 1.5.2; disambiguate from Faster Paths
+ // "Default | UpdateKey": "Chucklefish:4381", // Entoarox opted out of mod update checks
+ "~1.5.3 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Showcase Mod
"ID": "Igorious.Showcase",
- "UpdateKeys": [ "Chucklefish:4487" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~0.9": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapLocalVersions": {
- "0.9-500": "0.9"
- }
+ "MapLocalVersions": { "0.9-500": "0.9" },
+ "Default | UpdateKey": "Chucklefish:4487",
+ "~0.9 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~0.9 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Shroom Spotter
"ID": "TehPers.ShroomSpotter",
- "UpdateKeys": [ "Nexus:908" ]
+ "Default | UpdateKey": "Nexus:908"
},
{
// Simple Crop Label
"ID": "SimpleCropLabel",
- "UpdateKeys": [ "Nexus:314" ]
+ "Default | UpdateKey": "Nexus:314"
},
{
// Simple Sound Manager
"ID": "Omegasis.SimpleSoundManager",
- "UpdateKeys": [ "Nexus:1410" ], // added in 1.0.1
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0", // can remove once 1.0.1 is published
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Nexus:1410", // added in 1.0.1
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0" // can remove once 1.0.1 is published
},
{
// Simple Sprinklers
- "ID": "SimpleSprinkler.dll | tZed.SimpleSprinkler", // changed in 1.5
- "UpdateKeys": [ "Nexus:76" ],
- "Compatibility": {
- "~1.4": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "tZed.SimpleSprinkler",
+ "FormerIDs": "{EntryDLL: 'SimpleSprinkler.dll'}", // changed in 1.5
+ "Default | UpdateKey": "Nexus:76",
+ "~1.4 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Siv's Marriage Mod
"ID": "6266959802",
- "UpdateKeys": [ "Nexus:366" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.2.2": { "Status": "AssumeBroken" } // broke in SMAPI 1.9 (has multiple Mod instances)
- },
- "MapLocalVersions": {
- "0.0": "1.4"
- }
+ "MapLocalVersions": { "0.0": "1.4" },
+ "Default | UpdateKey": "Nexus:366",
+ "~1.2.2 | Status": "AssumeBroken", // broke in SMAPI 1.9 (has multiple Mod instances)
+ "~1.2.2 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Skill Prestige
- "ID": "6b843e60-c8fc-4a25-a67b-4a38ac8dcf9b | alphablackwolf.skillPrestige", // changed circa 1.2.3
- "UpdateKeys": [ "Nexus:569" ],
- "Compatibility": {
- "~1.0.9": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "alphablackwolf.skillPrestige",
+ "FormerIDs": "6b843e60-c8fc-4a25-a67b-4a38ac8dcf9b", // changed circa 1.2.3
+ "Default | UpdateKey": "Nexus:569",
+ "~1.0.9 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Skill Prestige: Cooking Adapter
- "ID": "20d6b8a3-b6e7-460b-a6e4-07c2b0cb6c63 | Alphablackwolf.CookingSkillPrestigeAdapter", // changed circa 1.1
- "UpdateKeys": [ "Nexus:569" ],
- "Compatibility": {
- "~1.0.9": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapRemoteVersions": {
- "1.2.3": "1.1" // manifest not updated
- }
+ "ID": "Alphablackwolf.CookingSkillPrestigeAdapter",
+ "FormerIDs": "20d6b8a3-b6e7-460b-a6e4-07c2b0cb6c63", // changed circa 1.1
+ "MapRemoteVersions": { "1.2.3": "1.1" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:569",
+ "~1.0.9 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Skip Intro
- "ID": "SkipIntro | Pathoschild.SkipIntro", // changed in 1.4
- "UpdateKeys": [ "Nexus:533" ]
+ "ID": "Pathoschild.SkipIntro",
+ "FormerIDs": "SkipIntro", // changed in 1.4
+ "Default | UpdateKey": "Nexus:533"
},
{
// Skull Cavern Elevator
"ID": "SkullCavernElevator",
- "UpdateKeys": [ "Nexus:963" ]
+ "Default | UpdateKey": "Nexus:963"
},
{
// Skull Cave Saver
- "ID": "8ac06349-26f7-4394-806c-95d48fd35774 | community.SkullCaveSaver", // changed in 1.1
- "UpdateKeys": [ "Nexus:175" ]
+ "ID": "community.SkullCaveSaver",
+ "FormerIDs": "8ac06349-26f7-4394-806c-95d48fd35774", // changed in 1.1
+ "Default | UpdateKey": "Nexus:175"
},
{
// Sleepy Eye
"ID": "spacechase0.SleepyEye",
- "UpdateKeys": [ "Nexus:1152" ]
+ "Default | UpdateKey": "Nexus:1152"
},
{
// Slower Fence Decay
- "ID": "SPDSlowFenceDecay | Speeder.SlowerFenceDecay", // changed in 0.5.2-pathoschild-update
- "UpdateKeys": [ "Nexus:252" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~0.5.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Speeder.SlowerFenceDecay",
+ "FormerIDs": "SPDSlowFenceDecay", // changed in 0.5.2-pathoschild-update
+ "Default | UpdateKey": "Nexus:252",
+ "~0.5.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~0.5.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Smart Mod
"ID": "KuroBear.SmartMod",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~2.2": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "~2.2 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~2.2 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Solar Eclipse Event
"ID": "KoihimeNakamura.SolarEclipseEvent",
- "UpdateKeys": [ "Nexus:897" ],
- "Compatibility": {
- "~1.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapLocalVersions": {
- "1.3-20170917": "1.3"
- }
+ "Default | UpdateKey": "Nexus:897",
+ "MapLocalVersions": { "1.3-20170917": "1.3" },
+ "~1.1 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// SpaceCore
"ID": "spacechase0.SpaceCore",
- "UpdateKeys": [ "Nexus:1348" ]
+ "Default | UpdateKey": "Nexus:1348"
},
{
// Speedster
"ID": "Platonymous.Speedster",
- "UpdateKeys": [ "Nexus:1102" ] // added in 1.3.1
+ "Default | UpdateKey": "Nexus:1102" // added in 1.3.1
},
{
// Sprinkler Range
"ID": "cat.sprinklerrange",
- "UpdateKeys": [ "Nexus:1179" ],
- "MapRemoteVersions": {
- "1.0.1": "1.0" // manifest not updated
- }
+ "MapRemoteVersions": { "1.0.1": "1.0" }, // manifest not updated
+ "Default | UpdateKey": "Nexus:1179"
},
{
// Sprinkles
"ID": "Platonymous.Sprinkles",
- "UpdateKeys": [ "Chucklefish:4592" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.1.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Chucklefish:4592",
+ "~1.1.3 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.1.3 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Sprint and Dash
"ID": "SPDSprintAndDash",
- "UpdateKeys": [ "Chucklefish:3531" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "Default | UpdateKey": "Chucklefish:3531",
+ "~1.0 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Sprint and Dash Redux
- "ID": "lrsk_sdvm_sndr.0921161059 | littleraskol.SprintAndDashRedux", // changed in 1.3
- "UpdateKeys": [ "Chucklefish:4201" ]
+ "ID": "littleraskol.SprintAndDashRedux",
+ "FormerIDs": "lrsk_sdvm_sndr.0921161059", // changed in 1.3
+ "Default | UpdateKey": "Chucklefish:4201"
},
{
// Sprinting Mod
"ID": "a10d3097-b073-4185-98ba-76b586cba00c",
- "UpdateKeys": [ "GitHub:oliverpl/SprintingMod" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~2.1": { "Status": "AssumeBroken" } // broke in SDV 1.2
- },
- "MapLocalVersions": {
- "1.0": "2.1" // not updated in manifest
- }
+ "MapLocalVersions": { "1.0": "2.1" }, // not updated in manifest
+ "Default | UpdateKey": "GitHub:oliverpl/SprintingMod",
+ "~2.1 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~2.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// StackSplitX
- "ID": "StackSplitX.dll | tstaples.StackSplitX", // changed circa 1.3.1
- "UpdateKeys": [ "Nexus:798" ],
- "Compatibility": {
- "~1.2": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "tstaples.StackSplitX",
+ "FormerIDs": "{EntryDLL: 'StackSplitX.dll'}", // changed circa 1.3.1
+ "Default | UpdateKey": "Nexus:798",
+ "~1.2 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// StaminaRegen
"ID": "StaminaRegen.dll",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "~1.0.3 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.3 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Stardew Config Menu
"ID": "Juice805.StardewConfigMenu",
- "UpdateKeys": [ "Nexus:1312" ]
+ "Default | UpdateKey": "Nexus:1312"
},
{
// Stardew Content Compatibility Layer (SCCL)
"ID": "SCCL",
- "UpdateKeys": [ "Nexus:889" ],
- "Compatibility": {
- "~0.1": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "Default | UpdateKey": "Nexus:889",
+ "~0.1 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Stardew Editor Game Integration
"ID": "spacechase0.StardewEditor.GameIntegration",
- "UpdateKeys": [ "Nexus:1298" ]
+ "Default | UpdateKey": "Nexus:1298"
},
{
// Stardew Notification
"ID": "stardewnotification",
- "UpdateKeys": [ "GitHub:monopandora/StardewNotification" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.7": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "GitHub:monopandora/StardewNotification",
+ "~1.7 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.7 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Stardew Symphony
- "ID": "{ID:'4108e859-333c-4fec-a1a7-d2e18c1019fe', Name:'Stardew_Symphony'} | Omegasis.StardewSymphony", // changed in 1.4; disambiguate other mods by Alpha_Omegasis
- "UpdateKeys": [ "Nexus:425" ], // added in 1.4.1
- "Compatibility": {
- "~1.3": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "ID": "Omegasis.StardewSymphony",
+ "FormerIDs": "{ID:'4108e859-333c-4fec-a1a7-d2e18c1019fe', Name:'Stardew_Symphony'}", // changed in 1.4; disambiguate other mods by Alpha_Omegasis
+ "Default | UpdateKey": "Nexus:425", // added in 1.4.1
+ "~1.3 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// StarDustCore
"ID": "StarDustCore",
- "Compatibility": {
- "~": {
- "Status": "Obsolete",
- "ReasonPhrase": "it was only used by earlier versions of Save Anywhere, and is no longer used or maintained."
- }
- }
+ "~ | Status": "Obsolete",
+ "~ | StatusReasonPhrase": "it was only used by earlier versions of Save Anywhere, and is no longer used or maintained."
},
{
// Starting Money
- "ID": "StartingMoney | mmanlapat.StartingMoney", // changed in 1.1
- "UpdateKeys": [ "Nexus:1138" ]
+ "ID": "mmanlapat.StartingMoney",
+ "FormerIDs": "StartingMoney", // changed in 1.1
+ "Default | UpdateKey": "Nexus:1138"
},
{
// StashItemsToChest
"ID": "BlueMod_StashItemsToChest",
- "UpdateKeys": [ "GitHub:lambui/StardewValleyMod_StashItemsToChest" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "GitHub:lambui/StardewValleyMod_StashItemsToChest",
+ "~1.0.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Stephan's Lots of Crops
"ID": "stephansstardewcrops",
- "UpdateKeys": [ "Chucklefish:4314" ],
- "MapRemoteVersions": {
- "1.41": "1.1" // manifest not updated
- }
+ "MapRemoteVersions": { "1.41": "1.1" }, // manifest not updated
+ "Default | UpdateKey": "Chucklefish:4314"
},
{
// Stone Bridge Over Pond (PondWithBridge)
"ID": "PondWithBridge.dll",
- "UpdateKeys": [ "Nexus:316" ],
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- },
- "MapLocalVersions": {
- "0.0": "1.0"
- }
+ "MapLocalVersions": { "0.0": "1.0" },
+ "Default | UpdateKey": "Nexus:316",
+ "~1.0 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// Stumps to Hardwood Stumps
"ID": "StumpsToHardwoodStumps",
- "UpdateKeys": [ "Nexus:691" ]
+ "Default | UpdateKey": "Nexus:691"
},
{
// Super Greenhouse Warp Modifier
"ID": "SuperGreenhouse",
- "UpdateKeys": [ "Chucklefish:4334" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Chucklefish:4334",
+ "~1.0 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Swim Almost Anywhere / Swim Suit
"ID": "Platonymous.SwimSuit",
- "UpdateKeys": [ "Nexus:1215" ] // added in 0.5.1
+ "Default | UpdateKey": "Nexus:1215" // added in 0.5.1
},
{
// Tainted Cellar
"ID": "TaintedCellar.dll",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SDV 1.1 or 1.11
- }
+ "~1.0 | Status": "AssumeBroken", // broke in SDV 1.1 or 1.11
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Tapper Ready
"ID": "skunkkk.TapperReady",
- "UpdateKeys": [ "Nexus:1219" ]
+ "Default | UpdateKey": "Nexus:1219"
},
{
// Teh's Fishing Overhaul
"ID": "TehPers.FishingOverhaul",
- "UpdateKeys": [ "Nexus:866" ]
+ "Default | UpdateKey": "Nexus:866"
},
{
// Teleporter
"ID": "Teleporter",
- "UpdateKeys": [ "Chucklefish:4374" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.2": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "Default | UpdateKey": "Chucklefish:4374",
+ "~1.0.2 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.0.2 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// The Long Night
"ID": "Pathoschild.TheLongNight",
- "UpdateKeys": [ "Nexus:1369" ]
+ "Default | UpdateKey": "Nexus:1369"
},
{
// Three-heart Dance Partner
"ID": "ThreeHeartDancePartner",
- "UpdateKeys": [ "Nexus:500" ],
- "Compatibility": {
- "~1.0.1": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "Default | UpdateKey": "Nexus:500",
+ "~1.0.1 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// TimeFreeze
- "ID": "4108e859-333c-4fec-a1a7-d2e18c1019fe | Omegasis.TimeFreeze", // changed in 1.2
- "UpdateKeys": [ "Nexus:973" ] // added in 1.2.1
+ "ID": "Omegasis.TimeFreeze",
+ "FormerIDs": "4108e859-333c-4fec-a1a7-d2e18c1019fe", // changed in 1.2
+ "Default | UpdateKey": "Nexus:973" // added in 1.2.1
},
{
// Time Reminder
"ID": "KoihimeNakamura.TimeReminder",
- "UpdateKeys": [ "Nexus:1000" ],
- "MapLocalVersions": {
- "1.0-20170314": "1.0.2"
- }
+ "MapLocalVersions": { "1.0-20170314": "1.0.2" },
+ "Default | UpdateKey": "Nexus:1000"
},
{
// TimeSpeed
- "ID": "TimeSpeed.dll | {ID:'4108e859-333c-4fec-a1a7-d2e18c1019fe', Name:'TimeSpeed'} | {ID:'4108e859-333c-4fec-a1a7-d2e18c1019fe', Name:'TimeSpeed Mod (unofficial)'} | community.TimeSpeed", // changed in 2.0.3 and 2.1; disambiguate other mods by Alpha_Omegasis
- "UpdateKeys": [ "Nexus:169" ],
- "Compatibility": {
- "~2.2": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "community.TimeSpeed",
+ "FormerIDs": "TimeSpeed.dll | {ID:'4108e859-333c-4fec-a1a7-d2e18c1019fe', Name:'TimeSpeed'} | {ID:'4108e859-333c-4fec-a1a7-d2e18c1019fe', Name:'TimeSpeed Mod (unofficial)'}", // changed in 2.0.3 and 2.1; disambiguate other mods by Alpha_Omegasis
+ "Default | UpdateKey": "Nexus:169",
+ "~2.2 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// TractorMod
- "ID": "BlueMod_TractorMod | PhthaloBlue.TractorMod | community.TractorMod | Pathoschild.TractorMod", // changed in 3.2, 4.0 beta, and 4.0
- "UpdateKeys": [ "Nexus:1401" ]
+ "ID": "Pathoschild.TractorMod",
+ "FormerIDs": "BlueMod_TractorMod | PhthaloBlue.TractorMod | community.TractorMod", // changed in 3.2, 4.0 beta, and 4.0
+ "Default | UpdateKey": "Nexus:1401"
},
{
// TrainerMod
"ID": "SMAPI.TrainerMod",
- "Compatibility": {
- "~": {
- "Status": "Obsolete",
- "ReasonPhrase": "replaced by ConsoleCommands, which is added by the SMAPI installer."
- }
- }
+ "~ | Status": "Obsolete",
+ "~ | StatusReasonPhrase": "replaced by ConsoleCommands, which is added by the SMAPI installer."
},
{
// Tree Transplant
"ID": "TreeTransplant",
- "UpdateKeys": [ "Nexus:1342" ]
+ "Default | UpdateKey": "Nexus:1342"
},
{
// UI Info Suite
"ID": "Cdaragorn.UiInfoSuite",
- "UpdateKeys": [ "Nexus:1150" ]
+ "Default | UpdateKey": "Nexus:1150"
},
{
// UiModSuite
"ID": "Demiacle.UiModSuite",
- "UpdateKeys": [ "Nexus:1023" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SDV 1.2
- },
- "MapLocalVersions": {
- "0.5": "1.0" // not updated in manifest
- }
+ "MapLocalVersions": { "0.5": "1.0" }, // not updated in manifest
+ "Default | UpdateKey": "Nexus:1023",
+ "~1.0 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Variable Grass
"ID": "dantheman999.VariableGrass",
- "UpdateKeys": [ "GitHub:dantheman999301/StardewMods" ]
+ "Default | UpdateKey": "GitHub:dantheman999301/StardewMods"
},
{
// Vertical Toolbar
"ID": "SB_VerticalToolMenu",
- "UpdateKeys": [ "Nexus:943" ]
+ "Default | UpdateKey": "Nexus:943"
},
{
// WakeUp
"ID": "WakeUp.dll",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.2": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "~1.0.2 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.0.2 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// Wallpaper Fix
"ID": "WallpaperFix.dll",
- "UpdateKeys": [ "Chucklefish:4211" ],
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.1": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ "Default | UpdateKey": "Chucklefish:4211",
+ "~1.1 | Status": "AssumeBroken", // broke in SMAPI 2.0
+ "~1.1 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// WarpAnimals
"ID": "Symen.WarpAnimals",
- "UpdateKeys": [ "Nexus:1400" ]
+ "Default | UpdateKey": "Nexus:1400"
},
{
// Weather Controller
"ID": "WeatherController.dll",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0.2": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "~1.0.2 | Status": "AssumeBroken", // broke in SDV 1.2
+ "~1.0.2 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// What Farm Cave / WhatAMush
"ID": "WhatAMush",
- "UpdateKeys": [ "Nexus:1097" ]
+ "Default | UpdateKey": "Nexus:1097"
},
{
// WHats Up
"ID": "wHatsUp",
- "UpdateKeys": [ "Nexus:1082" ]
+ "Default | UpdateKey": "Nexus:1082"
},
{
// Wonderful Farm Life
"ID": "WonderfulFarmLife.dll",
- "AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0",
- "Compatibility": {
- "~1.0": { "Status": "AssumeBroken" } // broke in SDV 1.1 or 1.11
- }
+ "~1.0 | Status": "AssumeBroken", // broke in SDV 1.1 or 1.11
+ "~1.0 | AlternativeUrl": "http://stardewvalleywiki.com/Modding:SMAPI_2.0"
},
{
// XmlSerializerRetool
"ID": "XmlSerializerRetool.dll",
- "Compatibility": {
- "~": {
- "Status": "Obsolete",
- "ReasonPhrase": "it's no longer maintained or used."
- }
- }
+ "~ | Status": "Obsolete",
+ "~ | StatusReasonPhrase": "it's no longer maintained or used."
},
{
// Xnb Loader
"ID": "Entoarox.XnbLoader",
- // "UpdateKeys": [ "Chucklefish:4506" ], // Entoarox opted out of mod update checks
- "Compatibility": {
- "~1.0.6": { "Status": "AssumeBroken" } // broke in SMAPI 2.0
- }
+ // "Default | UpdateKey": "Chucklefish:4506", // Entoarox opted out of mod update checks
+ "~1.0.6 | Status": "AssumeBroken" // broke in SMAPI 2.0
},
{
// zDailyIncrease
"ID": "zdailyincrease",
- "UpdateKeys": [ "Chucklefish:4247" ],
- "Compatibility": {
- "~1.2": { "Status": "AssumeBroken" } // broke in SDV 1.2
- },
- "MapRemoteVersions": {
- "1.3.5": "1.3.4" // not updated in manifest
- }
+ "MapRemoteVersions": { "1.3.5": "1.3.4" }, // not updated in manifest
+ "Default | UpdateKey": "Chucklefish:4247",
+ "~1.2 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Zoom Out Extreme
- "ID": "ZoomMod | RockinMods.ZoomMod", // changed circa 1.2.1
- "UpdateKeys": [ "Nexus:1326" ],
- "Compatibility": {
- "~0.1": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "RockinMods.ZoomMod",
+ "FormerIDs": "ZoomMod", // changed circa 1.2.1
+ "Default | UpdateKey": "Nexus:1326",
+ "~0.1 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Zoryn's Better RNG
- "ID": "76b6d1e1-f7ba-4d72-8c32-5a1e6d2716f6 | Zoryn.BetterRNG", // changed in 1.6
- "UpdateKeys": [ "GitHub:Zoryn4163/SMAPI-Mods" ],
- "Compatibility": {
- "~1.6": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Zoryn.BetterRNG",
+ "FormerIDs": "76b6d1e1-f7ba-4d72-8c32-5a1e6d2716f6", // changed in 1.6
+ "Default | UpdateKey": "GitHub:Zoryn4163/SMAPI-Mods",
+ "~1.6 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Zoryn's Calendar Anywhere
- "ID": "a41c01cd-0437-43eb-944f-78cb5a53002a | Zoryn.CalendarAnywhere", // changed in 1.6
- "UpdateKeys": [ "GitHub:Zoryn4163/SMAPI-Mods" ],
- "Compatibility": {
- "~1.6": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Zoryn.CalendarAnywhere",
+ "FormerIDs": "a41c01cd-0437-43eb-944f-78cb5a53002a", // changed in 1.6
+ "Default | UpdateKey": "GitHub:Zoryn4163/SMAPI-Mods",
+ "~1.6 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Zoryn's Durable Fences
- "ID": "56d3439c-7b9b-497e-9496-0c4890e8a00e | Zoryn.DurableFences", // changed in 1.6
- "UpdateKeys": [ "GitHub:Zoryn4163/SMAPI-Mods" ]
+ "ID": "Zoryn.DurableFences",
+ "FormerIDs": "56d3439c-7b9b-497e-9496-0c4890e8a00e", // changed in 1.6
+ "Default | UpdateKey": "GitHub:Zoryn4163/SMAPI-Mods"
},
{
// Zoryn's Health Bars
- "ID": "HealthBars.dll | Zoryn.HealthBars", // changed in 1.6
- "UpdateKeys": [ "GitHub:Zoryn4163/SMAPI-Mods" ],
- "Compatibility": {
- "~1.6": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Zoryn.HealthBars",
+ "FormerIDs": "{EntryDLL: 'HealthBars.dll'}", // changed in 1.6
+ "Default | UpdateKey": "GitHub:Zoryn4163/SMAPI-Mods",
+ "~1.6 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Zoryn's Fishing Mod
- "ID": "fa277b1f-265e-47c3-a84f-cd320cc74949 | Zoryn.FishingMod", // changed in 1.6
- "UpdateKeys": [ "GitHub:Zoryn4163/SMAPI-Mods" ]
+ "ID": "Zoryn.FishingMod",
+ "FormerIDs": "fa277b1f-265e-47c3-a84f-cd320cc74949", // changed in 1.6
+ "Default | UpdateKey": "GitHub:Zoryn4163/SMAPI-Mods"
},
{
// Zoryn's Junimo Deposit Anywhere
- "ID": "f93a4fe8-cade-4146-9335-b5f82fbbf7bc | Zoryn.JunimoDepositAnywhere", // changed in 1.6
- "UpdateKeys": [ "GitHub:Zoryn4163/SMAPI-Mods" ],
- "Compatibility": {
- "~1.7": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Zoryn.JunimoDepositAnywhere",
+ "FormerIDs": "f93a4fe8-cade-4146-9335-b5f82fbbf7bc", // changed in 1.6
+ "Default | UpdateKey": "GitHub:Zoryn4163/SMAPI-Mods",
+ "~1.7 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Zoryn's Movement Mod
- "ID": "8a632929-8335-484f-87dd-c29d2ba3215d | Zoryn.MovementModifier", // changed in 1.6
- "UpdateKeys": [ "GitHub:Zoryn4163/SMAPI-Mods" ],
- "Compatibility": {
- "~1.6": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Zoryn.MovementModifier",
+ "FormerIDs": "8a632929-8335-484f-87dd-c29d2ba3215d", // changed in 1.6
+ "Default | UpdateKey": "GitHub:Zoryn4163/SMAPI-Mods",
+ "~1.6 | Status": "AssumeBroken" // broke in SDV 1.2
},
{
// Zoryn's Regen Mod
- "ID": "dfac4383-1b6b-4f33-ae4e-37fc23e5252e | Zoryn.RegenMod", // changed in 1.6
- "UpdateKeys": [ "GitHub:Zoryn4163/SMAPI-Mods" ],
- "Compatibility": {
- "~1.6": { "Status": "AssumeBroken" } // broke in SDV 1.2
- }
+ "ID": "Zoryn.RegenMod",
+ "FormerIDs": "dfac4383-1b6b-4f33-ae4e-37fc23e5252e", // changed in 1.6
+ "Default | UpdateKey": "GitHub:Zoryn4163/SMAPI-Mods",
+ "~1.6 | Status": "AssumeBroken" // broke in SDV 1.2
}
]
}
diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj
index cd6c4ac3..129c88b0 100644
--- a/src/SMAPI/StardewModdingAPI.csproj
+++ b/src/SMAPI/StardewModdingAPI.csproj
@@ -89,7 +89,9 @@
<Compile Include="Framework\Input\InputState.cs" />
<Compile Include="Framework\Input\InputStatus.cs" />
<Compile Include="Framework\LegacyManifestVersion.cs" />
- <Compile Include="Framework\Models\ModCompatibility.cs" />
+ <Compile Include="Framework\Models\ModDataField.cs" />
+ <Compile Include="Framework\Models\ModDataFieldKey.cs" />
+ <Compile Include="Framework\Models\ParsedModDataRecord.cs" />
<Compile Include="Framework\ModLoading\Finders\EventFinder.cs" />
<Compile Include="Framework\ModLoading\Finders\FieldFinder.cs" />
<Compile Include="Framework\ModLoading\Finders\MethodFinder.cs" />
@@ -110,9 +112,7 @@
<Compile Include="Framework\Exceptions\SAssemblyLoadFailedException.cs" />
<Compile Include="Framework\ModLoading\AssemblyLoadStatus.cs" />
<Compile Include="Framework\Reflection\InterfaceProxyBuilder.cs" />
- <Compile Include="Framework\Serialisation\SmapiConverters\ModCompatibilityArrayConverter.cs" />
<Compile Include="Framework\Serialisation\SmapiConverters\ManifestDependencyArrayConverter.cs" />
- <Compile Include="Framework\Serialisation\SmapiConverters\ModDataIdConverter.cs" />
<Compile Include="Framework\Serialisation\SmapiConverters\SemanticVersionConverter.cs" />
<Compile Include="Framework\Serialisation\SimpleReadOnlyConverter.cs" />
<Compile Include="Framework\Serialisation\CrossplatformConverters\RectangleConverter.cs" />
@@ -154,7 +154,6 @@
<Compile Include="Framework\Utilities\Countdown.cs" />
<Compile Include="Framework\GameVersion.cs" />
<Compile Include="Framework\IModMetadata.cs" />
- <Compile Include="Framework\Models\ModDataID.cs" />
<Compile Include="Framework\ModHelpers\BaseHelper.cs" />
<Compile Include="Framework\ModHelpers\CommandHelper.cs" />
<Compile Include="Framework\ModHelpers\ContentHelper.cs" />