move incompatible mod logic into mod registry
This commit is contained in:
parent
3005270437
commit
6b26eceb57
|
@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using StardewModdingAPI.Framework.Models;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework
|
namespace StardewModdingAPI.Framework
|
||||||
{
|
{
|
||||||
|
@ -18,10 +20,21 @@ namespace StardewModdingAPI.Framework
|
||||||
/// <summary>The friendly mod names treated as deprecation warning sources (assembly full name => mod name).</summary>
|
/// <summary>The friendly mod names treated as deprecation warning sources (assembly full name => mod name).</summary>
|
||||||
private readonly IDictionary<string, string> ModNamesByAssembly = new Dictionary<string, string>();
|
private readonly IDictionary<string, string> ModNamesByAssembly = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
/// <summary>The mod versions which should be disabled due to incompatibility.</summary>
|
||||||
|
private readonly IncompatibleMod[] IncompatibleMods;
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
** Public methods
|
** Public methods
|
||||||
*********/
|
*********/
|
||||||
|
/// <summary>Construct an instance.</summary>
|
||||||
|
/// <param name="incompatibleMods">The mod versions which should be disabled due to incompatibility.</param>
|
||||||
|
public ModRegistry(IEnumerable<IncompatibleMod> incompatibleMods)
|
||||||
|
{
|
||||||
|
this.IncompatibleMods = incompatibleMods.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/****
|
/****
|
||||||
** IModRegistry
|
** IModRegistry
|
||||||
****/
|
****/
|
||||||
|
@ -113,5 +126,22 @@ namespace StardewModdingAPI.Framework
|
||||||
// no known assembly found
|
// no known assembly found
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Get a record indicating why a mod is incompatible (if applicable).</summary>
|
||||||
|
/// <param name="manifest">The mod manifest.</param>
|
||||||
|
/// <returns>Returns the incompatibility record if applicable, else <c>null</c>.</returns>
|
||||||
|
internal IncompatibleMod GetIncompatibilityRecord(IManifest manifest)
|
||||||
|
{
|
||||||
|
string key = !string.IsNullOrWhiteSpace(manifest.UniqueID) ? manifest.UniqueID : manifest.EntryDll;
|
||||||
|
return (
|
||||||
|
from mod in this.IncompatibleMods
|
||||||
|
where
|
||||||
|
mod.ID == key
|
||||||
|
&& (mod.LowerSemanticVersion == null || !manifest.Version.IsOlderThan(mod.LowerSemanticVersion))
|
||||||
|
&& !manifest.Version.IsNewerThan(mod.UpperSemanticVersion)
|
||||||
|
&& (string.IsNullOrWhiteSpace(mod.ForceCompatibleVersion) || !Regex.IsMatch(manifest.Version.ToString(), mod.ForceCompatibleVersion, RegexOptions.IgnoreCase))
|
||||||
|
select mod
|
||||||
|
).FirstOrDefault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Text.RegularExpressions;
|
using System.Runtime.Serialization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Models
|
namespace StardewModdingAPI.Framework.Models
|
||||||
{
|
{
|
||||||
|
@ -8,6 +9,9 @@ namespace StardewModdingAPI.Framework.Models
|
||||||
/*********
|
/*********
|
||||||
** Accessors
|
** Accessors
|
||||||
*********/
|
*********/
|
||||||
|
/****
|
||||||
|
** From config
|
||||||
|
****/
|
||||||
/// <summary>The unique mod ID.</summary>
|
/// <summary>The unique mod ID.</summary>
|
||||||
public string ID { get; set; }
|
public string ID { get; set; }
|
||||||
|
|
||||||
|
@ -34,24 +38,28 @@ namespace StardewModdingAPI.Framework.Models
|
||||||
public string ReasonPhrase { get; set; }
|
public string ReasonPhrase { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
/****
|
||||||
|
** Injected
|
||||||
|
****/
|
||||||
|
/// <summary>The semantic version corresponding to <see cref="LowerVersion"/>.</summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public ISemanticVersion LowerSemanticVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The semantic version corresponding to <see cref="UpperVersion"/>.</summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public ISemanticVersion UpperSemanticVersion { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
** Public methods
|
** Private methods
|
||||||
*********/
|
*********/
|
||||||
/// <summary>Get whether the specified version is compatible according to this metadata.</summary>
|
/// <summary>The method called when the model finishes deserialising.</summary>
|
||||||
/// <param name="version">The current version of the matching mod.</param>
|
/// <param name="context">The deserialisation context.</param>
|
||||||
public bool IsCompatible(ISemanticVersion version)
|
[OnDeserialized]
|
||||||
|
private void OnDeserialized(StreamingContext context)
|
||||||
{
|
{
|
||||||
ISemanticVersion lowerVersion = this.LowerVersion != null ? new SemanticVersion(this.LowerVersion) : null;
|
this.LowerSemanticVersion = this.LowerVersion != null ? new SemanticVersion(this.LowerVersion) : null;
|
||||||
ISemanticVersion upperVersion = new SemanticVersion(this.UpperVersion);
|
this.UpperSemanticVersion = this.UpperVersion != null ? new SemanticVersion(this.UpperVersion) : null;
|
||||||
|
|
||||||
// ignore versions not in range
|
|
||||||
if (lowerVersion != null && version.IsOlderThan(lowerVersion))
|
|
||||||
return true;
|
|
||||||
if (version.IsNewerThan(upperVersion))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// allow versions matching override
|
|
||||||
return !string.IsNullOrWhiteSpace(this.ForceCompatibleVersion) && Regex.IsMatch(version.ToString(), this.ForceCompatibleVersion, RegexOptions.IgnoreCase);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace StardewModdingAPI
|
||||||
internal SGame GameInstance;
|
internal SGame GameInstance;
|
||||||
|
|
||||||
/// <summary>Tracks the installed mods.</summary>
|
/// <summary>Tracks the installed mods.</summary>
|
||||||
internal readonly ModRegistry ModRegistry = new ModRegistry();
|
internal readonly ModRegistry ModRegistry;
|
||||||
|
|
||||||
/// <summary>Manages deprecation warnings.</summary>
|
/// <summary>Manages deprecation warnings.</summary>
|
||||||
internal readonly DeprecationManager DeprecationManager;
|
internal readonly DeprecationManager DeprecationManager;
|
||||||
|
@ -92,6 +92,7 @@ namespace StardewModdingAPI
|
||||||
|
|
||||||
// initialise
|
// initialise
|
||||||
this.Monitor = new Monitor("SMAPI", this.ConsoleManager, this.LogFile, this.ExitGameImmediately) { WriteToConsole = writeToConsole };
|
this.Monitor = new Monitor("SMAPI", this.ConsoleManager, this.LogFile, this.ExitGameImmediately) { WriteToConsole = writeToConsole };
|
||||||
|
this.ModRegistry = new ModRegistry(this.Settings.IncompatibleMods);
|
||||||
this.DeprecationManager = new DeprecationManager(this.Monitor, this.ModRegistry);
|
this.DeprecationManager = new DeprecationManager(this.Monitor, this.ModRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,28 +389,22 @@ namespace StardewModdingAPI
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate known incompatible mods
|
// validate compatibility
|
||||||
|
IncompatibleMod compatibility = this.ModRegistry.GetIncompatibilityRecord(manifest);
|
||||||
|
if (compatibility != null)
|
||||||
{
|
{
|
||||||
string modKey = !string.IsNullOrWhiteSpace(manifest.UniqueID) ? manifest.UniqueID : manifest.EntryDll;
|
bool hasOfficialUrl = !string.IsNullOrWhiteSpace(compatibility.UpdateUrl);
|
||||||
IncompatibleMod compatibility = this.Settings.IncompatibleMods.FirstOrDefault(p => p.ID == modKey);
|
bool hasUnofficialUrl = !string.IsNullOrWhiteSpace(compatibility.UnofficialUpdateUrl);
|
||||||
if(compatibility != null)
|
|
||||||
{
|
|
||||||
if (!compatibility.IsCompatible(manifest.Version))
|
|
||||||
{
|
|
||||||
bool hasOfficialUrl = !string.IsNullOrWhiteSpace(compatibility.UpdateUrl);
|
|
||||||
bool hasUnofficialUrl = !string.IsNullOrWhiteSpace(compatibility.UnofficialUpdateUrl);
|
|
||||||
|
|
||||||
string reasonPhrase = compatibility.ReasonPhrase ?? "it isn't compatible with the latest version of the game";
|
string reasonPhrase = compatibility.ReasonPhrase ?? "it isn't compatible with the latest version of the game";
|
||||||
string warning = $"Skipped {compatibility.Name} because {reasonPhrase}. Please check for a version newer than {compatibility.UpperVersion} here:";
|
string warning = $"Skipped {compatibility.Name} because {reasonPhrase}. Please check for a version newer than {compatibility.UpperVersion} here:";
|
||||||
if (hasOfficialUrl)
|
if (hasOfficialUrl)
|
||||||
warning += !hasUnofficialUrl ? $" {compatibility.UpdateUrl}" : $"{Environment.NewLine}- official mod: {compatibility.UpdateUrl}";
|
warning += !hasUnofficialUrl ? $" {compatibility.UpdateUrl}" : $"{Environment.NewLine}- official mod: {compatibility.UpdateUrl}";
|
||||||
if (hasUnofficialUrl)
|
if (hasUnofficialUrl)
|
||||||
warning += $"{Environment.NewLine}- unofficial update: {compatibility.UnofficialUpdateUrl}";
|
warning += $"{Environment.NewLine}- unofficial update: {compatibility.UnofficialUpdateUrl}";
|
||||||
|
|
||||||
this.Monitor.Log(warning, LogLevel.Error);
|
this.Monitor.Log(warning, LogLevel.Error);
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate SMAPI version
|
// validate SMAPI version
|
||||||
|
|
|
@ -63,9 +63,13 @@ namespace StardewModdingAPI
|
||||||
|
|
||||||
/// <summary>Get an integer indicating whether this version precedes (less than 0), supercedes (more than 0), or is equivalent to (0) the specified version.</summary>
|
/// <summary>Get an integer indicating whether this version precedes (less than 0), supercedes (more than 0), or is equivalent to (0) the specified version.</summary>
|
||||||
/// <param name="other">The version to compare with this instance.</param>
|
/// <param name="other">The version to compare with this instance.</param>
|
||||||
|
/// <exception cref="ArgumentNullException">The <paramref name="other"/> value is null.</exception>
|
||||||
/// <remarks>The implementation is defined by Semantic Version 2.0 (http://semver.org/).</remarks>
|
/// <remarks>The implementation is defined by Semantic Version 2.0 (http://semver.org/).</remarks>
|
||||||
public int CompareTo(ISemanticVersion other)
|
public int CompareTo(ISemanticVersion other)
|
||||||
{
|
{
|
||||||
|
if(other == null)
|
||||||
|
throw new ArgumentNullException(nameof(other));
|
||||||
|
|
||||||
const int same = 0;
|
const int same = 0;
|
||||||
const int curNewer = 1;
|
const int curNewer = 1;
|
||||||
const int curOlder = -1;
|
const int curOlder = -1;
|
||||||
|
|
Loading…
Reference in New Issue