This project is read-only.

Plugin interface


Here's the biggest pain of the project. I've got more planning to do before I tackle it, but, if someone else wants to start, that's fine.
Here's what I've got so far:
Plugins will be implemented through loading assemblies into another appdomain and loading a compiler into another appdomain and creating the assembly there from code.
Personally, I'll be starting on the assembly loader because I'm more familiar with it.
Each plugin, assembly or code, will be in its own folder. All plugins created in this project will be prefixed with awp_.
For assembly plugins, the assembly must be <folder name>.dll. When loading these plugins, all folder contents are copied to a temporary folder with that folder's name being the md5 of the assembly. This is done because loaded assemblies cannot be unloaded, and the assembly plugins should be able to be updated when loaded.
For code plugins, the compiler will be loaded into another appdomain, and the compiler will create the plugin instance in that same appdomain, all in memory.
In order to keep things efficient, the UI appdomain must never load the plugins' assemblies, so the API must be written to not allow this. To see what assemblies are loaded, use AppDomain.CurrentDomain.GetAssemblies(). As far as I know, this will only happen when a plugin sends "custom data" to the main AppDomain. I've never been able to find out what kind of data this is, but it's generally data specific to the plugin's assembly. I believe events are like that because the method the event works with is based in the assembly (not sure).; that's why plugins shouldn't subscribe to events. Events are going to be one of the things I'll be investigating before I get to work.


Timiz0r wrote Oct 23, 2011 at 8:48 PM

After testing, it's true that subscribing to events over appdomains causes the assembly to be loaded. So far, the API's being designed to not request information from plugins, so it should be fine, for now (or until we find otherwise D:). The way we'll implement plugin events is give the plugin's abstract class virtual methods that will be run when the appropriate On<event> method is raised for AwpAdmin events or when the RconClient event is raised.

Also, the plugin abstract class should have the following code: (this is in vb cos didnt translate it yet)
Public Overrides Function InitializeLifetimeService() As Object
    Dim lease As ILease = MyBase.InitializeLifetimeService()

    If lease.CurrentState = LeaseState.Initial Then
        lease.InitialLeaseTime = TimeSpan.Zero
    End If
    Return lease
End Function
That code ensures the ObjectHandle (the proxy for marshalbyrefobject) doesn't expire after inactivity.

Timiz0r wrote Oct 23, 2011 at 9:12 PM

Other things I forgot!

It's important to catch exceptions because they will cause the application to fail. For plugins, the events and constructor should be the only places where an exception should be thrown. Therefore, the constructor (actually, the methods that create the instance) and the virtual methods (events) should be run inside of a try statement.

Also, by default, a winforms app will keep running after an unhandled exception occurs. This will be disabled because the exception may be too big to ignore (such as if it's reoccurring rapidly) and will ensure we keep up a high standard of quality. Console applications do not apply.

Timiz0r wrote Oct 23, 2011 at 9:49 PM

More infos. When we do the code-based plugins, things like references will probably be gotten by parsing vs project files. For now, we'll only support VB.NET and C#.

For the project parsing thingy, we don't have to do any special xml parsing. We just need to find the Reference tags and Compile tags.

Timiz0r wrote Oct 23, 2011 at 10:32 PM

The plugin folder will also contain an info.xml file containing information such as name, website, and description. This will not be done in the assembly because that would require loading it.

Timiz0r wrote Oct 23, 2011 at 11:05 PM

Enabled plugins will be stored in settings.xml's <plugins> element. Plugins are disabled by default, but the settings.xml generator will add the awp_* plugins.

Timiz0r wrote Oct 23, 2011 at 11:24 PM

I've started working on it, and I'll be done by tomorrow.

Timiz0r wrote Oct 24, 2011 at 5:13 PM

I should also mention that there's no way we can prevent plugins from subscribing to RconClient events, even though we provide the virtual methods in the plugin. However, even though this results in the assembly being loaded into the UI's AppDomain, plugins will still work. The only downside is that the repeated loading of assemblies will cause memory usage to increase, I think.

Timiz0r wrote Oct 24, 2011 at 7:28 PM

The plugin that is loaded must be in the namespace AdminPlugin and have a class name of PluginMain.

Timiz0r wrote Oct 29, 2011 at 10:06 PM

The assembly loading plugin interface is completed. Eventually, work will begin on the code loading plugin interface.

wrote Jan 17, 2013 at 7:10 PM

wrote Fri at 9:53 AM