summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2017-12-12 01:00:32 -0500
committerJesse Plamondon-Willard <github@jplamondonw.com>2017-12-12 01:00:32 -0500
commit0e43041777d68b96f110fa38ad7424b855db761a (patch)
treef80a166ef3eb0abc0671dff1ba70593479178d55
parentd04cacbdd0729140e4d8e93323ba66ee90ff9d2a (diff)
downloadSMAPI-0e43041777d68b96f110fa38ad7424b855db761a.tar.gz
SMAPI-0e43041777d68b96f110fa38ad7424b855db761a.tar.bz2
SMAPI-0e43041777d68b96f110fa38ad7424b855db761a.zip
add support for casting mod-provided API to an interface without a direct assembly reference (#409)
-rw-r--r--build/common.targets1
-rw-r--r--build/prepare-install-package.targets2
-rw-r--r--src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs24
-rw-r--r--src/SMAPI/IModRegistry.cs5
-rw-r--r--src/SMAPI/StardewModdingAPI.csproj3
-rw-r--r--src/SMAPI/packages.config1
6 files changed, 36 insertions, 0 deletions
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 @@
<Copy SourceFiles="$(TargetDir)\StardewModdingAPI.AssemblyRewriters.dll" DestinationFolder="$(GamePath)" />
<Copy SourceFiles="$(TargetDir)\$(TargetName).pdb" DestinationFolder="$(GamePath)" />
<Copy SourceFiles="$(TargetDir)\$(TargetName).xml" DestinationFolder="$(GamePath)" />
+ <Copy SourceFiles="$(TargetDir)\ImpromptuInterface.dll" DestinationFolder="$(GamePath)" />
<Copy SourceFiles="$(TargetDir)\Newtonsoft.Json.dll" DestinationFolder="$(GamePath)" />
<Copy SourceFiles="$(TargetDir)\Mono.Cecil.dll" DestinationFolder="$(GamePath)" />
</Target>
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 @@
<Copy SourceFiles="$(TargetDir)\readme.txt" DestinationFiles="$(PackagePath)\README.txt" />
<!-- copy SMAPI files for Mono -->
+ <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\ImpromptuInterface.dll" DestinationFolder="$(PackageInternalPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Mono.Cecil.dll" DestinationFolder="$(PackageInternalPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Newtonsoft.Json.dll" DestinationFolder="$(PackageInternalPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.exe" DestinationFolder="$(PackageInternalPath)\Mono" />
@@ -36,6 +37,7 @@
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="@(CompiledMods)" DestinationFolder="$(PackageInternalPath)\Mono\Mods\%(RecursiveDir)" />
<!-- copy SMAPI files for Windows -->
+ <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\ImpromptuInterface.dll" DestinationFolder="$(PackageInternalPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Mono.Cecil.dll" DestinationFolder="$(PackageInternalPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Newtonsoft.Json.dll" DestinationFolder="$(PackageInternalPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.exe" DestinationFolder="$(PackageInternalPath)\Windows" />
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;
}
+
+ /// <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 (!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<TInterface>();
+ }
}
}
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
/// <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>
/// <param name="uniqueID">The mod's unique ID.</param>
object GetApi(string uniqueID);
+
+ /// <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>
+ TInterface GetApi<TInterface>(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 @@
<ApplicationIcon>icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="ImpromptuInterface, Version=6.2.2.0, Culture=neutral, PublicKeyToken=0b1781c923b2975b, processorArchitecture=MSIL">
+ <HintPath>..\packages\ImpromptuInterface.6.2.2\lib\net40\ImpromptuInterface.dll</HintPath>
+ </Reference>
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
<Private>True</Private>
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 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
+ <package id="ImpromptuInterface" version="6.2.2" targetFramework="net45" />
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net45" />
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net45" />
</packages> \ No newline at end of file