summaryrefslogtreecommitdiff
path: root/src/SMAPI.Toolkit
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI.Toolkit')
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs22
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs16
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs12
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs4
-rw-r--r--src/SMAPI.Toolkit/Framework/SemanticVersionReader.cs126
-rw-r--r--src/SMAPI.Toolkit/SMAPI.Toolkit.csproj5
-rw-r--r--src/SMAPI.Toolkit/SemanticVersion.cs72
-rw-r--r--src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs2
8 files changed, 193 insertions, 66 deletions
diff --git a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs
index f1bcfccc..2f58a3f1 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs
@@ -1,5 +1,3 @@
-using System;
-
namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
{
/// <summary>Metadata about a mod.</summary>
@@ -17,26 +15,6 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
/// <summary>Optional extended data which isn't needed for update checks.</summary>
public ModExtendedMetadataModel Metadata { get; set; }
- /// <summary>The main version.</summary>
- [Obsolete]
- public ModEntryVersionModel Main { get; set; }
-
- /// <summary>The latest optional version, if newer than <see cref="Main"/>.</summary>
- [Obsolete]
- public ModEntryVersionModel Optional { get; set; }
-
- /// <summary>The latest unofficial version, if newer than <see cref="Main"/> and <see cref="Optional"/>.</summary>
- [Obsolete]
- public ModEntryVersionModel Unofficial { get; set; }
-
- /// <summary>The latest unofficial version for the current Stardew Valley or SMAPI beta, if any (see <see cref="HasBetaInfo"/>).</summary>
- [Obsolete]
- public ModEntryVersionModel UnofficialForBeta { get; set; }
-
- /// <summary>Whether a Stardew Valley or SMAPI beta which affects mod compatibility is in progress. If this is true, <see cref="UnofficialForBeta"/> should be used for beta versions of SMAPI instead of <see cref="Unofficial"/>.</summary>
- [Obsolete]
- public bool? HasBetaInfo { get; set; }
-
/// <summary>The errors that occurred while fetching update data.</summary>
public string[] Errors { get; set; } = new string[0];
}
diff --git a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs
index 4a697585..8c21e4e0 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs
@@ -55,7 +55,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
/// <summary>The latest unofficial version, if newer than <see cref="Main"/> and <see cref="Optional"/>.</summary>
public ModEntryVersionModel Unofficial { get; set; }
- /// <summary>The latest unofficial version for the current Stardew Valley or SMAPI beta, if any (see <see cref="HasBetaInfo"/>).</summary>
+ /// <summary>The latest unofficial version for the current Stardew Valley or SMAPI beta, if any.</summary>
public ModEntryVersionModel UnofficialForBeta { get; set; }
/****
@@ -84,6 +84,15 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
/// <summary>The beta game or SMAPI version which broke this mod, if applicable.</summary>
public string BetaBrokeIn { get; set; }
+ /****
+ ** Version mappings
+ ****/
+ /// <summary>Maps local versions to a semantic version for update checks.</summary>
+ public IDictionary<string, string> MapLocalVersions { get; set; }
+
+ /// <summary>Maps remote versions to a semantic version for update checks.</summary>
+ public IDictionary<string, string> MapRemoteVersions { get; set; }
+
/*********
** Public methods
@@ -127,13 +136,16 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
this.BetaCompatibilityStatus = wiki.BetaCompatibility?.Status;
this.BetaCompatibilitySummary = wiki.BetaCompatibility?.Summary;
this.BetaBrokeIn = wiki.BetaCompatibility?.BrokeIn;
+
+ this.MapLocalVersions = wiki.MapLocalVersions;
+ this.MapRemoteVersions = wiki.MapRemoteVersions;
}
// internal DB data
if (db != null)
{
this.ID = this.ID.Union(db.FormerIDs).ToArray();
- this.Name = this.Name ?? db.DisplayName;
+ this.Name ??= db.DisplayName;
}
}
diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
index 384f23fc..c829c0f4 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
@@ -102,6 +102,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
string anchor = this.GetAttribute(node, "id");
string contentPackFor = this.GetAttribute(node, "data-content-pack-for");
string devNote = this.GetAttribute(node, "data-dev-note");
+ string pullRequestUrl = this.GetAttribute(node, "data-pr");
IDictionary<string, string> mapLocalVersions = this.GetAttributeAsVersionMapping(node, "data-map-local-versions");
IDictionary<string, string> mapRemoteVersions = this.GetAttributeAsVersionMapping(node, "data-map-remote-versions");
@@ -132,15 +133,6 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
}
}
- // parse links
- List<Tuple<Uri, string>> metadataLinks = new List<Tuple<Uri, string>>();
- foreach (HtmlNode linkElement in node.Descendants("td").Last().Descendants("a").Skip(1)) // skip anchor link
- {
- string text = linkElement.InnerText.Trim();
- Uri url = new Uri(linkElement.GetAttributeValue("href", ""));
- metadataLinks.Add(Tuple.Create(url, text));
- }
-
// yield model
yield return new WikiModEntry
{
@@ -159,7 +151,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
Compatibility = compatibility,
BetaCompatibility = betaCompatibility,
Warnings = warnings,
- MetadataLinks = metadataLinks.ToArray(),
+ PullRequestUrl = pullRequestUrl,
DevNote = devNote,
MapLocalVersions = mapLocalVersions,
MapRemoteVersions = mapRemoteVersions,
diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
index 931dcd43..474dce3d 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
@@ -57,8 +57,8 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <summary>The human-readable warnings for players about this mod.</summary>
public string[] Warnings { get; set; }
- /// <summary>Extra metadata links (usually for open pull requests).</summary>
- public Tuple<Uri, string>[] MetadataLinks { get; set; }
+ /// <summary>The URL of the pull request which submits changes for an unofficial update to the author, if any.</summary>
+ public string PullRequestUrl { get; set; }
/// <summary>Special notes intended for developers who maintain unofficial updates or submit pull requests. </summary>
public string DevNote { get; set; }
diff --git a/src/SMAPI.Toolkit/Framework/SemanticVersionReader.cs b/src/SMAPI.Toolkit/Framework/SemanticVersionReader.cs
new file mode 100644
index 00000000..489e1c4d
--- /dev/null
+++ b/src/SMAPI.Toolkit/Framework/SemanticVersionReader.cs
@@ -0,0 +1,126 @@
+namespace StardewModdingAPI.Toolkit.Framework
+{
+ /// <summary>Reads strings into a semantic version.</summary>
+ internal static class SemanticVersionReader
+ {
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Parse a semantic version string.</summary>
+ /// <param name="versionStr">The version string to parse.</param>
+ /// <param name="allowNonStandard">Whether to recognize non-standard semver extensions.</param>
+ /// <param name="major">The major version incremented for major API changes.</param>
+ /// <param name="minor">The minor version incremented for backwards-compatible changes.</param>
+ /// <param name="patch">The patch version for backwards-compatible fixes.</param>
+ /// <param name="platformRelease">The platform-specific version (if applicable).</param>
+ /// <param name="prereleaseTag">An optional prerelease tag.</param>
+ /// <param name="buildMetadata">Optional build metadata. This is ignored when determining version precedence.</param>
+ /// <returns>Returns whether the version was successfully parsed.</returns>
+ public static bool TryParse(string versionStr, bool allowNonStandard, out int major, out int minor, out int patch, out int platformRelease, out string prereleaseTag, out string buildMetadata)
+ {
+ // init
+ major = 0;
+ minor = 0;
+ patch = 0;
+ platformRelease = 0;
+ prereleaseTag = null;
+ buildMetadata = null;
+
+ // normalize
+ versionStr = versionStr?.Trim();
+ if (string.IsNullOrWhiteSpace(versionStr))
+ return false;
+ char[] raw = versionStr.ToCharArray();
+
+ // read major/minor version
+ int i = 0;
+ if (!TryParseVersionPart(raw, ref i, out major) || !TryParseLiteral(raw, ref i, '.') || !TryParseVersionPart(raw, ref i, out minor))
+ return false;
+
+ // read optional patch version
+ if (TryParseLiteral(raw, ref i, '.') && !TryParseVersionPart(raw, ref i, out patch))
+ return false;
+
+ // read optional non-standard platform release version
+ if (allowNonStandard && TryParseLiteral(raw, ref i, '.') && !TryParseVersionPart(raw, ref i, out platformRelease))
+ return false;
+
+ // read optional prerelease tag
+ if (TryParseLiteral(raw, ref i, '-') && !TryParseTag(raw, ref i, out prereleaseTag))
+ return false;
+
+ // read optional build tag
+ if (TryParseLiteral(raw, ref i, '+') && !TryParseTag(raw, ref i, out buildMetadata))
+ return false;
+
+ // validate
+ return i == versionStr.Length; // valid if we're at the end
+ }
+
+
+ /*********
+ ** Private methods
+ *********/
+ /// <summary>Try to parse the next characters in a queue as a numeric part.</summary>
+ /// <param name="raw">The raw characters to parse.</param>
+ /// <param name="index">The index of the next character to read.</param>
+ /// <param name="part">The parsed part.</param>
+ private static bool TryParseVersionPart(char[] raw, ref int index, out int part)
+ {
+ part = 0;
+
+ // take digits
+ string str = "";
+ for (int i = index; i < raw.Length && char.IsDigit(raw[i]); i++)
+ str += raw[i];
+
+ // validate
+ if (str.Length == 0)
+ return false;
+ if (str.Length > 1 && str[0] == '0')
+ return false; // can't have leading zeros
+
+ // parse
+ part = int.Parse(str);
+ index += str.Length;
+ return true;
+ }
+
+ /// <summary>Try to parse a literal character.</summary>
+ /// <param name="raw">The raw characters to parse.</param>
+ /// <param name="index">The index of the next character to read.</param>
+ /// <param name="ch">The expected character.</param>
+ private static bool TryParseLiteral(char[] raw, ref int index, char ch)
+ {
+ if (index >= raw.Length || raw[index] != ch)
+ return false;
+
+ index++;
+ return true;
+ }
+
+ /// <summary>Try to parse a tag.</summary>
+ /// <param name="raw">The raw characters to parse.</param>
+ /// <param name="index">The index of the next character to read.</param>
+ /// <param name="tag">The parsed tag.</param>
+ private static bool TryParseTag(char[] raw, ref int index, out string tag)
+ {
+ // read tag length
+ int length = 0;
+ for (int i = index; i < raw.Length && (char.IsLetterOrDigit(raw[i]) || raw[i] == '-' || raw[i] == '.'); i++)
+ length++;
+
+ // validate
+ if (length == 0)
+ {
+ tag = null;
+ return false;
+ }
+
+ // parse
+ tag = new string(raw, index, length);
+ index += length;
+ return true;
+ }
+ }
+}
diff --git a/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj b/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj
index 3bb7e313..16a97dbf 100644
--- a/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj
+++ b/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj
@@ -5,15 +5,14 @@
<RootNamespace>StardewModdingAPI.Toolkit</RootNamespace>
<Description>A library which encapsulates mod-handling logic for mod managers and tools. Not intended for use by mods.</Description>
<TargetFrameworks>net4.5;netstandard2.0</TargetFrameworks>
- <OutputPath>..\..\bin\$(Configuration)\SMAPI.Toolkit</OutputPath>
- <DocumentationFile>..\..\bin\$(Configuration)\SMAPI.Toolkit\$(TargetFramework)\SMAPI.Toolkit.xml</DocumentationFile>
<LangVersion>latest</LangVersion>
+ <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\SMAPI.Toolkit.xml</DocumentationFile>
<PlatformTarget Condition="'$(TargetFramework)' == 'net4.5'">x86</PlatformTarget>
<RootNamespace>StardewModdingAPI.Toolkit</RootNamespace>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="HtmlAgilityPack" Version="1.11.16" />
+ <PackageReference Include="HtmlAgilityPack" Version="1.11.18" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Pathoschild.Http.FluentClient" Version="3.3.1" />
<PackageReference Include="System.Management" Version="4.5.0" Condition="'$(OS)' == 'Windows_NT'" />
diff --git a/src/SMAPI.Toolkit/SemanticVersion.cs b/src/SMAPI.Toolkit/SemanticVersion.cs
index 4955dcae..5ead6dc8 100644
--- a/src/SMAPI.Toolkit/SemanticVersion.cs
+++ b/src/SMAPI.Toolkit/SemanticVersion.cs
@@ -1,5 +1,6 @@
using System;
using System.Text.RegularExpressions;
+using StardewModdingAPI.Toolkit.Framework;
namespace StardewModdingAPI.Toolkit
{
@@ -9,6 +10,8 @@ namespace StardewModdingAPI.Toolkit
/// - short-form "x.y" versions are supported (equivalent to "x.y.0");
/// - hyphens are synonymous with dots in prerelease tags and build metadata (like "-unofficial.3-pathoschild");
/// - and "-unofficial" in prerelease tags is always lower-precedence (e.g. "1.0-beta" is newer than "1.0-unofficial").
+ ///
+ /// This optionally also supports four-part versions, a non-standard extension used by Stardew Valley on ported platforms to represent platform-specific patches to a ported version, represented as a fourth number in the version string.
/// </remarks>
public class SemanticVersion : ISemanticVersion
{
@@ -16,14 +19,7 @@ namespace StardewModdingAPI.Toolkit
** Fields
*********/
/// <summary>A regex pattern matching a valid prerelease or build metadata tag.</summary>
- internal const string TagPattern = @"(?>[a-z0-9]+[\-\.]?)+";
-
- /// <summary>A regex pattern matching a version within a larger string.</summary>
- internal const string UnboundedVersionPattern = @"(?>(?<major>0|[1-9]\d*))\.(?>(?<minor>0|[1-9]\d*))(?>(?:\.(?<patch>0|[1-9]\d*))?)(?:-(?<prerelease>" + SemanticVersion.TagPattern + "))?(?:\\+(?<buildmetadata>" + SemanticVersion.TagPattern + "))?";
-
- /// <summary>A regular expression matching a semantic version string.</summary>
- /// <remarks>This pattern is derived from the BNF documentation in the <a href="https://github.com/mojombo/semver">semver repo</a>, with deviations to support the Stardew Valley mod conventions (see remarks on <see cref="SemanticVersion"/>).</remarks>
- internal static readonly Regex Regex = new Regex($@"^{SemanticVersion.UnboundedVersionPattern}$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
+ private const string TagPattern = @"(?>[a-z0-9]+[\-\.]?)+";
/*********
@@ -38,6 +34,9 @@ namespace StardewModdingAPI.Toolkit
/// <summary>The patch version for backwards-compatible bug fixes.</summary>
public int PatchVersion { get; }
+ /// <summary>The platform release. This is a non-standard semver extension used by Stardew Valley on ported platforms to represent platform-specific patches to a ported version, represented as a fourth number in the version string.</summary>
+ public int PlatformRelease { get; }
+
/// <summary>An optional prerelease tag.</summary>
public string PrereleaseTag { get; }
@@ -52,13 +51,15 @@ namespace StardewModdingAPI.Toolkit
/// <param name="major">The major version incremented for major API changes.</param>
/// <param name="minor">The minor version incremented for backwards-compatible changes.</param>
/// <param name="patch">The patch version for backwards-compatible fixes.</param>
+ /// <param name="platformRelease">The platform-specific version (if applicable).</param>
/// <param name="prereleaseTag">An optional prerelease tag.</param>
/// <param name="buildMetadata">Optional build metadata. This is ignored when determining version precedence.</param>
- public SemanticVersion(int major, int minor, int patch, string prereleaseTag = null, string buildMetadata = null)
+ public SemanticVersion(int major, int minor, int patch, int platformRelease = 0, string prereleaseTag = null, string buildMetadata = null)
{
this.MajorVersion = major;
this.MinorVersion = minor;
this.PatchVersion = patch;
+ this.PlatformRelease = platformRelease;
this.PrereleaseTag = this.GetNormalizedTag(prereleaseTag);
this.BuildMetadata = this.GetNormalizedTag(buildMetadata);
@@ -82,23 +83,22 @@ namespace StardewModdingAPI.Toolkit
/// <summary>Construct an instance.</summary>
/// <param name="version">The semantic version string.</param>
+ /// <param name="allowNonStandard">Whether to recognize non-standard semver extensions.</param>
/// <exception cref="ArgumentNullException">The <paramref name="version"/> is null.</exception>
/// <exception cref="FormatException">The <paramref name="version"/> is not a valid semantic version.</exception>
- public SemanticVersion(string version)
+ public SemanticVersion(string version, bool allowNonStandard = false)
{
- // parse
if (version == null)
throw new ArgumentNullException(nameof(version), "The input version string can't be null.");
- var match = SemanticVersion.Regex.Match(version.Trim());
- if (!match.Success)
+ if (!SemanticVersionReader.TryParse(version, allowNonStandard, out int major, out int minor, out int patch, out int platformRelease, out string prereleaseTag, out string buildMetadata) || (!allowNonStandard && platformRelease != 0))
throw new FormatException($"The input '{version}' isn't a valid semantic version.");
- // initialize
- 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.PrereleaseTag = match.Groups["prerelease"].Success ? this.GetNormalizedTag(match.Groups["prerelease"].Value) : null;
- this.BuildMetadata = match.Groups["buildmetadata"].Success ? this.GetNormalizedTag(match.Groups["buildmetadata"].Value) : null;
+ this.MajorVersion = major;
+ this.MinorVersion = minor;
+ this.PatchVersion = patch;
+ this.PlatformRelease = platformRelease;
+ this.PrereleaseTag = prereleaseTag;
+ this.BuildMetadata = buildMetadata;
this.AssertValid();
}
@@ -110,7 +110,7 @@ namespace StardewModdingAPI.Toolkit
{
if (other == null)
throw new ArgumentNullException(nameof(other));
- return this.CompareTo(other.MajorVersion, other.MinorVersion, other.PatchVersion, other.PrereleaseTag);
+ return this.CompareTo(other.MajorVersion, other.MinorVersion, other.PatchVersion, (other as SemanticVersion)?.PlatformRelease ?? 0, other.PrereleaseTag);
}
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
@@ -139,7 +139,7 @@ namespace StardewModdingAPI.Toolkit
/// <exception cref="FormatException">The specified version is not a valid semantic version.</exception>
public bool IsOlderThan(string other)
{
- return this.IsOlderThan(new SemanticVersion(other));
+ return this.IsOlderThan(new SemanticVersion(other, allowNonStandard: true));
}
/// <summary>Get whether this version is newer than the specified version.</summary>
@@ -154,7 +154,7 @@ namespace StardewModdingAPI.Toolkit
/// <exception cref="FormatException">The specified version is not a valid semantic version.</exception>
public bool IsNewerThan(string other)
{
- return this.IsNewerThan(new SemanticVersion(other));
+ return this.IsNewerThan(new SemanticVersion(other, allowNonStandard: true));
}
/// <summary>Get whether this version is between two specified versions (inclusively).</summary>
@@ -171,13 +171,15 @@ namespace StardewModdingAPI.Toolkit
/// <exception cref="FormatException">One of the specified versions is not a valid semantic version.</exception>
public bool IsBetween(string min, string max)
{
- return this.IsBetween(new SemanticVersion(min), new SemanticVersion(max));
+ return this.IsBetween(new SemanticVersion(min, allowNonStandard: true), new SemanticVersion(max, allowNonStandard: true));
}
/// <summary>Get a string representation of the version.</summary>
public override string ToString()
{
string version = $"{this.MajorVersion}.{this.MinorVersion}.{this.PatchVersion}";
+ if (this.PlatformRelease != 0)
+ version += $".{this.PlatformRelease}";
if (this.PrereleaseTag != null)
version += $"-{this.PrereleaseTag}";
if (this.BuildMetadata != null)
@@ -185,15 +187,30 @@ namespace StardewModdingAPI.Toolkit
return version;
}
+ /// <summary>Whether the version uses non-standard extensions, like four-part game versions on some platforms.</summary>
+ public bool IsNonStandard()
+ {
+ return this.PlatformRelease != 0;
+ }
+
/// <summary>Parse a version string without throwing an exception if it fails.</summary>
/// <param name="version">The version string.</param>
/// <param name="parsed">The parsed representation.</param>
/// <returns>Returns whether parsing the version succeeded.</returns>
public static bool TryParse(string version, out ISemanticVersion parsed)
{
+ return SemanticVersion.TryParseNonStandard(version, out parsed) && !parsed.IsNonStandard();
+ }
+
+ /// <summary>Parse a version string without throwing an exception if it fails, including support for non-standard extensions like <see cref="IPlatformSpecificVersion"/>.</summary>
+ /// <param name="version">The version string.</param>
+ /// <param name="parsed">The parsed representation.</param>
+ /// <returns>Returns whether parsing the version succeeded.</returns>
+ public static bool TryParseNonStandard(string version, out ISemanticVersion parsed)
+ {
try
{
- parsed = new SemanticVersion(version);
+ parsed = new SemanticVersion(version, true);
return true;
}
catch
@@ -219,8 +236,9 @@ namespace StardewModdingAPI.Toolkit
/// <param name="otherMajor">The major version to compare with this instance.</param>
/// <param name="otherMinor">The minor version to compare with this instance.</param>
/// <param name="otherPatch">The patch version to compare with this instance.</param>
+ /// <param name="otherPlatformRelease">The non-standard platform release to compare with this instance.</param>
/// <param name="otherTag">The prerelease tag to compare with this instance.</param>
- private int CompareTo(int otherMajor, int otherMinor, int otherPatch, string otherTag)
+ private int CompareTo(int otherMajor, int otherMinor, int otherPatch, int otherPlatformRelease, string otherTag)
{
const int same = 0;
const int curNewer = 1;
@@ -233,6 +251,8 @@ namespace StardewModdingAPI.Toolkit
return this.MinorVersion.CompareTo(otherMinor);
if (this.PatchVersion != otherPatch)
return this.PatchVersion.CompareTo(otherPatch);
+ if (this.PlatformRelease != otherPlatformRelease)
+ return this.PlatformRelease.CompareTo(otherPlatformRelease);
if (this.PrereleaseTag == otherTag)
return same;
@@ -274,7 +294,7 @@ namespace StardewModdingAPI.Toolkit
}
// fallback (this should never happen)
- return string.Compare(this.ToString(), new SemanticVersion(otherMajor, otherMinor, otherPatch, otherTag).ToString(), StringComparison.InvariantCultureIgnoreCase);
+ return string.Compare(this.ToString(), new SemanticVersion(otherMajor, otherMinor, otherPatch, otherPlatformRelease, otherTag).ToString(), StringComparison.InvariantCultureIgnoreCase);
}
/// <summary>Assert that the current version is valid.</summary>
diff --git a/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs b/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs
index ece4a72e..e1b9db1d 100644
--- a/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs
+++ b/src/SMAPI.Toolkit/Serialization/Converters/SemanticVersionConverter.cs
@@ -68,7 +68,7 @@ namespace StardewModdingAPI.Toolkit.Serialization.Converters
int patch = obj.ValueIgnoreCase<int>(nameof(ISemanticVersion.PatchVersion));
string prereleaseTag = obj.ValueIgnoreCase<string>(nameof(ISemanticVersion.PrereleaseTag));
- return new SemanticVersion(major, minor, patch, prereleaseTag);
+ return new SemanticVersion(major, minor, patch, prereleaseTag: prereleaseTag);
}
/// <summary>Read a JSON string.</summary>