Skip to content
Peter edited this page Jul 21, 2016 · 18 revisions

What is a Wurm Assistant Plugin?

Before Wurm Assistant 3.1, all features could only be part of the application itself. It was only possible to clone the repo, modify the source code and compile a special version of Wurm Assistant - or make a pull request and wait for official update.

Since Wurm Assistant 3.1, there is a new option - a dependency injection powered plugin loading system, which will runtime-load any DLL's from folders under:

Data Directory\Plugins\*\*.dll

This enables you to share your plugin, without having to ever request a pull on the master github repository, or mess around with the existing codebase.

Following guide will show you, how to create such a plugin and how to cleanly leverage some handy services provided by the core Wurm Assistant.

Getting started

Assuming you have already obtained Visual Studio, cloned the repository, successfully built and launched the app from the source code (if not, see the main readme.md).

Easiest way is by example. There is a sample plugin available within the source, at src\Apps\WurmAssistant\WurmAssistant3.Areas.SamplePlugin

  1. Build the plugin and then navigate to the bin folder, where the DLL and other files have been produced.
  2. Copy these files to the plugins folder at Wurm Assistant Data Directory, remember to put them into a nested folder called for example SamplePlugin.
  3. Launch WurmAssistant3 project.
  4. You should see a smiling and working sample plugin button in the toolbox.

New plugin, step by step

Create a code library for your plugin

Your first step should be creation of a new C# Code Library. You don't need to follow any special convention to make it work, except to put it under src\Apps\WurmAssistant\YourAreaName. Also try to give this assembly some unique name and default namespace, to avoid potential conflicts.

Reference WurmAssistant3.Contracts

WurmAssistant3.Contracts contains the types intended to be used across plugins, this includes essential interfaces, various utilities and api's of the core features, if available.

Create your feature

The core of a plugin is a public class, which inherits IFeature (AldursLab.WurmAssistant3.Areas.Features.Contracts) and is decorated by the KernelBindAttribute. Kernel is able to find such classes in the assemblies. Afterwards, it creates a single instance of this class and "plugs" it into the toolbox as button.

Create such class and implement IFeature.

The IFeature has 5 simple members:

Show() - called when toolbox button is pressed. Hide() - not used at the moment, reserved for future as a contract to hide the feature GUIs (eg. minimize). Name - will be used as the tooltip of the button. Icon - will be used as an icon of the button. InitAsync() - this special method is called right after feature is plugged into toolbox. It can be used to "start" your feature asynchronously, without blocking the rest of Wurm Assistant. You can of course ignore this method (Just return a Task.FromResult(true)) and use your own preferred logic, eg. a timer.

Additionally, if you'd like your plugin to do some cleanup on Wurm Assistant closing, simply implement IDisposable. Dispose() will be called for you, in a smart way.

You can have multiple features within one plugin.

Build your feature the way you see fit!

IFeature implementation is minimalistically everything you need from Wurm Assistant to run your plugin! You can use your preferred patterns and libraries to construct whatever you like!

However, Wurm Assistant comes with a few very useful tools to make your life much easier. Consider trying them!

Debugging

Nothing non-trivial can be made without debugging. Fortunately debugging a plugin it rather easy, just add a temporary reference to your plugin library from WurmAssistant project itself. By building and starting WurmAssistant, your plugin will load automatically.

However, remember to remove this reference before packaging final version of your plugin and then test the plugin from Plugins directory, to ensure all DLL's load correctly.

Avoiding some major headaches

  • Be sure to use nuget packages at the same version, as the rest of the app.
  • Access core interfaces from GUI thread only, they are not thread safe (except if clearly stated so!).
  • Delegate large chunks of work or web requests, to threadpool tasks or use async methods. Blocking GUI thread will block entire Wurm Assistant!
  • Your plugin should never directly reference WurmAssistant project.
  • You can use WinForms and WPF, other Gui frameworks may work but are not directly supported.

Using Dependency Injection

Under the hood, Wurm Assistant is powered by Ninject. If you are familiar with dependency injection, you can leverage this. There is a convention in place, which will register into the kernel all types decorated with KernelBindAttribute. Binding can be further customized with KernelHint.

3 basic customizations are in place:

  • KernelHint.Transient - default binding, every time a type is requested, a new object is created.
  • KernelHint.Singleton - Kernel will create just one instance and inject it into all requestors.
  • KernelHint.FactoryProxy - intended for interfaces, registers them using Ninject.Extensions.Factory convention. If you need to create a registered type at runtime, this is one of the better ways.

Kernel will bind the decorated class, it's base classes (including abstract) and all implemented interfaces. Furthermore, each binding is named with FullName of the class type, so you can bind many classes to same interface, then inject specific implementations of your choice to specific classes, by for example using NamedAttribute (from Ninject library) on a constructor param.

However, you are not in any way forced to stick with these conventions. IAreaConfig can be used to customize your bindings as you see fit.

Using Wurm Assistant core services

Here is a list of most important build-in services you may find useful.

  1. IAreaConfig
  2. IWurmApi
  3. IWurmAssistantDataDirectory
  4. IPersistentContextProvider
  5. ISoundManager
  6. Caliburn Micro
  7. IMessageBus
  8. IDisposable
  9. ILogger
  10. IKernelConfig
  11. IConsoleArgs
  12. IProcessStarter
  13. IWurmAssistantConfig
  14. ITimerFactory
  15. ITrayPopups

Need more docs? More API's?

Only some of the WA components are available for plugins. However, if you'd like something specific, eg. an API to timers feature, feel free to request! We may be able to work something out.

Same for docs, if something is unclear or missing, it can be added.

Clone this wiki locally