Licensing: The code in this article is licensed under the “Creative Commons Zero v1.0 Universal” license. The license grants you the rights to use the code examples shown in this article in your own mods. ====== Command Suggestions ====== Brigadier allows specification of custom suggestions for arguments. In Minecraft, these suggestions are sent to the client as a user is typing out the command. Besides, some argument types can have their default suggestion providers calculated directly in client, which is not focused in this article. ===== Suggestion Providers ===== A ''SuggestionProvider'' is used to make a list of suggestions that will be sent to the client. A suggestion provider is a functional interface that takes a ''CommandContext'' and a ''SuggestionBuilder'' and returns some ''Suggestions''. The ''SuggestionProvider'' returns a ''CompletableFuture'' as the suggestions may not be available immediately. Suggestions can be contextual since a suggestion provider gives you access to the current command context. ===== An example suggestion provider ===== For example let's say you want to suggest all attributes an entity could have. public class AttributeSuggestionProvider implements SuggestionProvider { @Override public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { Identifier entityTypeId = context.getArgument("type", Identifier.class); ... Since we have a command context, we can check the context for the value of any arguments before the argument this suggestion provider targets. Next is a bunch of boilerplate code public class AttributeSuggestionProvider implements SuggestionProvider { @Override public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) { Identifier entityTypeId = context.getArgument("type", Identifier.class); EntityType entityType = Registries.ENTITY_TYPE.getOrEmpty(entityTypeId).orElse(null); // For versions before 1.19.3, use ''Registry.ENTITY_TYPE'' instead. if (!DefaultAttributeContainer.hasDefinitionFor(entityType)) { return Suggestions.empty() } DefaultAttributeContainer attributeContainer = DefaultAttributeRegistry.get(entityType); // You will need mixin to get the 'instances map'. Lets assume we can just access it for the sake of the tutorial for (EntityAttribute attribute : attributeContainer.instances.keySet()) { Identifier attributeId = Registries.ATTRIBUTE.getId(attribute); if (attributeId != null && CommandSource.shouldSuggest(builder.getRemaining(), attributeId.toString())) { ... The check of ''CommandSource.shouldSuggest'' is intended to suggest only results that match the inputed part, which is ''builder.getRemaining()'', which is the part between the beginning of the argument and the cursor. In order to have a suggestion appear on the client, you must add the suggestion to the builder. This can be done through one of the ''suggest'' methods. Some of these handle numbers, and a few support showing a tooltip. for (EntityAttribute attribute : attributeContainer.instances.keySet()) { Identifier attributeId = Registries.ATTRIBUTE.getId(attribute); if (attributeId != null && CommandSource.shouldSuggest(builder.getRemaining(), attributeId.toString())) { builder.suggest(attributeId.toString()); } } You can also combine the result of another suggestion builder using the ''add(SuggestionBuilder)'' method. Finally, you need to build the suggestions to be returned. This is done with the ''buildFuture'' method. return builder.buildFuture(); And the final product: public class AttributeSuggestionProvider implements SuggestionProvider { @Override public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) { Identifier entityTypeId = context.getArgument("type", Identifier.class); EntityType entityType = Registries.ENTITY_TYPE.getOrEmpty(entityTypeId).orElse(null); if (!DefaultAttributeContainer.hasDefinitionFor(entityType)) { return Suggestions.empty() } DefaultAttributeContainer attributeContainer = DefaultAttributeRegistry.get(entityType); // You will need mixin to get the 'instances map'. Lets assume we can just access it for the sake of the tutorial for (EntityAttribute attribute : attributeContainer.instances.keySet()) { Identifier attributeId = Registries.ATTRIBUTE.getId(attribute); if (attributeId != null && CommandSource.shouldSuggest(builder.getRemaining(), attributeId.toString())) { builder.suggest(attributeId.toString()); } } return builder.buildFuture(); } } ===== Using a suggestion provider ===== Now that you have a suggestion provider, it is time to use the provider. Do note suggestion providers cannot be applied to literals. When registering an argument, you can set the suggestion provider using the ''suggests(SuggestionProvider)'' method. This is applied to the ''RequiredArgumentBuilder'' as shown below: argument(argumentName, word()) .suggests(CompletionProviders.suggestedStrings()) .then(/*Rest of the command*/)); ===== Builtin suggestion providers ===== Minecraft includes a few builtin suggestion providers, which includes: ^ Type ^ Field/Method ^ | Summonable entities | ''SuggestionProviders.SUMMONABLE_ENTITIES'' | | Available sounds | ''SuggestionProviders.AVAILABLE_SOUNDS'' | | Loot Tables | ''LootCommand.SUGGESTION_PROVIDER'' | | Biomes | ''SuggestionProviders.ALL_BIOMES'' | ===== Utilities in CommandSource ===== ''CommandSource'' contains a few utility methods to help remove boilerplate when making the suggestions. Many of the utility methods involve returning completed suggestions from a ''Stream'' or ''Set'' of Identifiers, positions or matching strings. In the example above, we can simplify it to: DefaultAttributeContainer attributeContainer = DefaultAttributeRegistry.get(entityType); // You will need mixin to get the 'instances map'. Lets assume we can just access it for the sake of the tutorial return CommandSource.suggestMatching(Iterables.transform(attributeContainer.instances.keySet(), Identifier::toString), builder); // you can also use stream: return CommandSource.suggestMatching(attributeContainer.instances.keySet().stream().map(Identifier::toString), builder); ===== Builder offsets ===== Most cases the suggestions appear from the beginning of the argument, such as the example above. However, sometimes suggestions appear in the middle of the argument. For example, in a block state argument, you input ''oak_stairs['', and then suggestions should be property names of the block (''facing'', ''waterlogged'', ...). The suggestion appears after the left square bracket. In this case, you should use ''builder.createOffset(offset)'', where ''offset'' is the position of the new suggestion builder. ===== Other command tutorials ===== For other command tutorials, see the sidebar.