5.6 KiB
Defining Plugin Contexts
Plugin contexts are defined similarly to event handlers.
They are public static
methods of your plugin class that must have a
ContextAttribute
and must accept a VoiceAttackInvokeProxyClass
parameter.
ContextAttribute
has a single property Name
. Name
can either be the name
of a plugin context or a regular expression defining all plugin contexts it
should be associated with. Name
is set through an optional parameter of the
attribute constructor; if it is omitted, the method will be executed for any
plugin context.
A method can have multiple ContextAttribute
s. It will be executed if any of
them matches the context of a plugin invocation. That also means that you can
have several methods that handle the same plugin context; as with event
handlers, a specific order of execution cannot be guaranteed.
If your method handles multiple contexts, the context it was invoked with can be
found in the Context
property of its VoiceAttackInvokeProxyClass
parameter.
Note: The log.*
context is reserved for
logging and cannot be used for your
plugin.
Named Plugin Contexts
For singular context names, add a ContextAttribute
for each name. Context
names are to be lower case by convention.
This should be the default way to handle plugin contexts, and multiple contexts handled by the same method should be alternate names for the same functionality. Separate functionality, separate handler method(s).
[Context("test")]
[Context("test context")]
[Context("alternate context name")]
public static void TestContext(VoiceAttackInvokeProxyClass vaProxy) {
[…]
}
Regular Expression Plugin Contexts
For contexts defined by regular expressions, the Name
property must start with
a ^
to be recognized as a regular expression. Incidentally that means you have
to define your regular expression to match from the beginning of the context
string.
The main use case for regular expression contexts is grouping contexts that
logically belong together or behave in very similar ways. For example you could
have a single ^edsm\..*
context in an Elite Dangerous related plugin that
handles anything related to querying EDSM.
As with catchall contexts, you should probably have
some kind of way to differentiate between contexts. For any contexts that match
the regular expression(s) but are not valid contexts for your plugin, throw
an
ArgumentException
with “context” as the parameter name. The exception message
can be anything, it will not be used.
Oh, and of course you can combine named and regular expression contexts. This example features some different regular expressions and corresponding conditionals:
[Context(@"^foo.*")]
[Context(@"^.*bar.*")]
[Context(@"^.*baz")]
[Context("some name")]
public static void RegexContext(VoiceAttackInvokeProxyClass vaProxy) {
string context = vaProxy.Context;
if (context.StartsWith("foo")) {
[…]
}
else if (context.Contains("bar")) {
[…]
}
else if (context.EndsWith("baz")) {
[…]
}
else if (context == "some name")) {
[…]
}
else {
throw new ArgumentException("", "context");
}
}
This example is more focused and closer to how regular expression contexts are intended to be used in practice:
[Context(@"^edsm\..*")]
public static void EdsmContext(VoiceAttackInvokeProxyClass vaProxy) {
switch(vaProxy.Context)
{
case "edsm.findsystem":
[…]
break;
case "edsm.findcommander":
[…]
break;
case "edsm.trafficreport":
[…]
break;
default:
throw new ArgumentException("", "context");;
}
}
“Catchall” Plugin Contexts
To have a method invoked on any plugin invocation regardless of context, add a
ContextAttribute
and omit the Name
.
This is not recommended and has similar issues to using the bare VoiceAttack
plugin API. It is mostly provided for backwards compatibility; you can easily
convert your old VA_Invoke1(dynamic)
method to a catchall plugin context and
then modify from there.
As with regular expression contexts, you
should probably have some kind of way to differentiate between contexts. For any
contexts that are not valid contexts for your plugin, throw
an
ArgumentException
with “context” as the parameter name. The exception message,
again, doesn’t matter.
[Context]
public static void CatchallContext(VoiceAttackInvokeProxyClass vaProxy) {
switch (vaProxy.Context)
{
case "some context":
[…]
break;
case "some other context":
[…]
break;
default:
throw new ArgumentException("", "context");;
}
}
Context Parameters
VoiceAttack plugin contexts by design do not have any parameters. If you need data passed from a VoiceAttack command to the plugin when a context is invoked, you will have to set a variable in your VoiceAttack command and then retrieve said variable from the context handler method.
In general it is recommended to provide context parameters as command scoped
variables (~
prefix) in order not to interfere with other commands / plugin
invocations and their data.
This example accesses the ~test
text variable from plugin code:
string? testParameter = Plugin.Get<string>("~test");
In case a parameter is missing that is required for your context throw
an
ArgumentNullException
with the variable name as the parameter name:
string testParameter = Plugin.Get<string>("~test") ?? throw new ArgumentNullException("~test");