Plugin Dependencies

As of 1.21.0, Openplanet plugins can depend on other plugins. For a plugin that depends on another plugin to run, both plugins need to be installed. For example, if plugin A depends on plugin B, then both A and B need to be installed for A to successfully load.

Plugins that depend on other plugins will also inherit a part of the implementation of those plugins. To be more precise, a dependent plugin will import a dependency's exports. These exported functions (and optionally shared classes) can then be used by any dependent plugins to perform actions within the context of the other plugin.

For example, the built-in NadeoServices plugin allows dependent plugins to use the same access tokens for Nadeo's live services. When multiple plugins are depending on NadeoServices, only 1 access token will be created inside of the NadeoServices plugin itself, which the dependent plugins are then making use of. This saves resources, simplifies development because you don't have to worry about authentication, and avoids any potential rate limiting or other conflicts.

Depending on a plugin

If you're a developer and you wish to depend on another plugin, you have to add the plugin dependency to your info.toml file. For example, if you are integrating with the NadeoServices plugin, you would add a dependencies array to your [script] section:

dependencies = [ "NadeoServices" ]

When your plugin loads, from NadeoServices is compiled into your plugin as well. This file contains functions that interact with the plugin. It's recommended you check the actual source of this file, as it often contains documentation on how to use a plugin's exported scripts.

For the NadeoServices dependency example, you'd then simply call any of the exported functions:

void Main()
  // ...

Exporting to other plugins

If you want other plugin developers to be able to have a dependency on your plugin, you have to export script files. There's 2 ways to do this inside of info.toml. The first is exports, and the second is shared_exports.

  • exports is an array of files in your plugin that will be compiled into any dependent plugins, but NOT in the dependency plugin.
  • shared_exports is like exports, except it will be compiled into both plugins.

Shared exports are usually only useful if you want to provide classes using Angelscript's shared entities.

exports = [ "src/" ]
shared_exports = [ "src/" ]

Exporting functions

Function exports are using Angelscript's function importing to create a connection between multiple script modules.

This works by exporting a file containing your function definition using the import .. from ".."; syntax. For example, if your plugin ID is Foo, you could write the following exported script:

namespace Foo
  import void DoSomething() from "Foo";

Note that the exported script is not compiled with your plugin, so you have to declare the actual function in a separate file:

namespace Foo
  void DoSomething()
    print("Hello, world!");

If you've worked with header files in C or C++ before, this concept should be familiar. When you change the function signature, make sure you change it in both files!

Exporting classes and other entities

If you want to export a class (via an exported function's return value or parameter for example), you have 2 ways of doing it.

  • Add the class to a regular exported script. The downside about this is that you can't use the same class in your own code since exported scripts are not compiled into the dependency plugin.
  • Make the class shared and put it in a shared exported script. This way you can use (and pass around handles to) the class.

To make a class shared, you can simply add the shared keyword as described in Angelscript's shared entities page. Keep the following important rule in mind though:

Shared entities have a restriction in that they cannot access non-shared entities because the non-shared entities are exclusive to the script module in which they were compiled.

If you feel like breaking this restriction, consider whether a class really needs to be exported. It's likely you can solve the problem without any shared entities, purely with exported functions.

Required and optional dependencies

By default, the dependencies you list in dependencies are required dependencies. That means that your plugin won't compile if any of the dependencies are not installed, and will throw an error at the user.

As of Openplanet 1.22.2, you can also specifiy optional dependencies by using optional_dependencies. This is an additional array of plugin ID's to optionally depend on. If such a plugin is not installed, then your plugin will still compile, but without any of the exported files.

If an optional dependency is installed however, it will add a preprocessor definition that you can use in your scripts. The definition will have a prefix of DEPENDENCY_ followed by the plugin ID in uppercase, with spaces replaced by underscores. For example, if you have an optional dependency on Dashboard and Dashboard is installed, you can check for DEPENDENCY_DASHBOARD in your scripts:

  auto playerState = Dashboard::ViewingPlayerState();
  // ...
  warn("Dashboard is not installed!");

Page updated 7 months ago by Miss