Difference between revisions of "Modding:Modder Guide/APIs/Integrations"

From Stardew Valley Wiki
Jump to navigation Jump to search
(remove footer (no longer needed with new sidebar))
Line 86: Line 86:
 
* You can't call <tt>GetApi</tt> until all mods are initialised and their <tt>Entry</tt> methods called. You can use the <tt>GameLoop.GameLaunched</tt> [[#Events|event]] if you need to access mod APIs early; this is guaranteed to happen after all mods are initialised.
 
* You can't call <tt>GetApi</tt> until all mods are initialised and their <tt>Entry</tt> methods called. You can use the <tt>GameLoop.GameLaunched</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.
 
* 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.
 
{{modding guide footer
 
|prev = [[Modding:Modder Guide/APIs|SMAPI reference]]
 
|next =
 
}}
 

Revision as of 18:03, 13 September 2019

Creating SMAPI mods SMAPI mascot.png


Modding:Index

A mod integration refers to two mods communicating or cooperating in some way. SMAPI provides three distinct features to support this.

Dependencies

You can define dependencies in your manifest.json file, which are other mods that must be loaded before yours. If the dependency is required and missing, SMAPI will show a friendly error to the player. See the manifest page for more info.

Mod registry

Your mod can get information about loaded mods, or check if a particular mod is loaded. (All mods are loaded by the time your mod's Entry(…) method is called.)

// check if a mod is loaded
bool isLoaded = this.Helper.ModRegistry.IsLoaded("UniqueModID");

// get info for a mod
IModInfo mod = this.Helper.ModRegistry.Get("UniqueModID");
bool isContentPack = mod.IsContentPack;
IManifest manifest = mod.Manifest; // name, description, version, etc

// get info for all loaded mods
foreach(IModInfo mod in this.Helper.ModRegistry.GetAll()) {  }

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:

  1. Add a normal class to your mod project with the methods and properties you want to expose.
    public class YourModApi
    {
        public string ExampleProperty { get; set; } = "Example value";
    
        public bool GetThing(string example)
        {
           return true;
        }
    }
    
    (You can use a constructor to initialise the API if desired.)
  2. Override GetApi in your mod's entry class and return an instance of your API:
       public override object GetApi()
       {
          return new YourModApi();
       }
    

That's it! SMAPI will get one instance of your API and cache it.

Notes:

  • GetApi is always called after Entry, 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 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 interface:

  1. 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.)
    public interface ISomeModApi
    {
       bool GetThing(string example);
    }
    
  2. In your mod code (after Entry), you can get the API by specifying the interface you created in step 1, and the mod's unique ID:
    ISomeModApi api = helper.ModRegistry.GetApi<ISomeModApi>("other-mod-ID");
    if (api != null)
       bool result = api.GetThing("boop");
    

For a quick integration, you can also use reflection instead of creating an interface:

object api = helper.ModRegistry.GetApi("other-mod-id");
if (api != null)
   bool result = helper.Reflection.GetMethod(api, "GetThing").Invoke<bool>("boop");

Notes:

  • You can't call GetApi until all mods are initialised and their Entry methods called. You can use the GameLoop.GameLaunched 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. GetApi will return null 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.