Skip to content

Commit 6172478

Browse files
authored
Added a help command (#6037)
Shows command descriptions, aliases and usage
1 parent 595d1a0 commit 6172478

3 files changed

Lines changed: 153 additions & 0 deletions

File tree

src/main/java/meteordevelopment/meteorclient/commands/Commands.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public static void init() {
6767
add(new InputCommand());
6868
add(new WaspCommand());
6969
add(new LocateCommand());
70+
add(new HelpCommand());
7071

7172
COMMANDS.sort(Comparator.comparing(Command::getName));
7273

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client).
3+
* Copyright (c) Meteor Development.
4+
*/
5+
6+
package meteordevelopment.meteorclient.commands.arguments;
7+
8+
import com.mojang.brigadier.StringReader;
9+
import com.mojang.brigadier.arguments.ArgumentType;
10+
import com.mojang.brigadier.context.CommandContext;
11+
import com.mojang.brigadier.exceptions.CommandSyntaxException;
12+
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
13+
import com.mojang.brigadier.suggestion.Suggestions;
14+
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
15+
import meteordevelopment.meteorclient.commands.Command;
16+
import meteordevelopment.meteorclient.commands.Commands;
17+
import net.minecraft.command.CommandSource;
18+
import net.minecraft.text.Text;
19+
20+
import java.util.Collection;
21+
import java.util.LinkedHashSet;
22+
import java.util.Set;
23+
import java.util.concurrent.CompletableFuture;
24+
import java.util.stream.Collectors;
25+
26+
public class CommandArgumentType implements ArgumentType<Command> {
27+
private static final CommandArgumentType INSTANCE = new CommandArgumentType();
28+
private static final DynamicCommandExceptionType NO_SUCH_COMMAND = new DynamicCommandExceptionType(name -> Text.literal("Command with name " + name + " doesn't exist."));
29+
private static final Collection<String> EXAMPLES = Commands.COMMANDS.stream().limit(3).map(Command::getName).collect(Collectors.toList());
30+
31+
private CommandArgumentType() {
32+
}
33+
34+
public static CommandArgumentType create() {
35+
return INSTANCE;
36+
}
37+
38+
public static Command get(CommandContext<?> context) {
39+
return context.getArgument("command", Command.class);
40+
}
41+
42+
@Override
43+
public Command parse(StringReader reader) throws CommandSyntaxException {
44+
String name = reader.readString();
45+
46+
Command command = Commands.get(name);
47+
48+
if (command == null) {
49+
for (Command c : Commands.COMMANDS) {
50+
for (String alias : c.getAliases()) {
51+
if (alias.equals(name)) {
52+
command = c;
53+
break;
54+
}
55+
}
56+
if (command != null) break;
57+
}
58+
}
59+
60+
if (command == null) throw NO_SUCH_COMMAND.create(name);
61+
return command;
62+
}
63+
64+
@Override
65+
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
66+
Set<String> suggestions = new LinkedHashSet<>();
67+
for (Command c : Commands.COMMANDS) {
68+
suggestions.add(c.getName());
69+
suggestions.addAll(c.getAliases());
70+
}
71+
return CommandSource.suggestMatching(suggestions, builder);
72+
}
73+
74+
@Override
75+
public Collection<String> getExamples() {
76+
return EXAMPLES;
77+
}
78+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client).
3+
* Copyright (c) Meteor Development.
4+
*/
5+
6+
package meteordevelopment.meteorclient.commands.commands;
7+
8+
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
9+
import com.mojang.brigadier.tree.CommandNode;
10+
import meteordevelopment.meteorclient.commands.Command;
11+
import meteordevelopment.meteorclient.commands.Commands;
12+
import meteordevelopment.meteorclient.commands.arguments.CommandArgumentType;
13+
import meteordevelopment.meteorclient.utils.player.ChatUtils;
14+
import net.minecraft.command.CommandSource;
15+
import net.minecraft.text.MutableText;
16+
import net.minecraft.text.Text;
17+
import net.minecraft.util.Formatting;
18+
19+
import java.util.Map;
20+
21+
public class HelpCommand extends Command {
22+
public HelpCommand() {
23+
super("help", "Shows you what a command does.");
24+
}
25+
26+
@Override
27+
public void build(LiteralArgumentBuilder<CommandSource> builder) {
28+
builder.then(argument("command", CommandArgumentType.create()).executes(context -> {
29+
showHelp(CommandArgumentType.get(context));
30+
return SINGLE_SUCCESS;
31+
}));
32+
33+
builder.executes(context -> {
34+
showHelp(this);
35+
return SINGLE_SUCCESS;
36+
});
37+
}
38+
39+
private void showHelp(Command cmd) {
40+
MutableText msg = Text.literal("");
41+
msg.append(Text.literal("Help for ").formatted(Formatting.GRAY).append(Text.literal(cmd.getName()).formatted(Formatting.YELLOW)));
42+
msg.append(Text.literal("\n ")).append(Text.literal("Description: ").formatted(Formatting.GRAY).append(Text.literal(cmd.getDescription()).formatted(Formatting.WHITE)));
43+
44+
if (!cmd.getAliases().isEmpty()) {
45+
msg.append(Text.literal("\n ")).append(Text.literal("Aliases: ").formatted(Formatting.GRAY));
46+
msg.append(Text.literal(String.join(", ", cmd.getAliases())).formatted(Formatting.AQUA));
47+
}
48+
49+
msg.append(getUsageText(cmd));
50+
ChatUtils.sendMsg(msg);
51+
}
52+
53+
private MutableText getUsageText(Command cmd) {
54+
CommandSource source = mc.getNetworkHandler().getCommandSource();
55+
CommandNode<CommandSource> root = Commands.DISPATCHER.getRoot();
56+
CommandNode<CommandSource> node = root.getChild(cmd.getName());
57+
58+
MutableText usagesText = Text.literal("");
59+
60+
if (node != null) {
61+
Map<CommandNode<CommandSource>, String> usages = Commands.DISPATCHER.getSmartUsage(node, source);
62+
63+
for (String usage : usages.values()) {
64+
usagesText.append(Text.literal("\n " + cmd + " ").formatted(Formatting.GREEN)).append(Text.literal(usage).formatted(Formatting.GREEN));
65+
}
66+
}
67+
68+
if (usagesText.getString().isEmpty()) {
69+
usagesText.append(Text.literal("\n " + cmd).formatted(Formatting.GREEN));
70+
}
71+
72+
return Text.literal("\n Usage:").formatted(Formatting.GRAY).append(usagesText);
73+
}
74+
}

0 commit comments

Comments
 (0)