Plugin Release Grenadier Command Library

Grenadier is a library for Paper that allows developers to use the Brigadier command engine developed by Mojang without having to interact with NMS classes all the while providing access to a lot of the powerful features Brigadier brought with it.

Check out the project on GitHub here and the Javadoc documentation
The project also comes with lots of built-in argument parsers and utilities so you don't have to rewrite something that already exists in vanilla, you can see those all listed below.

On top of this, each argument type is mapped to a vanilla counterpart which allows for grenadier's command trees to be translated into vanilla trees so they can provide more info during input for the client, and show distinct colors in chat to let you know what kind of argument you're typing. Not to mention the error messages which give more detail on where an error ocurred during parsing.

Support is also provided for custom ArgumentTypes

You can then create commands by extending the net.forthecrown.grenadier.AbstractCommand abstract class, for example:
Java:
import net.forthecrown.grenadier.AbstractCommand;

public class ExampleCommand extends AbstractCommand {
  public ExampleCommand() {
    super("example_command");

    register();
  }

  public void createCommand(GrenadierCommand command) {
    command.executes(context -> {
      CommandSource source = context.getSource();
      source.sendMessage("Hello, world!");
      return 0;
    });
  }
}

Currently, an annotation extension (inspired by Aikar's command framework) is being worked on to remove a lot of boilerplate and hassle involved in writing commands. Here's an example of how that should look like:
Java:
@CommandData("""
name = 'annotation_example'
aliases = alias1
        | alias2
       
argument(@argument_name, greedy_string) {
  executes = run()
}
""")
public class TestCommand2 {

  static final String THING_ARGUMENT = "thing";

  @VariableInitializer
  void initLocalVariables(Map<String, Object> variables) {
    variables.put("argument_name", THING_ARGUMENT);
  }

  public void run(CommandContext<CommandSource> context,
                  @Argument(THING_ARGUMENT) String input
  ) {
    context.getSource().sendMessage(input);
  }
}

General use argument types
Argument typeDescriptionExample
OptionsArgumentParse a list of pre-set options and flagskey=value -flag
MapArgumentTakes a string 2 object map and parses a map value via its string keya_value
EnumArgumentParses an enum constant from it's Enum.name()red
ArrayArgumentParses a List of a specified type of argumentsminecraft:stone,minecraft:eek:ak_log
LocalDateArgumentParses a LocalDate object from the ISO-8601 format12-12-2023
TimeArgumentParses a Duration3s, 3seconds, 5m, 5minutes


Minecraft argument types
Argument typeDescriptionExample
BlockArgumentParses a block state and optionally NBT data that can be applied to a blockminecraft:chest[facing=west]{dataKey:1b}
BlockFilterArgumentParses a block or block tag that can be used to as a predicate for blocks#minecraft:buttons[face=ceiling]
ComponentArgumentParses a text component from a JSON format{"text":"Some text","color":"red"}
EntityArgumentParses an entity selector that returns 1 or more entities/players@e[limit=1,distance=..2]
GameModeArgumentGame mode value from a non-vanilla set of labelscreative, survival, c, s
ItemArgumentParses an itemstack along with item NBT dataminecraft:stone{nbtKey:1b}
ItemFilterArgumentParses an item or itemtag along with NBT data that will be used as a predicate against other items#minecraft:flowers{nbtKey:1b}
KeyArgumentParses a namespaced keyminecraft:stone
NbtArgumentParses NBT data in the SNBT format{foo:'bar',abc:1b}
ObjectiveArgumentParses a scoreboard objective from its namedeaths, noClip
ParticleArgumentParses a particle by its keyminecraft:explosion_emitter
PositionArgumentParses a relative/local/absolute 2D or 3D position~ ~ ~
TagPathArgumentParses an NBT pathkey1.key2[]
TeamArgumentParses a scoreboard team from its nameteam1, Team2
UuidArgumentParses a UUID by its hexadecimal value21290ce5-679c-4917-b30e-168c0d450c72
WorldArgumentParses a world by its nameworld, world_the_end
DoubleRangeArgumentParses an inclusive range of double values1..2, 1.., ..3
IntRangeArgumentParses an inclusive range of integer values1..2, 1.., ..3

You can add it to your projects like so:
Code:
repositories {
  mavenCentral()

  // Brigadier's repository
  maven("https://libraries.minecraft.net")
}

dependencies {
  // Grenadier
  implementation("net.forthecrown:grenadier:2.0.6")

  // Mojang's Brigadier
  compileOnly("com.mojang:brigadier:1.0.18")
}