From 0e43041777d68b96f110fa38ad7424b855db761a Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 12 Dec 2017 01:00:32 -0500 Subject: [PATCH] add support for casting mod-provided API to an interface without a direct assembly reference (#409) --- build/common.targets | 1 + build/prepare-install-package.targets | 2 ++ .../Framework/ModHelpers/ModRegistryHelper.cs | 24 +++++++++++++++++++ src/SMAPI/IModRegistry.cs | 5 ++++ src/SMAPI/StardewModdingAPI.csproj | 3 +++ src/SMAPI/packages.config | 1 + 6 files changed, 36 insertions(+) diff --git a/build/common.targets b/build/common.targets index aa11344e..15c935e3 100644 --- a/build/common.targets +++ b/build/common.targets @@ -86,6 +86,7 @@ + diff --git a/build/prepare-install-package.targets b/build/prepare-install-package.targets index f2a2b23c..e88ca273 100644 --- a/build/prepare-install-package.targets +++ b/build/prepare-install-package.targets @@ -22,6 +22,7 @@ + @@ -36,6 +37,7 @@ + diff --git a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs index 827c77d5..68201d9a 100644 --- a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using ImpromptuInterface; namespace StardewModdingAPI.Framework.ModHelpers { @@ -62,5 +63,28 @@ namespace StardewModdingAPI.Framework.ModHelpers this.Monitor.Log($"Accessed mod-provided API for {mod.DisplayName}.", LogLevel.Trace); return mod?.Api; } + + /// 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 null. + /// The interface which matches the properties and methods you intend to access. + /// The mod's unique ID. + public TInterface GetApi(string uniqueID) where TInterface : class + { + // validate + if (!typeof(TInterface).IsInterface) + { + this.Monitor.Log("Tried to map a mod-provided API into a class; must be an interface."); + 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 api.ActLike(); + } } } diff --git a/src/SMAPI/IModRegistry.cs b/src/SMAPI/IModRegistry.cs index f84cfcfb..a06e099e 100644 --- a/src/SMAPI/IModRegistry.cs +++ b/src/SMAPI/IModRegistry.cs @@ -20,5 +20,10 @@ namespace StardewModdingAPI /// Get the API provided by a mod, or null if it has none. This signature requires using the API to access the API's properties and methods. /// The mod's unique ID. object GetApi(string uniqueID); + + /// 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 null. + /// The interface which matches the properties and methods you intend to access. + /// The mod's unique ID. + TInterface GetApi(string uniqueID) where TInterface : class; } } diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj index 0db94843..c585a0c4 100644 --- a/src/SMAPI/StardewModdingAPI.csproj +++ b/src/SMAPI/StardewModdingAPI.csproj @@ -53,6 +53,9 @@ icon.ico + + ..\packages\ImpromptuInterface.6.2.2\lib\net40\ImpromptuInterface.dll + ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll True diff --git a/src/SMAPI/packages.config b/src/SMAPI/packages.config index 98d742c7..60be6881 100644 --- a/src/SMAPI/packages.config +++ b/src/SMAPI/packages.config @@ -1,5 +1,6 @@  + \ No newline at end of file