Skip to content

Commit 02f02dd

Browse files
committed
Added MissingSubcommandException, plus some more internal changes
1 parent fd54913 commit 02f02dd

16 files changed

+145
-11
lines changed

src/main/java/fr/zcraft/quartzlib/components/commands/CommandGroup.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
package fr.zcraft.quartzlib.components.commands;
22

33
import fr.zcraft.quartzlib.components.commands.exceptions.CommandException;
4+
import fr.zcraft.quartzlib.components.commands.exceptions.MissingSubcommandException;
45
import java.lang.reflect.Field;
56
import java.util.Arrays;
7+
import java.util.Collection;
68
import java.util.HashMap;
79
import java.util.Map;
810
import java.util.function.Supplier;
911
import org.bukkit.command.CommandSender;
1012
import org.jetbrains.annotations.Nullable;
1113

12-
class CommandGroup extends CommandNode {
14+
public class CommandGroup extends CommandNode {
1315
private final Class<?> commandGroupClass;
1416

1517
@Nullable
@@ -52,7 +54,7 @@ private CommandGroup(
5254
DiscoveryUtils.getSubCommands(this, typeCollection).forEach(this::addSubCommand);
5355
}
5456

55-
public Iterable<CommandNode> getSubCommands() {
57+
public Collection<CommandNode> getSubCommands() {
5658
return this.subCommands.values();
5759
}
5860

@@ -91,6 +93,10 @@ void run(Object parentInstance, CommandSender sender, String[] args) throws Comm
9193
}
9294

9395
private void runSelf(Object instance, CommandSender sender, String[] args) throws CommandException {
96+
if (args.length == 0) {
97+
throw new MissingSubcommandException(this);
98+
}
99+
94100
String commandName = args[0];
95101
CommandNode subCommand = subCommands.get(commandName);
96102
// TODO: handle null

src/main/java/fr/zcraft/quartzlib/components/commands/CommandMethod.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class CommandMethod {
2929
if (parameter.isAnnotationPresent(Sender.class)) { // TODO: check for multiple sender arguments
3030
senderArgument = new CommandMethodSenderArgument(parameter, i, typeCollection);
3131
} else {
32-
arguments.add(new CommandMethodArgument(parameter, i, typeCollection));
32+
arguments.add(new CommandMethodArgument(this, parameter, i, typeCollection));
3333
}
3434
}
3535

@@ -69,4 +69,8 @@ private Object[] parseArguments(CommandSender sender, String[] args)
6969
public CommandMethodArgument[] getArguments() {
7070
return arguments;
7171
}
72+
73+
public Method getMethod() {
74+
return method;
75+
}
7276
}

src/main/java/fr/zcraft/quartzlib/components/commands/CommandMethodArgument.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
package fr.zcraft.quartzlib.components.commands;
22

33
import fr.zcraft.quartzlib.components.commands.exceptions.ArgumentParseException;
4+
import fr.zcraft.quartzlib.components.commands.exceptions.UnknownArgumentTypeException;
45
import java.lang.reflect.Parameter;
56

67
public class CommandMethodArgument {
78
private final Parameter parameter;
89
private final int position;
910
private final ArgumentTypeWrapper<?> typeHandler;
1011

11-
public CommandMethodArgument(Parameter parameter, int position, TypeCollection typeCollection) {
12+
public CommandMethodArgument(
13+
CommandMethod parent,
14+
Parameter parameter,
15+
int position,
16+
TypeCollection typeCollection
17+
) {
1218
this.parameter = parameter;
1319
this.position = position;
14-
this.typeHandler = typeCollection.findArgumentType(parameter.getType()).get(); // FIXME: handle unknown types
20+
this.typeHandler = typeCollection.findArgumentType(parameter.getType())
21+
.orElseThrow(() -> new UnknownArgumentTypeException(parent.getMethod(), parameter.getType()));
1522
}
1623

1724
public Object parse(String raw) throws ArgumentParseException {

src/main/java/fr/zcraft/quartzlib/components/commands/CommandNode.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import org.bukkit.command.CommandSender;
55
import org.jetbrains.annotations.Nullable;
66

7-
abstract class CommandNode {
7+
public abstract class CommandNode {
88
private final String name;
99
@Nullable private final CommandGroup parent;
1010

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package fr.zcraft.quartzlib.components.commands;
2+
3+
import org.bukkit.command.CommandSender;
4+
5+
public class ExecutionContext {
6+
private final CommandSender sender;
7+
private final String[] fullArgs;
8+
9+
public ExecutionContext(CommandSender sender, String[] fullArgs) {
10+
this.sender = sender;
11+
this.fullArgs = fullArgs;
12+
}
13+
}

src/main/java/fr/zcraft/quartzlib/components/commands/QuartzCommandExecutor.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fr.zcraft.quartzlib.components.commands;
22

33
import fr.zcraft.quartzlib.components.commands.exceptions.CommandException;
4+
import fr.zcraft.quartzlib.tools.text.RawMessage;
45
import org.bukkit.command.Command;
56
import org.bukkit.command.CommandExecutor;
67
import org.bukkit.command.CommandSender;
@@ -19,7 +20,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command
1920
try {
2021
group.run(sender, args);
2122
} catch (CommandException e) {
22-
throw new RuntimeException(e); // TODO
23+
RawMessage.send(sender, e.display(sender).build());
2324
}
2425
return true;
2526
}

src/main/java/fr/zcraft/quartzlib/components/commands/TypeCollection.java

+2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ private void registerNativeTypes() {
6262
register(new ArgumentTypeWrapper<>(Integer.class, new IntegerArgumentType()));
6363
register(new ArgumentTypeWrapper<>(String.class, s -> s));
6464

65+
register(new ArgumentTypeWrapper<>(int.class, new IntegerArgumentType()));
66+
6567
// Generic types
6668
register(new EnumArgumentType());
6769

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
package fr.zcraft.quartzlib.components.commands.exceptions;
22

3+
import fr.zcraft.quartzlib.components.rawtext.RawText;
4+
import org.bukkit.command.CommandSender;
5+
36
public class ArgumentParseException extends CommandException {
7+
@Override
8+
public RawText display(CommandSender sender) {
9+
return null;
10+
}
411
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
package fr.zcraft.quartzlib.components.commands.exceptions;
22

3+
import fr.zcraft.quartzlib.components.rawtext.RawText;
4+
import org.bukkit.command.CommandSender;
5+
36
public abstract class CommandException extends Exception {
7+
public abstract RawText display(CommandSender sender);
48
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
package fr.zcraft.quartzlib.components.commands.exceptions;
22

3+
import fr.zcraft.quartzlib.components.rawtext.RawText;
4+
import org.bukkit.command.CommandSender;
5+
36
public class InvalidSenderException extends CommandException {
7+
@Override
8+
public RawText display(CommandSender sender) {
9+
return null;
10+
}
411
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package fr.zcraft.quartzlib.components.commands.exceptions;
2+
3+
import fr.zcraft.quartzlib.components.commands.CommandGroup;
4+
import fr.zcraft.quartzlib.components.commands.CommandNode;
5+
import fr.zcraft.quartzlib.components.i18n.I;
6+
import fr.zcraft.quartzlib.components.rawtext.RawText;
7+
import fr.zcraft.quartzlib.components.rawtext.RawTextPart;
8+
import org.bukkit.ChatColor;
9+
import org.bukkit.command.CommandSender;
10+
11+
public class MissingSubcommandException extends CommandException {
12+
private final CommandGroup commandGroup;
13+
14+
public MissingSubcommandException(CommandGroup commandGroup) {
15+
this.commandGroup = commandGroup;
16+
}
17+
18+
@Override
19+
public RawText display(CommandSender sender) {
20+
RawTextPart<?> text = new RawText(I.t("Missing subcommand: "))
21+
.color(ChatColor.RED)
22+
.then("/").color(ChatColor.WHITE)
23+
.then(getParents()).color(ChatColor.AQUA)
24+
.then(" <").style(ChatColor.GRAY)
25+
.then(I.t("sub-command"))
26+
.style(ChatColor.GRAY, ChatColor.UNDERLINE)
27+
.hover(appendSubCommandList(new RawText()))
28+
.then(">").style(ChatColor.GRAY);
29+
30+
return text.build();
31+
}
32+
33+
private String getParents() {
34+
StringBuilder builder = new StringBuilder();
35+
36+
CommandGroup group = commandGroup;
37+
38+
do {
39+
if (builder.length() > 0) {
40+
builder.append(' ');
41+
}
42+
builder.append(group.getName());
43+
group = group.getParent();
44+
} while (group != null);
45+
46+
return builder.toString();
47+
}
48+
49+
private RawTextPart<?> appendSubCommandList(RawTextPart<?> text) {
50+
boolean first = true;
51+
text = text.then(I.t("One of the following:\n "));
52+
for (CommandNode subCommand : commandGroup.getSubCommands()) {
53+
if (!first) {
54+
text = text.then(", ").color(ChatColor.GRAY);
55+
}
56+
first = false;
57+
58+
text = text.then(subCommand.getName()).color(ChatColor.AQUA);
59+
}
60+
61+
return text;
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package fr.zcraft.quartzlib.components.commands.exceptions;
2+
3+
import java.lang.reflect.Method;
4+
5+
public class UnknownArgumentTypeException extends RuntimeException {
6+
public UnknownArgumentTypeException(Method method, Class<?> foundType) {
7+
super(getErrorMessage(method, foundType));
8+
}
9+
10+
private static String getErrorMessage(Method method, Class<?> foundType) {
11+
return "Found unknown command argument type: '" + foundType
12+
+ "' (found in '" + method.toString() + "'). "
13+
+ "Did you forget to register it to the CommandManager?";
14+
}
15+
}

src/main/java/fr/zcraft/quartzlib/tools/text/RawMessage.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
* Utility to send JSON messages.
4242
*
4343
* <p>This tool uses the /tellraw command to send the messages. If the JSON is not correctly
44-
* formatted, the message will not be sent and a Runtime exception containing the exception throw by
44+
* formatted, the message will not be sent and a Runtime exception containing the exception thrown by
4545
* the vanilla /tellraw command will be thrown.</p>
4646
*/
4747
public final class RawMessage {

src/test/java/fr/zcraft/quartzlib/components/commands/CommandRegistrationTests.java renamed to src/test/java/fr/zcraft/quartzlib/components/commands/CommandExecutionTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import org.junit.Before;
77
import org.junit.Test;
88

9-
public class CommandRegistrationTests extends MockedToasterTest {
9+
public class CommandExecutionTests extends MockedToasterTest {
1010
private CommandManager commands;
1111

1212
@Before

ztoaster/src/main/java/fr/zcraft/ztoaster/Toaster.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
package fr.zcraft.ztoaster;
3232

33+
import fr.zcraft.quartzlib.components.commands.CommandManager;
3334
import fr.zcraft.quartzlib.components.gui.Gui;
3435
import fr.zcraft.quartzlib.components.i18n.I18n;
3536
import fr.zcraft.quartzlib.components.scoreboard.Sidebar;
@@ -64,14 +65,16 @@ public class Toaster extends QuartzPlugin implements Listener {
6465
*/
6566
private Sidebar toasterSidebar;
6667

67-
public Toaster () {}
68+
public Toaster() {
69+
}
6870

6971
protected Toaster(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) {
7072
super(loader, description, dataFolder, file);
7173
}
7274

7375
/**
7476
* .
77+
*
7578
* @return The id for a new toast.
7679
*/
7780
public static int newToastId() {
@@ -80,6 +83,7 @@ public static int newToastId() {
8083

8184
/**
8285
* .
86+
*
8387
* @return an array of all the toasts ever created (until toaster restart).
8488
*/
8589
public static Toast[] getToasts() {
@@ -106,7 +110,8 @@ public void onEnable() {
106110

107111
loadComponents(Gui.class, ToasterWorker.class, SidebarScoreboard.class, I18n.class);
108112

109-
// Commands.register("toaster", AddCommand.class, OpenCommand.class, ListCommand.class);
113+
new CommandManager()
114+
.registerCommand("toaster", ToastCommands.class, ToastCommands::new);
110115

111116
I18n.useDefaultPrimaryLocale();
112117
I18n.setFallbackLocale(Locale.US);

0 commit comments

Comments
 (0)