Skip to content
This repository has been archived by the owner on Apr 20, 2022. It is now read-only.

Plugin Development

Alex Rønne Petersen edited this page Jul 4, 2019 · 8 revisions

Plugins are an alternative to script packages for extending Alkahest. A plugin is a compiled .NET assembly. There are pros and cons to using plugins instead of scripting.

Pros:

  • You can use any .NET programming language (C#, F#, etc).
  • Compilation is done ahead of time, making startup time faster.
  • Compiler diagnostics are available before running Alkahest.
  • You have full control over compiler options.
  • Arbitrary third-party .NET assemblies can be referenced (e.g. via NuGet).
  • Native compilation (e.g. Ngen.exe) is a possibility.

Cons:

  • The Alkahest package registry does not support distribution of plugins.
  • Users will not be able to easily see or modify the source code.
  • Sharing code between plugins is more difficult than with scripting.

In general, it is recommended to use scripting wherever possible.

This is a quick guide to getting started with plugin development in C#, using an example plugin called example.

Conventions

  • GitHub repository name: alkahest-example
  • Project name and namespace: Alkahest.Plugins.Example
  • Assembly name: alkahest-example.dll
  • Plugin class name: ExamplePlugin
  • Alkahest.Core.Plugins.IPlugin.Name property: "example"

Setup

  1. Create a C# class library project targeting .NET Framework 4.7.2 called Alkahest.Plugins.Example.
  2. Go to the project's properties and set the assembly name to alkahest-example.
  3. Add a reference to the Alkahest.Core NuGet package.
  4. Create an ExamplePlugin.cs file in your project.

Basic Structure

Your ExamplePlugin.cs file should look like this:

using Alkahest.Core.Logging;
using Alkahest.Core.Plugins;

namespace Alkahest.Plugins.Example
{
    public sealed class ExamplePlugin : IPlugin
    {
        public string Name => "example";

        static readonly Log _log = new Log(typeof(ExamplePlugin));

        readonly PluginContext _context;

        ExamplePlugin(PluginContext context)
        {
            _context = context;
        }

        public void Start()
        {
            _log.Basic("Example plugin started");
        }

        public void Stop()
        {
            _log.Basic("Example plugin stopped");
        }
    }
}

You do not need to register your plugin class anywhere; simply implementing Alkahest.Core.Plugins.IPlugin and adding a constructor taking an Alkahest.Core.Plugins.PluginContext parameter is enough for Alkahest to find and instantiate your plugin class. The context parameter provides functionality such as packet handling, data center access, and a list of server proxy (Alkahest.Core.Net.Game.GameProxy) objects, each corresponding to an official server. For example, on EU, you would get 4 objects - one for each of Killian, Mystel, Seren, and Yurian.

Start is invoked when the proxy server is starting. This is where a plugin should do its startup work; do not perform significant work in the constructor as a plugin will be instantiated even if it is disabled.

Stop is invoked when the proxy server is stopping. Here, a plugin should clean up any resources it acquired in Start.

The _log field is used for logging rather than sending messages directly to the console or a file. These objects should be instantiated on a per-class basis, not per-object, and so should be private static readonly.

Workflow

After compiling the plugin, copy alkahest-example.dll into the Plugins sub-directory in your Alkahest directory. Start Alkahest and your plugin should be loaded.

Debugging

Unlike in script packages, exceptions that occur during startup/shutdown of a plugin will not be caught by Alkahest; instead, they will cause the whole proxy server to terminate. This is intentional: Plugins are held to a higher standard of correctness than script packages. Exceptions that occur in packet handlers are treated the same as in script packages, however.

To debug a plugin, simply attach a debugger (e.g. Visual Studio) to the Alkahest process. When Alkahest detects the presence of a debugger, it will let all exceptions bubble up so the debugger can catch them and suspend the process. You can also set breakpoints in your plugin's code, or insert explicit calls to System.Diagnostics.Debugger.Break(), in order to break into the debugger.

Clone this wiki locally