diff --git a/docs/release-notes.md b/docs/release-notes.md
index 4e2d7cab..2783ebc2 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -48,9 +48,12 @@
* Fixed `Context.IsPlayerFree` being true before the player finishes transitioning to a new location in multiplayer.
* Suppressed the game's 'added crickets' debug output.
* Updated dependencies (Harmony 1.0.9.1 → 1.2.0.1, Mono.Cecil 0.10 → 0.10.1).
- * **Deprecation:** non-string manifest versions are now deprecated and will no longer work in SMAPI 3.0.
- * **Breaking change:** `helper.ModRegistry` now returns `IModInfo` instead of `IManifest` directly. This lets SMAPI return more metadata about mods.
- * **Breaking change:** most SMAPI files have been moved into a `smapi-internal` subfolder. This won't affect compiled mod releases, but you'll need to update the build config NuGet package.
+ * **Deprecations:**
+ * Non-string manifest versions are now deprecated and will no longer work in SMAPI 3.0. Affected mods should be updated to use a string version, like `"Version": "1.0.0"`.
+ * `ISemanticVersion.Build` is now deprecated and will be removed in SMAPI 3.0. Affected mods should use `ISemanticVersion.PrereleaseTag` instead.
+ * **Breaking changes:**
+ * `helper.ModRegistry` now returns `IModInfo` instead of `IManifest` directly. This lets SMAPI return more metadata about mods.
+ * Most SMAPI files have been moved into a `smapi-internal` subfolder. This won't affect compiled mod releases, but you'll need to update the build config NuGet package.
* For SMAPI developers:
* Added support for parallel stable/beta unofficial updates in update checks.
diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs
index 6cb564ce..7567c6db 100644
--- a/src/SMAPI/Framework/SCore.cs
+++ b/src/SMAPI/Framework/SCore.cs
@@ -77,7 +77,7 @@ namespace StardewModdingAPI.Framework
/// Manages deprecation warnings.
/// This is initialised after the game starts.
- private DeprecationManager DeprecationManager;
+ private readonly DeprecationManager DeprecationManager;
/// Manages SMAPI events for mods.
private readonly EventManager EventManager;
@@ -134,6 +134,10 @@ namespace StardewModdingAPI.Framework
};
this.MonitorForGame = this.GetSecondaryMonitor("game");
this.EventManager = new EventManager(this.Monitor, this.ModRegistry);
+ this.DeprecationManager = new DeprecationManager(this.Monitor, this.ModRegistry);
+
+ // inject deprecation managers
+ SemanticVersion.DeprecationManager = this.DeprecationManager;
// init logging
this.Monitor.Log($"SMAPI {Constants.ApiVersion} with Stardew Valley {Constants.GameVersion} on {EnvironmentUtility.GetFriendlyPlatformName(Constants.Platform)}", LogLevel.Info);
@@ -340,9 +344,6 @@ namespace StardewModdingAPI.Framework
/// Initialise SMAPI and mods after the game starts.
private void InitialiseAfterGameStart()
{
- // load core components
- this.DeprecationManager = new DeprecationManager(this.Monitor, this.ModRegistry);
-
// redirect direct console output
if (this.MonitorForGame.WriteToConsole)
this.ConsoleManager.OnMessageIntercepted += message => this.HandleConsoleMessage(this.MonitorForGame, message);
diff --git a/src/SMAPI/SemanticVersion.cs b/src/SMAPI/SemanticVersion.cs
index a65afeb8..401f62c2 100644
--- a/src/SMAPI/SemanticVersion.cs
+++ b/src/SMAPI/SemanticVersion.cs
@@ -1,5 +1,6 @@
using System;
using Newtonsoft.Json;
+using StardewModdingAPI.Framework;
namespace StardewModdingAPI
{
@@ -12,6 +13,9 @@ namespace StardewModdingAPI
/// The underlying semantic version implementation.
private readonly ISemanticVersion Version;
+ /// Manages deprecation warnings.
+ internal static DeprecationManager DeprecationManager { get; set; }
+
/*********
** Accessors
@@ -26,7 +30,18 @@ namespace StardewModdingAPI
public int PatchVersion => this.Version.PatchVersion;
/// An optional build tag.
- public string Build => this.Version.Build;
+ [Obsolete("Use " + nameof(ISemanticVersion.PrereleaseTag) + " instead")]
+ public string Build
+ {
+ get
+ {
+ SemanticVersion.DeprecationManager?.Warn($"{nameof(ISemanticVersion)}.{nameof(ISemanticVersion.Build)}", "2.8", DeprecationLevel.Notice);
+ return this.Version.PrereleaseTag;
+ }
+ }
+
+ /// An optional prerelease tag.
+ public string PrereleaseTag => this.Version.PrereleaseTag;
/*********
diff --git a/src/StardewModdingAPI.Toolkit.CoreInterfaces/ISemanticVersion.cs b/src/StardewModdingAPI.Toolkit.CoreInterfaces/ISemanticVersion.cs
index 961ef777..6631b01d 100644
--- a/src/StardewModdingAPI.Toolkit.CoreInterfaces/ISemanticVersion.cs
+++ b/src/StardewModdingAPI.Toolkit.CoreInterfaces/ISemanticVersion.cs
@@ -18,8 +18,12 @@ namespace StardewModdingAPI
int PatchVersion { get; }
/// An optional build tag.
+ [Obsolete("Use " + nameof(ISemanticVersion.PrereleaseTag) + " instead")]
string Build { get; }
+ /// An optional prerelease tag.
+ string PrereleaseTag { get; }
+
/*********
** Accessors
diff --git a/src/StardewModdingAPI.Toolkit/SemanticVersion.cs b/src/StardewModdingAPI.Toolkit/SemanticVersion.cs
index de33df2f..a7990d13 100644
--- a/src/StardewModdingAPI.Toolkit/SemanticVersion.cs
+++ b/src/StardewModdingAPI.Toolkit/SemanticVersion.cs
@@ -40,7 +40,11 @@ namespace StardewModdingAPI.Toolkit
public int PatchVersion { get; }
/// An optional prerelease tag.
- public string Build { get; }
+ [Obsolete("Use " + nameof(ISemanticVersion.PrereleaseTag) + " instead")]
+ public string Build => this.PrereleaseTag;
+
+ /// An optional prerelease tag.
+ public string PrereleaseTag { get; }
/// Whether the version was parsed from the legacy object format.
public bool IsLegacyFormat { get; }
@@ -60,7 +64,7 @@ namespace StardewModdingAPI.Toolkit
this.MajorVersion = major;
this.MinorVersion = minor;
this.PatchVersion = patch;
- this.Build = this.GetNormalisedTag(tag);
+ this.PrereleaseTag = this.GetNormalisedTag(tag);
this.IsLegacyFormat = isLegacyFormat;
this.AssertValid();
@@ -98,7 +102,7 @@ namespace StardewModdingAPI.Toolkit
this.MajorVersion = int.Parse(match.Groups["major"].Value);
this.MinorVersion = match.Groups["minor"].Success ? int.Parse(match.Groups["minor"].Value) : 0;
this.PatchVersion = match.Groups["patch"].Success ? int.Parse(match.Groups["patch"].Value) : 0;
- this.Build = match.Groups["prerelease"].Success ? this.GetNormalisedTag(match.Groups["prerelease"].Value) : null;
+ this.PrereleaseTag = match.Groups["prerelease"].Success ? this.GetNormalisedTag(match.Groups["prerelease"].Value) : null;
this.AssertValid();
}