All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.forthecrown.grenadier.annotations.package-info Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
/**
 * Grenadier command annotation library, see below for guides.
 * 

* The annotation library works by taking in an object with a {@link net.forthecrown.grenadier.annotations.CommandData} * annotation, tokenizing the {@link net.forthecrown.grenadier.annotations.CommandData#value()} * and parsing it into an abstract command tree and finally resolving all * variable references, class field/method references and all other else before * the command is registered. *
* This framework makes the creation of commands easier as less boilerplate is * required and command trees can be created faster. * *

Table of contents

*
    *
  1. Guide *
      *
    1. Creating a basic command
    2. *
    3. Using variables
    4. *
    5. Permission and execution defaults
    6. *
    *
  2. *
  3. Syntax Documentation *
      *
    1. Concepts *
        *
      1. Method/Field References
      2. *
      3. Variable References
      4. *
      5. Names
      6. *
      *
    2. *
    3. Command node syntax
    4. *
    5. Root-specific fields
    6. *
    7. Argument-specific fields
    8. *
    9. Fields used by all nodes
    10. *
    11. Child nodes
    12. *
    13. Comments
    14. *
    15. Full example
    16. *
    *
  4. *
* *

Guide

* This part will act as a guide on how to use the Grenadier Annotations library. * *

Creating a basic command

* Let's start with a simple command that just says hello world when it's ran, * we would do that like so: *

 * @CommandData("""
 * name = 'example_command'
 * executes = run()
 * """)
 * public class ExampleCommand {
 *
 *   public void run(CommandContext<CommandSource> context) {
 *     CommandSource source = context.getSource();
 *     source.sendMessage("Hello, world");
 *   }
 * }
 * 
* * You can then register the command like so: *

 * public class ExamplePlugin extends JavaPlugin {
 *
 *   @Override
 *   public void onEnable() {
 *     AnnotatedCommandContext ctx = AnnotatedCommandContext.create();
 *     ctx.registerCommand(new ExampleCommand());
 *   }
 * }
 * 
* *

Using variables

* * Before talking about variables, it must be made clear that there are 2 types * of variables, local and global. For this example, we'll show global variables * first. *

* Variables can be of any type and can be registered like this: *


 * AnnotatedCommandContext ctx = AnnotatedCommandContext.create();
 *
 * Map<String, Object> variables = ctx.getVariables();
 * variables.put("variable_name", "foobar");
 * 
* * You can then use variables like so: *

 * name = 'command_name'
 *
 * literal(@variable_name) {
 *   executes = methodName()
 * }
 * 
* Variables can be used in lots of places, including in argument names, * permission fields, as command names and even for the 'executes', 'suggests' * and 'requires' fields. Make sure to read the Syntax * documentation section for a full guide on variables and the syntax. * *

Permission and executes defaults

* * Default values for both command permissions and 'executes' can be registered * to avoid typing similar permissions and names over and over again. * *
* Permission defaults can be registered like so: *

 * AnnotatedCommandContext ctx = AnnotatedCommandContext.create();
 * ctx.setDefaultPermissionFormat("commands.permission.{command}");
 * 
* The {@code {command}} is a placeholder for the command's name. * *

* Execution defaults allow you to set a method name that will be used * automatically by a command's 'root' node if no other 'executes' value was * specified. *
* * We can set a default execution value like so: *


 * AnnotatedCommandContext ctx = AnnotatedCommandContext.create();
 * ctx.setDefaultExecutes("execute");
 * 
* * and then use it like so: *

 * // No 'executes' was specified, so it defaults to what we set as the
 * // default above
 * @CommandData("name = 'example_command'")
 * public class ExampleCommand {
 *
 *   // Default execution method
 *   public void execute(CommandContext<CommandSource> context) {
 *
 *   }
 * }
 * 
* * Normally, the default execution method will be used if the 'root' node has no * specified 'executes' value set. This can be changed to make sure the default * is only used when there's no other command on the root node and when there's * no child nodes on the command. This can be done like so: * *

 * AnnotatedCommandContext ctx = AnnotatedCommandContext.create();
 * ctx.setDefaultRule(DefaultExecutionRule.IF_NO_CHILDREN);
 * 
* *

Syntax documentation

* Before any of the general syntax is documented, a couple concepts have to be * cleared up. * *

Concepts

* *

Method/Field References

* * These are values that reference a method or a field within a class. Examples: *
 * // References a field within the command's class
 * fieldName
 *
 * // References a method within the command's class, do not
 * // specify any actual parameters here, the '()' are just to
 * // tell the parser this is referencing a method instead
 * // of a field
 * methodName()
 * 
* Both of the above-shown values can be combined like so:
 * field.method().field.method().method()
 * 
* This does become a bit tricky for the behind-the-scenes evaluator as it'll * have to trudge through all those field and method references anytime the * command is executed, suggestions are needed or a requirements check is done. * *

Variable references

* * Far simpler than method/field references, these just reference a variable * registered in {@link net.forthecrown.grenadier.annotations.AnnotatedCommandContext#getVariables()}. *
* Examples:
 * @variableName
 * 
* The values registered in {@link net.forthecrown.grenadier.annotations.AnnotatedCommandContext#getVariables()} * are not the only variables commands can use, those are just the 'global' * variables. Each command can register local variables by declaring a void * method that takes a {@code Map} as input and annotating it * with {@link net.forthecrown.grenadier.annotations.VariableInitializer}. This * will be called before the command is 'compiled' to initialize local * variables within that command's scope. * *

Names

* For the most part, and most commonly, names are just quoted strings, * eg: {@code 'name'}, but there are times when this is not enough. So, whenever * a name is referenced in this documentation it can be 1 or 3 types of values. * These are: A) Quoted strings, B) Variable references or C) Field references. * In the case of C, they reference a field member of the command class. *

* As an example, we'll use the 3 above name types in declaring a * {@code literal} node: *


 * // Quoted string name
 * literal('name') = methodName()
 *
 * // Variable reference name
 * literal(@name) = methodName()
 *
 * // Field reference
 * literal(argumentName) = methodName()
 * 
* *

Command node syntax

* The top level of the Annotation input is the 'root' node, it allows users to * specify details about the base command such as aliases, permission, name and * description. * *

Root specific fields

* *

Name

* See Concepts, Names for valid input. Determines the * name of the command. *

* Examples:

 * name = 'command_name'
 * name = @variable
 * name = classField
 * 
* *

Permission

* A quoted string or '@' variable reference. Specifies the permission the * command uses. Examples:
 * permission = 'foo.bar.foobar'
 * permission = @permission_variable // Must be a string variable
 * 
* * Using the {@link net.forthecrown.grenadier.annotations.AnnotatedCommandContext} * a default permission can be set that is applied to all commands registered * using that specific context. See {@link net.forthecrown.grenadier.annotations.AnnotatedCommandContext#setDefaultPermissionFormat(String)} * for more info. * *

Description

* A quoted string, specifies the command's description. Example: *
 * description = 'This command does a thing'
 * 
* See All Nodes, Descriptions for more info on * descriptions * *

Aliases

* A special list of either quoted strings, unquoted strings, or variable * references. These obviously determine the aliases a command uses. Examples: *
 * aliases = alias1 | alias2 | alias3
 * 
* *

Translate plain

* A {@code true} or {@code false} value that specifies {@link net.forthecrown.grenadier.GrenadierCommand#withPlainTranslation(boolean)}, * defaults to {@code false}, Examples: *
 * translate_plain = true
 * translate_plain = false
 * 
* *

Argument node specific fields

* *

Suggests

* A field/method reference, a variable reference, or a string suggestions list. * Overrides the argument's ArgumentType suggestions. Examples:
 * // Method reference, must take in a CommandContext and SuggestionsBuilder,
 * // and return a CompletableFuture<Suggestions>
 * suggests = getSomeSuggestions()
 *
 * suggests = [ 'foo', 'bar', 'foobar' ]
 *
 * // Variable must be a SuggestionProvider
 * suggests = @suggestion_variable
 * 
* Just like the Executes field, the 'suggests' field * is flexible when it comes to a method reference. Any of the following method * parameters are automatically filled by the system: *
    *
  1. * Any parameter with the {@link net.forthecrown.grenadier.CommandSource} * type is set to the current command's command source *
  2. *
  3. * Any parameter with the {@link com.mojang.brigadier.context.CommandContext} * type is set to the current command context *
  4. *
  5. * Any parameter with the {@link com.mojang.brigadier.suggestion.SuggestionsBuilder} * type is set to the suggestions builder *
  6. *
* The rest of the parameters are treated as argument values within the command. * See the 'Executes' section for more info on that. * *

Fields used by all nodes

* * Fields that are accepted by all nodes (root, argument and literal) * *

Executes

* * A method/field reference or a variable reference. In the case of variable * reference, the variable must be a {@link com.mojang.brigadier.Command}. * Otherwise, in the case of a field reference, the field must point to a * {@link com.mojang.brigadier.Command} value. * *

* In the case the executes value references a method then the method can be * very flexible. For starters, the method must be a publicly accessible method. *
* If the method has any {@link com.mojang.brigadier.context.CommandContext} * parameters, then the context of the command being executed is inputted for * that parameter. The rest of the parameters are treated as arguments in the * command itself and are filled by calling {@link com.mojang.brigadier.context.CommandContext#getArgument(String, Class)} * with the parameter's name and type. *

* If you're encountering issues with the parameter names disappearing during * compilation, you can use the {@link net.forthecrown.grenadier.annotations.Argument} * annotation to preserve it, for example: *

 * public void run(@Argument("argumentName") int value) {
 *   // Do a thing
 * }
 * 
* The {@link net.forthecrown.grenadier.annotations.Argument} annotation can * also be used to avoid the {@link java.lang.IllegalStateException} thrown when * one of the parameter arguments cannot be found like so: *

 * public void run(@Argument(value = "value", optional = true) int value) {
 *
 * }
 * 
* This allows for 1 executes method to be reused for several arguments where * some arguments may be missing. *
* Examples:
 * executes = methodName()
 * executes = @variableName
 * executes = fieldName
 * 
* *

* If the 'executes' field is unset of the 'root' command node, then it may be * assigned a default value, if it exists. See {@link net.forthecrown.grenadier.annotations.AnnotatedCommandContext#getDefaultExecutes()} * for more info. * *

* Since the 'map_result' can be applied to any argument to change it's result * type, any value output from any modifier is also valid for executes methods. * For example, say we have an argument that returns an intermediary object, * like {@link net.forthecrown.grenadier.types.PositionArgument} which returns * {@link net.forthecrown.grenadier.types.ParsedPosition}. If we have a * map_result that converts the position into a location with {@link net.forthecrown.grenadier.types.ParsedPosition#apply(net.forthecrown.grenadier.CommandSource)} * then we can use either the parsed position or location in method parameters. * *

Requires

* Accepts a field/method reference, a variable name or a special 'permission' * value. *

* Sets the requirement a command source must pass to use the command node and * any child nodes. *
* In the case this field is set to a variable name then the variable must be a * {@link java.util.function.Predicate}. Otherwise, in the case of a field * reference the field must be a {@link java.util.function.Predicate} and * finally, in the case of a method reference the method must return a * {@code boolean} and accept a single parameter, a {@link net.forthecrown.grenadier.CommandSource}. *
* If the 'requires' is set to a permission value, the permission value can be * a quoted string, a reference to a field in the command class or a variable. * The variable must be a string or a {@link org.bukkit.permissions.Permission} *

* Examples:

 * requires = permission('permission.name')
 * requires = permission(PERMISSION_CONSTANT)
 * requires = permission(@permissionVariable)
 *
 * requires = @variableName
 * requires = fieldName
 * requires = methodName()
 * 
* *

Map Result

* A field/method reference or variable reference. Allows for the result of an * argument type to mapped to a different type. *
* Results can be mapped with a reference to a method/field within the command's * class or with in the argument result's class. *
* In the case the value of this is a variable reference, then the variable must * be an instance of {@link net.forthecrown.grenadier.annotations.ArgumentModifier}. * *
* Examples: *
 * // References a method within the argument result
 * map_result = result.apply()
 * // References a method in the command class
 * map_result = mapArgument()
 * map_result = @variable
 * 
* *

* If you need to map the value of an argument other than the current one, you * can use {@code map_result(argument name)}, for example: *


 * argument('arg1', entities) {
 *
 *   argument('arg2', int(min=1, max=2) {
 *     map_result('arg1') = result.findEntities()
 *   }
 * }
 * 
* *

Description

* A quoted string, variable or translatable text key. *
* Describes an argument's use description. If this is set in the root node, * then this becomes the command's description and won't become the usage text * unless there's an executes method in the root node. *
* Literal description Example:

 * description = 'Argument description'
 * 
* Translatable description example:

 * description = translatable('translation.key')
 * 
* See {@link net.kyori.adventure.translation.TranslationRegistry}, * {@link net.kyori.adventure.translation.GlobalTranslator} or * {@link net.kyori.adventure.text.TranslatableComponent} for more info on * translatable text. *

* Variable description example:


 * description = @desc_variable
 * 
* The variable must be an instance of {@link net.kyori.adventure.text.Component} *

* This and the {@code label} values are a part of the usage/help system * of the command system. When this description is compiled it will be given to * the {@link net.forthecrown.grenadier.annotations.SyntaxConsumer} of the * current context with the path to the argument provided as well. * *

Syntax Label

* A quoted string, field name or variable that overrides the default node name * for usage/help messages. *
* Example:

 * argument('pos', vec3i) {
 *   label = '<pos: x,y,z>'
 * }
 * 
* In the above example, when the node's name is used in a help message, it will * say '<pos: x,y,z>' instead of '<pos>' * *

Child nodes

* * There are 2 types of child nodes, literals and argument nodes, exactly like * there are in normal Brigadier. * *

Literals

* * Literals only require the name that will be input and are declared so: *
 * literal('foobar') {
 *
 * }
 * 
* * In the case a simple node with nothing but an executes is needed, you can * use the following examples: *
 * literal('foobar') = executesMethod()
 * literal('foobar') = commandField
 * literal('foobar') = @executes_variable
 * 
* See Executes section for how executes methods are * specified. And see Concepts, Names for valid name * input * *

Arguments

* * Arguments require the name of the argument and the argument type. For info * about the argument types and their parsers, see the {@link net.forthecrown.grenadier.annotations.TypeRegistry}. *

* Examples: *

 * argument('argumentName', int(min=1, max=5)) {
 *
 * }
 * 
* Just like with literals, if all that is required is an empty node with an * executes function, you can use the following examples: *
 * argument('arg', int(min=1, max=5)) = executesMethod()
 * argument('arg', int(min=1, max=5)) = commandField
 * argument('arg', int(min=1, max=5)) = @executes_variable
 * 
* See Executes section for how executes methods are * specified. And see Concepts, Names for valid name * input * *

Comments

* Comments inside {@link net.forthecrown.grenadier.annotations.CommandData} * values are the same as in java, '//' starts a line comment, and '/*' specifies * a comment that lasts until '*/' * *

Full example

* *
 * name = 'signedit'
 * aliases = sign | signs
 * permission = 'commands.admin.signedit'
 * description = 'Allows you to edit signs'
 *
 * argument(SIGN_ARG, vec3i) {
 *   map_result = positionToSign()
 *   label = "<sign: x,y,z>"
 *
 *   literal('clear') {
 *     description = "Clears a <sign>"
 *     executes = clear()
 *   }
 *
 *   literal('copy') {
 *     description = "Copies a sign that you can later paste"
 *     executes = copy()
 *   }
 *
 *   literal('paste') {
 *     description = "Pastes a previously copied sign"
 *     executes = paste()
 *   }
 *
 *   literal('glowing').argument(GLOW_ARG, bool) {
 *     description = "Changes whether the sign is glowing or not"
 *     executes = setGlowing()
 *   }
 *
 *   argument(LINE_ARG, int(min=1, max=4)) {
 *     label = '<line: 1..4>'
 *     suggests = ['1', '2', '3', '4']
 *
 *     literal('set') {
 *       argument(TEXT_ARG, greedy_string) {
 *         description = "Sets the sign's <line> to <text>"
 *
 *         map_result = stringToComponent()
 *
 *         suggests = suggestSignLine()
 *         executes = setLine()
 *       }
 *     }
 *
 *     literal('clear') {
 *       executes = clearLine()
 *       description = "Clears a sign's <line>"
 *     }
 *   }
 * }
 * 
* * @see net.forthecrown.grenadier.annotations.AnnotatedCommandContext * Central command registration and handling class * * @see net.forthecrown.grenadier.annotations.TypeRegistry * Argument type parser registry */ package net.forthecrown.grenadier.annotations;




© 2015 - 2025 Weber Informatics LLC | Privacy Policy