Changes

Line 227: Line 227:  
</dd>
 
</dd>
 
</dl>
 
</dl>
  −
==Mod-provided APIs==
  −
Mods can provide their own APIs to other mods, even without a dependency or assembly reference. This can be used to integrate mods, provide custom information, or provide new framework APIs beyond those offered by SMAPI itself.
  −
  −
===Providing an API===
  −
To provide an API for other mods to use:
  −
<ol>
  −
<li>Add a normal class to your mod project with the methods and properties you want to expose.
  −
<source lang="c#">
  −
public class YourModApi
  −
{
  −
    public string ExampleProperty { get; set; } = "Example value";
  −
  −
    public bool GetThing(string example)
  −
    {
  −
      return true;
  −
    }
  −
}
  −
</source>
  −
(You can use a [https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/constructors constructor] to initialise the API if desired.)</li>
  −
<li>Override <tt>GetApi</tt> in your mod's entry class and return an instance of your API:
  −
<source lang="c#">
  −
  public override object GetApi()
  −
  {
  −
      return new YourModApi();
  −
  }
  −
</source></li>
  −
</ol>
  −
  −
That's it! SMAPI will get one instance of your API and cache it.
  −
  −
Notes:
  −
* <tt>GetApi</tt> is always called after <tt>Entry</tt>, so it's safe to pass in your mod's initialised fields.
  −
* Be careful when changing your API! If you make a breaking change, other mods may need an update before they can access your API again.
  −
* You can optionally add a public [https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/interface interface] to your API. If a mod directly references your mod DLL, they'll be able to use your interface instead of creating their own.
  −
* '''Known issue:''' SMAPI doesn't currently support non-public API classes.
  −
  −
===Using an API===
  −
You can use a mod-provided API by mapping it to an [https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/interface interface]:
  −
<ol>
  −
<li>Create an interface with only the properties and methods you want to access. (If you directly reference the mod DLL and it provides a public API interface, you can use that instead.)
  −
<source lang="C#">
  −
internal interface ISomeModApi
  −
{
  −
  bool GetThing(string example);
  −
}
  −
</source></li>
  −
<li>In your mod code (after <tt>Entry</tt>), you can get the API by specifying the interface you created in step 1, and the [[#Basic fields|mod's unique ID]]:
  −
<source lang="c#">
  −
ISomeModApi api = helper.ModRegistry.GetApi<ISomeModApi>("other-mod-ID");
  −
if (api != null)
  −
  bool result = api.GetThing("boop");
  −
</source></li>
  −
</ol>
  −
  −
For a quick integration, you can also use reflection instead of creating an interface:
  −
<source lang="c#">
  −
object api = helper.ModRegistry.GetApi("other-mod-id");
  −
if (api != null)
  −
  bool result = helper.Reflection.GetMethod(api, "GetThing").Invoke<bool>("boop");
  −
</source>
  −
  −
Notes:
  −
* You can't call <tt>GetApi</tt> until all mods are initialised and their <tt>Entry</tt> methods called. You can use the <tt>GameEvents.FirstUpdateTick</tt> [[#Events|event]] if you need to access mod APIs early; this is guaranteed to happen after all mods are initialised.
  −
* You should always null-check APIs you consume. <tt>GetApi</tt> will return <tt>null</tt> if the API isn't available (e.g. because the mod isn't already installed or doesn't have one), or if an error occurs fetching the API.
 
translators
8,404

edits