summaryrefslogtreecommitdiff
path: root/src/StardewModdingAPI/Framework
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2016-12-27 13:52:32 -0500
committerJesse Plamondon-Willard <github@jplamondonw.com>2016-12-27 13:52:32 -0500
commitb9dd6eb742e4f0c42ed887abd0f17f113f250056 (patch)
tree352a208a25780285419b0bae73148a00a98356ff /src/StardewModdingAPI/Framework
parentc24294c3dd73db3754d10ff8fe5bd51338555638 (diff)
parentb75d86e7cc19f9bc961abb475f22e8f2b059533c (diff)
downloadSMAPI-b9dd6eb742e4f0c42ed887abd0f17f113f250056.tar.gz
SMAPI-b9dd6eb742e4f0c42ed887abd0f17f113f250056.tar.bz2
SMAPI-b9dd6eb742e4f0c42ed887abd0f17f113f250056.zip
Merge branch 'develop' into stable
Diffstat (limited to 'src/StardewModdingAPI/Framework')
-rw-r--r--src/StardewModdingAPI/Framework/AssemblyRewriting/CacheEntry.cs2
-rw-r--r--src/StardewModdingAPI/Framework/ModAssemblyLoader.cs4
-rw-r--r--src/StardewModdingAPI/Framework/ModRegistry.cs18
-rw-r--r--src/StardewModdingAPI/Framework/Models/GitRelease.cs (renamed from src/StardewModdingAPI/Framework/GitRelease.cs)2
-rw-r--r--src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs47
-rw-r--r--src/StardewModdingAPI/Framework/Models/UserSettings.cs15
-rw-r--r--src/StardewModdingAPI/Framework/Reflection/CacheEntry.cs30
-rw-r--r--src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs34
-rw-r--r--src/StardewModdingAPI/Framework/UpdateHelper.cs1
-rw-r--r--src/StardewModdingAPI/Framework/UserSettings.cs9
10 files changed, 138 insertions, 24 deletions
diff --git a/src/StardewModdingAPI/Framework/AssemblyRewriting/CacheEntry.cs b/src/StardewModdingAPI/Framework/AssemblyRewriting/CacheEntry.cs
index 3dfbc78c..a747eaa8 100644
--- a/src/StardewModdingAPI/Framework/AssemblyRewriting/CacheEntry.cs
+++ b/src/StardewModdingAPI/Framework/AssemblyRewriting/CacheEntry.cs
@@ -36,7 +36,7 @@ namespace StardewModdingAPI.Framework.AssemblyRewriting
/// <param name="paths">The paths for the cached assembly.</param>
/// <param name="hash">The MD5 hash of the original assembly.</param>
/// <param name="currentVersion">The current SMAPI version.</param>
- public bool IsUpToDate(CachePaths paths, string hash, Version currentVersion)
+ public bool IsUpToDate(CachePaths paths, string hash, ISemanticVersion currentVersion)
{
return hash == this.Hash
&& this.ApiVersion == currentVersion.ToString()
diff --git a/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs b/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs
index 1ceb8ad2..a2c4ac23 100644
--- a/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs
+++ b/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs
@@ -58,7 +58,7 @@ namespace StardewModdingAPI.Framework
CachePaths cachePaths = this.GetCachePaths(assemblyPath);
{
CacheEntry cacheEntry = File.Exists(cachePaths.Metadata) ? JsonConvert.DeserializeObject<CacheEntry>(File.ReadAllText(cachePaths.Metadata)) : null;
- if (cacheEntry != null && cacheEntry.IsUpToDate(cachePaths, hash, Constants.Version))
+ if (cacheEntry != null && cacheEntry.IsUpToDate(cachePaths, hash, Constants.ApiVersion))
return new RewriteResult(assemblyPath, cachePaths, assemblyBytes, cacheEntry.Hash, cacheEntry.UseCachedAssembly, isNewerThanCache: false); // no rewrite needed
}
this.Monitor.Log($"Preprocessing {Path.GetFileName(assemblyPath)} for compatibility...", LogLevel.Trace);
@@ -99,7 +99,7 @@ namespace StardewModdingAPI.Framework
// cache all results
foreach (RewriteResult result in results)
{
- CacheEntry cacheEntry = new CacheEntry(result.Hash, Constants.Version.ToString(), forceCacheAssemblies || result.UseCachedAssembly);
+ CacheEntry cacheEntry = new CacheEntry(result.Hash, Constants.ApiVersion.ToString(), forceCacheAssemblies || result.UseCachedAssembly);
File.WriteAllText(result.CachePaths.Metadata, JsonConvert.SerializeObject(cacheEntry));
if (forceCacheAssemblies || result.UseCachedAssembly)
File.WriteAllBytes(result.CachePaths.Assembly, result.AssemblyBytes);
diff --git a/src/StardewModdingAPI/Framework/ModRegistry.cs b/src/StardewModdingAPI/Framework/ModRegistry.cs
index ba56a447..b593142d 100644
--- a/src/StardewModdingAPI/Framework/ModRegistry.cs
+++ b/src/StardewModdingAPI/Framework/ModRegistry.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Linq;
using System.Reflection;
namespace StardewModdingAPI.Framework
@@ -11,6 +12,9 @@ namespace StardewModdingAPI.Framework
/*********
** Properties
*********/
+ /// <summary>The registered mod data.</summary>
+ private readonly List<IMod> Mods = new List<IMod>();
+
/// <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>();
@@ -19,11 +23,17 @@ namespace StardewModdingAPI.Framework
** Public methods
*********/
/// <summary>Register a mod as a possible source of deprecation warnings.</summary>
- /// <param name="manifest">The mod manifest.</param>
- /// <param name="assembly">The mod assembly.</param>
- public void Add(Manifest manifest, Assembly assembly)
+ /// <param name="mod">The mod instance.</param>
+ public void Add(IMod mod)
+ {
+ this.Mods.Add(mod);
+ this.ModNamesByAssembly[mod.GetType().Assembly.FullName] = mod.ModManifest.Name;
+ }
+
+ /// <summary>Get all enabled mods.</summary>
+ public IEnumerable<IMod> GetMods()
{
- this.ModNamesByAssembly[assembly.FullName] = manifest.Name;
+ return (from mod in this.Mods select mod);
}
/// <summary>Get the friendly name for the closest assembly registered as a source of deprecation warnings.</summary>
diff --git a/src/StardewModdingAPI/Framework/GitRelease.cs b/src/StardewModdingAPI/Framework/Models/GitRelease.cs
index 0da57efd..bc53468f 100644
--- a/src/StardewModdingAPI/Framework/GitRelease.cs
+++ b/src/StardewModdingAPI/Framework/Models/GitRelease.cs
@@ -1,6 +1,6 @@
using Newtonsoft.Json;
-namespace StardewModdingAPI.Framework
+namespace StardewModdingAPI.Framework.Models
{
/// <summary>Metadata about a GitHub release tag.</summary>
internal class GitRelease
diff --git a/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs b/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs
new file mode 100644
index 00000000..9bf06552
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs
@@ -0,0 +1,47 @@
+using System.Text.RegularExpressions;
+
+namespace StardewModdingAPI.Framework.Models
+{
+ /// <summary>Contains abstract metadata about an incompatible mod.</summary>
+ internal class IncompatibleMod
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The unique mod ID.</summary>
+ public string ID { get; set; }
+
+ /// <summary>The mod name.</summary>
+ public string Name { get; set; }
+
+ /// <summary>The most recent incompatible mod version.</summary>
+ public string Version { get; set; }
+
+ /// <summary>The URL the user can check for an official updated version.</summary>
+ public string UpdateUrl { get; set; }
+
+ /// <summary>The URL the user can check for an unofficial updated version.</summary>
+ public string UnofficialUpdateUrl { get; set; }
+
+ /// <summary>A regular expression matching version strings to consider compatible, even if they technically precede <see cref="Version"/>.</summary>
+ public string ForceCompatibleVersion { get; set; }
+
+
+ /*********
+ ** Public 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)
+ {
+ ISemanticVersion incompatibleVersion = new SemanticVersion(this.Version);
+
+ // allow newer versions
+ if (version.IsNewerThan(incompatibleVersion))
+ return true;
+
+ // allow versions matching override
+ return !string.IsNullOrWhiteSpace(this.ForceCompatibleVersion) && Regex.IsMatch(version.ToString(), this.ForceCompatibleVersion, RegexOptions.IgnoreCase);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/StardewModdingAPI/Framework/Models/UserSettings.cs b/src/StardewModdingAPI/Framework/Models/UserSettings.cs
new file mode 100644
index 00000000..a0074f77
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/Models/UserSettings.cs
@@ -0,0 +1,15 @@
+namespace StardewModdingAPI.Framework.Models
+{
+ /// <summary>Contains user settings from SMAPI's JSON configuration file.</summary>
+ internal class UserSettings
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>Whether to enable development features.</summary>
+ public bool DeveloperMode { get; set; }
+
+ /// <summary>Whether to check if a newer version of SMAPI is available on startup.</summary>
+ public bool CheckForUpdates { get; set; } = true;
+ }
+}
diff --git a/src/StardewModdingAPI/Framework/Reflection/CacheEntry.cs b/src/StardewModdingAPI/Framework/Reflection/CacheEntry.cs
new file mode 100644
index 00000000..30faca37
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/Reflection/CacheEntry.cs
@@ -0,0 +1,30 @@
+using System.Reflection;
+
+namespace StardewModdingAPI.Framework.Reflection
+{
+ /// <summary>A cached member reflection result.</summary>
+ internal struct CacheEntry
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>Whether the lookup found a valid match.</summary>
+ public bool IsValid;
+
+ /// <summary>The reflection data for this member (or <c>null</c> if invalid).</summary>
+ public MemberInfo MemberInfo;
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="isValid">Whether the lookup found a valid match.</param>
+ /// <param name="memberInfo">The reflection data for this member (or <c>null</c> if invalid).</param>
+ public CacheEntry(bool isValid, MemberInfo memberInfo)
+ {
+ this.IsValid = isValid;
+ this.MemberInfo = memberInfo;
+ }
+ }
+}
diff --git a/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs b/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs
index 38b4e357..edf59b81 100644
--- a/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs
+++ b/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs
@@ -67,10 +67,17 @@ namespace StardewModdingAPI.Framework.Reflection
/// <param name="obj">The object which has the field.</param>
/// <param name="name">The field name.</param>
/// <param name="required">Whether to throw an exception if the private field is not found.</param>
- /// <remarks>This is a shortcut for <see cref="GetPrivateField{TValue}(object,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.</remarks>
+ /// <returns>Returns the field value, or the default value for <typeparamref name="TValue"/> if the field wasn't found and <paramref name="required"/> is false.</returns>
+ /// <remarks>
+ /// This is a shortcut for <see cref="GetPrivateField{TValue}(object,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.
+ /// When <paramref name="required" /> is false, this will return the default value if reflection fails. If you need to check whether the field exists, use <see cref="GetPrivateField{TValue}(object,string,bool)" /> instead.
+ /// </remarks>
public TValue GetPrivateValue<TValue>(object obj, string name, bool required = true)
{
- return this.GetPrivateField<TValue>(obj, name, required).GetValue();
+ IPrivateField<TValue> field = this.GetPrivateField<TValue>(obj, name, required);
+ return field != null
+ ? field.GetValue()
+ : default(TValue);
}
/// <summary>Get the value of a private static field.</summary>
@@ -78,10 +85,17 @@ namespace StardewModdingAPI.Framework.Reflection
/// <param name="type">The type which has the field.</param>
/// <param name="name">The field name.</param>
/// <param name="required">Whether to throw an exception if the private field is not found.</param>
- /// <remarks>This is a shortcut for <see cref="GetPrivateField{TValue}(Type,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.</remarks>
+ /// <returns>Returns the field value, or the default value for <typeparamref name="TValue"/> if the field wasn't found and <paramref name="required"/> is false.</returns>
+ /// <remarks>
+ /// This is a shortcut for <see cref="GetPrivateField{TValue}(Type,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.
+ /// When <paramref name="required" /> is false, this will return the default value if reflection fails. If you need to check whether the field exists, use <see cref="GetPrivateField{TValue}(Type,string,bool)" /> instead.
+ /// </remarks>
public TValue GetPrivateValue<TValue>(Type type, string name, bool required = true)
{
- return this.GetPrivateField<TValue>(type, name, required).GetValue();
+ IPrivateField<TValue> field = this.GetPrivateField<TValue>(type, name, required);
+ return field != null
+ ? field.GetValue()
+ : default(TValue);
}
/****
@@ -228,12 +242,18 @@ namespace StardewModdingAPI.Framework.Reflection
{
// get from cache
if (this.Cache.Contains(key))
- return (TMemberInfo)this.Cache[key];
+ {
+ CacheEntry entry = (CacheEntry)this.Cache[key];
+ return entry.IsValid
+ ? (TMemberInfo)entry.MemberInfo
+ : default(TMemberInfo);
+ }
// fetch & cache new value
TMemberInfo result = fetch();
- this.Cache.Add(key, result, new CacheItemPolicy { SlidingExpiration = this.SlidingCacheExpiry });
+ CacheEntry cacheEntry = new CacheEntry(result != null, result);
+ this.Cache.Add(key, cacheEntry, new CacheItemPolicy { SlidingExpiration = this.SlidingCacheExpiry });
return result;
}
}
-} \ No newline at end of file
+}
diff --git a/src/StardewModdingAPI/Framework/UpdateHelper.cs b/src/StardewModdingAPI/Framework/UpdateHelper.cs
index ddd1d840..e01e55c8 100644
--- a/src/StardewModdingAPI/Framework/UpdateHelper.cs
+++ b/src/StardewModdingAPI/Framework/UpdateHelper.cs
@@ -3,6 +3,7 @@ using System.Net;
using System.Reflection;
using System.Threading.Tasks;
using Newtonsoft.Json;
+using StardewModdingAPI.Framework.Models;
namespace StardewModdingAPI.Framework
{
diff --git a/src/StardewModdingAPI/Framework/UserSettings.cs b/src/StardewModdingAPI/Framework/UserSettings.cs
deleted file mode 100644
index 199d19b3..00000000
--- a/src/StardewModdingAPI/Framework/UserSettings.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace StardewModdingAPI.Framework
-{
- /// <summary>Contains user settings from SMAPI's JSON configuration file.</summary>
- internal class UserSettings
- {
- /// <summary>Whether to enable development features.</summary>
- public bool DeveloperMode { get; set; }
- }
-}