summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/ModHelpers
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Framework/ModHelpers')
-rw-r--r--src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs67
1 files changed, 62 insertions, 5 deletions
diff --git a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs
index 9e824694..ea0dbb38 100644
--- a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs
+++ b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs
@@ -1,4 +1,6 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
+using System.Linq;
+using StardewModdingAPI.Framework.Reflection;
namespace StardewModdingAPI.Framework.ModHelpers
{
@@ -11,6 +13,15 @@ namespace StardewModdingAPI.Framework.ModHelpers
/// <summary>The underlying mod registry.</summary>
private readonly ModRegistry Registry;
+ /// <summary>Encapsulates monitoring and logging for the mod.</summary>
+ private readonly IMonitor Monitor;
+
+ /// <summary>The mod IDs for APIs accessed by this instanced.</summary>
+ private readonly HashSet<string> AccessedModApis = new HashSet<string>();
+
+ /// <summary>Generates proxy classes to access mod APIs through an arbitrary interface.</summary>
+ private readonly InterfaceProxyBuilder ProxyBuilder;
+
/*********
** Public methods
@@ -18,16 +29,20 @@ namespace StardewModdingAPI.Framework.ModHelpers
/// <summary>Construct an instance.</summary>
/// <param name="modID">The unique ID of the relevant mod.</param>
/// <param name="registry">The underlying mod registry.</param>
- public ModRegistryHelper(string modID, ModRegistry registry)
+ /// <param name="proxyBuilder">Generates proxy classes to access mod APIs through an arbitrary interface.</param>
+ /// <param name="monitor">Encapsulates monitoring and logging for the mod.</param>
+ public ModRegistryHelper(string modID, ModRegistry registry, InterfaceProxyBuilder proxyBuilder, IMonitor monitor)
: base(modID)
{
this.Registry = registry;
+ this.ProxyBuilder = proxyBuilder;
+ this.Monitor = monitor;
}
/// <summary>Get metadata for all loaded mods.</summary>
public IEnumerable<IManifest> GetAll()
{
- return this.Registry.GetAll();
+ return this.Registry.GetAll().Select(p => p.Manifest);
}
/// <summary>Get metadata for a loaded mod.</summary>
@@ -35,14 +50,56 @@ namespace StardewModdingAPI.Framework.ModHelpers
/// <returns>Returns the matching mod's metadata, or <c>null</c> if not found.</returns>
public IManifest Get(string uniqueID)
{
- return this.Registry.Get(uniqueID);
+ return this.Registry.Get(uniqueID)?.Manifest;
}
/// <summary>Get whether a mod has been loaded.</summary>
/// <param name="uniqueID">The mod's unique ID.</param>
public bool IsLoaded(string uniqueID)
{
- return this.Registry.IsLoaded(uniqueID);
+ return this.Registry.Get(uniqueID) != null;
+ }
+
+ /// <summary>Get the API provided by a mod, or <c>null</c> if it has none. This signature requires using the <see cref="IModHelper.Reflection"/> API to access the API's properties and methods.</summary>
+ public object GetApi(string uniqueID)
+ {
+ IModMetadata mod = this.Registry.Get(uniqueID);
+ if (mod?.Api != null && this.AccessedModApis.Add(mod.Manifest.UniqueID))
+ this.Monitor.Log($"Accessed mod-provided API for {mod.DisplayName}.", LogLevel.Trace);
+ return mod?.Api;
+ }
+
+ /// <summary>Get the API provided by a mod, mapped to a given interface which specifies the expected properties and methods. If the mod has no API or it's not compatible with the given interface, get <c>null</c>.</summary>
+ /// <typeparam name="TInterface">The interface which matches the properties and methods you intend to access.</typeparam>
+ /// <param name="uniqueID">The mod's unique ID.</param>
+ public TInterface GetApi<TInterface>(string uniqueID) where TInterface : class
+ {
+ // validate
+ if (!this.Registry.AreAllModsInitialised)
+ {
+ this.Monitor.Log("Tried to access a mod-provided API before all mods were initialised.", LogLevel.Error);
+ return null;
+ }
+ if (!typeof(TInterface).IsInterface)
+ {
+ this.Monitor.Log("Tried to map a mod-provided API to a class; must be a public interface.", LogLevel.Error);
+ return null;
+ }
+ if (!typeof(TInterface).IsPublic)
+ {
+ this.Monitor.Log("Tried to map a mod-provided API to a non-public interface; must be a public interface.", LogLevel.Error);
+ return null;
+ }
+
+ // get raw API
+ object api = this.GetApi(uniqueID);
+ if (api == null)
+ return null;
+
+ // get API of type
+ if (api is TInterface castApi)
+ return castApi;
+ return this.ProxyBuilder.CreateProxy<TInterface>(api, this.ModID, uniqueID);
}
}
}