Mod System Design

NOTE: This documentation is a work in progress and subject to change

Plugin Architecture
ECO uses a plugin architecture which allows the client and server to be readily extended through a set of well-defined contracts. These contracts are defined as C# interfaces (other languages, when supported, would use a language-appropriate variant of this) which the plugin can implement to provide services, or require in order to consume existing services.

Plugins may depend on each other by either explicitly stating requirements (which must be fulfilled before the plugin can be activated) or by requesting access to another plugin/service at run time. For example, a plugin which adds to the minimap may require the minimap plugin, but at runtime might query for plugins which provide additional minimap-related information, if available.

To the extent possible, all services within ECO are provided as plugins, creating a unified and consistent picture of the available services.

Plugins and Mods
Plugins are related to mods. A plugin is specifically the code extension to the game - for example adding new animal behaviors. The mod would contain the plugin as well as related data, such as new animal models, sounds or other non-code artifacts. In this document we are primarily concerned with the plugin aspect of mods.

Plugin Basics
All plugins must implement the IServerPlugin or IClientPlugin interface, depending on whether they extend the server or client. Each of these derives from IPlugin which is the base interface for all plugins.

IPlugin has three methods, styled as events:

OnInitialize - Called after all plugins have been registered, this method allows a plugin to establish if it has all of the dependencies needed to run. If it returns true, the plugin will later be started. Otherwise, the plugin will not be started. This method also provides the plugin with access to the PluginManager, which it may use to find other plugins. The plugin should not normally start any threads or do any significant work in this method.

OnStartupAsync - The first event called after all plugins have been initialized. If the work to do is significant, it is recommend to spawn a worker thread and return a task to represent completion of the startup work. All plugins must complete their startup task before any other events can be raised in the system.

OnShutdownAsync - The last event called. No further calls will be made to the plugin after this. The plugin should release all resources by the time this call returns.

These events will always be called from the same thread, and never in parallel with another plugin. Plugins are free to use background threads to do work, subject to the behavior restrictions above.