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.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using StardewModdingAPI.Framework.Models;
|
||||
|
||||
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>
|
||||
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
|
||||
*********/
|
||||
/// <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
|
||||
****/
|
||||
|
@ -113,5 +126,22 @@ namespace StardewModdingAPI.Framework
|
|||
// no known assembly found
|
||||
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
|
||||
{
|
||||
|
@ -8,6 +9,9 @@ namespace StardewModdingAPI.Framework.Models
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/****
|
||||
** From config
|
||||
****/
|
||||
/// <summary>The unique mod ID.</summary>
|
||||
public string ID { get; set; }
|
||||
|
||||
|
@ -34,24 +38,28 @@ namespace StardewModdingAPI.Framework.Models
|
|||
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>
|
||||
/// <param name="version">The current version of the matching mod.</param>
|
||||
public bool IsCompatible(ISemanticVersion version)
|
||||
/// <summary>The method called when the model finishes deserialising.</summary>
|
||||
/// <param name="context">The deserialisation context.</param>
|
||||
[OnDeserialized]
|
||||
private void OnDeserialized(StreamingContext context)
|
||||
{
|
||||
ISemanticVersion lowerVersion = this.LowerVersion != null ? new SemanticVersion(this.LowerVersion) : null;
|
||||
ISemanticVersion upperVersion = new SemanticVersion(this.UpperVersion);
|
||||
|
||||
// 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);
|
||||
this.LowerSemanticVersion = this.LowerVersion != null ? new SemanticVersion(this.LowerVersion) : null;
|
||||
this.UpperSemanticVersion = this.UpperVersion != null ? new SemanticVersion(this.UpperVersion) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace StardewModdingAPI
|
|||
internal SGame GameInstance;
|
||||
|
||||
/// <summary>Tracks the installed mods.</summary>
|
||||
internal readonly ModRegistry ModRegistry = new ModRegistry();
|
||||
internal readonly ModRegistry ModRegistry;
|
||||
|
||||
/// <summary>Manages deprecation warnings.</summary>
|
||||
internal readonly DeprecationManager DeprecationManager;
|
||||
|
@ -92,6 +92,7 @@ namespace StardewModdingAPI
|
|||
|
||||
// initialise
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -388,28 +389,22 @@ namespace StardewModdingAPI
|
|||
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;
|
||||
IncompatibleMod compatibility = this.Settings.IncompatibleMods.FirstOrDefault(p => p.ID == modKey);
|
||||
if(compatibility != null)
|
||||
{
|
||||
if (!compatibility.IsCompatible(manifest.Version))
|
||||
{
|
||||
bool hasOfficialUrl = !string.IsNullOrWhiteSpace(compatibility.UpdateUrl);
|
||||
bool hasUnofficialUrl = !string.IsNullOrWhiteSpace(compatibility.UnofficialUpdateUrl);
|
||||
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 warning = $"Skipped {compatibility.Name} because {reasonPhrase}. Please check for a version newer than {compatibility.UpperVersion} here:";
|
||||
if (hasOfficialUrl)
|
||||
warning += !hasUnofficialUrl ? $" {compatibility.UpdateUrl}" : $"{Environment.NewLine}- official mod: {compatibility.UpdateUrl}";
|
||||
if (hasUnofficialUrl)
|
||||
warning += $"{Environment.NewLine}- unofficial update: {compatibility.UnofficialUpdateUrl}";
|
||||
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:";
|
||||
if (hasOfficialUrl)
|
||||
warning += !hasUnofficialUrl ? $" {compatibility.UpdateUrl}" : $"{Environment.NewLine}- official mod: {compatibility.UpdateUrl}";
|
||||
if (hasUnofficialUrl)
|
||||
warning += $"{Environment.NewLine}- unofficial update: {compatibility.UnofficialUpdateUrl}";
|
||||
|
||||
this.Monitor.Log(warning, LogLevel.Error);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
this.Monitor.Log(warning, LogLevel.Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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>
|
||||
/// <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>
|
||||
public int CompareTo(ISemanticVersion other)
|
||||
{
|
||||
if(other == null)
|
||||
throw new ArgumentNullException(nameof(other));
|
||||
|
||||
const int same = 0;
|
||||
const int curNewer = 1;
|
||||
const int curOlder = -1;
|
||||
|
|
Loading…
Reference in New Issue