-
Notifications
You must be signed in to change notification settings - Fork 0
Resolvers
Resolvers are used by the Axwabo.CommandSystem.Registration.CommandRegistrationProcessor
during registration.
They provide a way to separate the attribute data from the logic which gets the value for a property.
Most resolvers process a specific attribute. See also: instance-based resolvers
Tip
Resolvers can be incredibly useful if you want to specify multiple properties at once with an enum or a short string key, as shown in the example plugin
Various interfaces exist in the Axwabo.CommandSystem.PropertyManager.Resolvers
namespace to resolve a property of a command or RA option.
You must implement the generic interface to be able to use the resolver. See also: list of resolvers
When passing a type or a member instance to CommandRegistrationProcessor.RegisterAll
, the attributes on the type (or the type of the member) are added as resolver objects if applicable.
The Axwabo.CommandSystem.Registration.RegistrationExtensions
class defines all extension methods that can be used on a CommandRegistrationProcessor
to manually add resolvers.
These methods can be chained as they return the processor that was passed in.
RegisterAll
uses the WithMultiplexResolverObject
extension method to add all applicable implemented resolvers of each attribute.
Assume you have the following attribute that you add to command classes:
using System;
[AttributeUsage(AttributeTargets.Class)]
public sealed class ConfiguredDescriptionAttribute : Attribute
{
public string Key { get; }
public ConfiguredDescriptionAttribute(string key) => Key = key;
}
A configuration class for the plugin:
using System.Collections.Generic;
public sealed class MyConfig
{
public Dictionary<string, string> DescriptionTranslations { get; set; } = new()
{
{"myCommand", "MyCommand's description"}
};
}
Note
Resolvers don't need to be attributes. When a resolver isn't an attribute on the type used for registration, it must be manually added as shown in methods 3 and 4 of the plugin in this example
To resolve descriptions from the config, define a resolver attribute as follows:
using System;
using Axwabo.CommandSystem.PropertyManager.Resolvers;
[AttributeUsage(AttributeTargets.Class)]
public sealed class ConfiguredDescriptionResolverAttribute : Attribute,
ICommandDescriptionResolver<ConfiguredDescriptionAttribute> // attribute to resolve from
{
public string ResolveDescription(ConfiguredDescriptionAttribute attribute)
{
var config = MyPlugin.Instance?.Config;
if (config == null)
return null;
if (config.DescriptionTranslations.TryGetValue(attribute.Key, out var description))
return description;
return null;
}
}
Finally, register the commands in your plugin:
using Axwabo.CommandSystem.Registration;
using LabApi.Loader.Features.Plugins;
[ConfiguredDescriptionResolver] // added by RegisterAll
public sealed class MyPlugin : Plugin<MyConfig>
{
// plugin properties
public static MyPlugin Instance { get; private set; }
public override void Enable()
{
Instance = this;
// method 1
CommandRegistrationProcessor.RegisterAll(this);
// method 2 (same as RegisterAll)
CommandRegistrationProcessor.Create(this)
.WithTypesFromOriginalAssembly()
.WithRegistrationAttributesFrom(GetType())
.Execute();
// method 3 processes a specific class,
// adding all implemented resolvers
CommandRegistrationProcessor.Create(this)
.WithTypesFromOriginalAssembly()
.WithMultiplexResolverObject(new ConfiguredDescriptionResolverAttribute())
.Execute();
// method 4 explicitly sets what kind of resolvers to add,
// even if a class implements multiple resolvers
// the same instance may be reused in different calls
CommandRegistrationProcessor.Create(this)
.WithTypesFromOriginalAssembly()
.WithDescriptionResolver(new ConfiguredDescriptionResolverAttribute())
.Execute();
}
// unregister commands on disable
}
Important
The IAttributeBasedPermissionResolver
is only invoked if no instance-based resolver could process the attribute.
Interface | Method Name | Return Type |
---|---|---|
IAffectedAllPlayersResolver |
ResolveGenerator | IAffectedAllPlayersMessageGenerator |
IAffectedMultiplePlayersResolver |
ResolveGenerator | IAffectedMultiplePlayersMessageGenerator |
IAffectedOnePlayerResolver |
ResolveGenerator | IAffectedOnePlayerMessageGenerator |
IAttributeBasedPermissionResolver |
ResolvePermissionChecker | IPermissionChecker |
ICommandAliasResolver |
ResolveAliases | string[] |
ICommandDescriptionResolver |
ResolveDescription | string |
ICommandNameResolver |
ResolveName | string |
ICommandUsageResolver |
ResolveUsage | string[] |
IOptionIconResolver |
ResolveIcon | BlinkingIcon |
IPlayerOnlyResolver |
ResolvePlayerOnly | bool |
IRemoteAdminOptionIdResolver |
ResolveIdentifier | string |
IResultCompilerResolver |
ResolveCompiler | ICustomResultCompiler |
IStaticOptionTextResolver |
ResolveContent | string |
ITargetSelectionResolver |
ResolveSelectionManager | ITargetSelectionManager |
Important
Instance-based resolvers must be implemented by an attribute that is placed on the type of the command or RA option
Instance-based resolvers operate on the command or RA option instance. They can be used to resolve a permission checker based on any factor, since base properties have already been initialized. This factor may be the command name or an enum defined in a custom command class.
When implementing the IInstanceBasedPermissionResolver
interface, both of the following methods have to be declared:
CreateFromCommand(CommandBase)
CreateFromOption(RemoteAdminOptionBase)
The IGenericCommandInstanceBasedPermissionResolver<TCommand>
and IGenericRemoteAdminOptionInstanceBasedPermissionResolver<TOption>
interfaces only specify a Create
method where the parameter is the type of TCommand
or TOption
, respectively.