Implement command registration and argument handling
And added some TODOs Also tried to make the code less messy
This commit is contained in:
parent
519a632636
commit
05477641a4
6 changed files with 104 additions and 90 deletions
|
@ -3,13 +3,14 @@ package buttondevteam.lib.chat;
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.lib.chat.commands.CommandArgument;
|
import buttondevteam.lib.chat.commands.CommandArgument;
|
||||||
import buttondevteam.lib.chat.commands.ParameterData;
|
|
||||||
import buttondevteam.lib.chat.commands.SubcommandData;
|
import buttondevteam.lib.chat.commands.SubcommandData;
|
||||||
import buttondevteam.lib.player.ChromaGamerBase;
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import com.mojang.brigadier.ParseResults;
|
import com.mojang.brigadier.ParseResults;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
|
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.mojang.brigadier.tree.CommandNode;
|
||||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
@ -24,24 +25,22 @@ import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Parameter;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Objects;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static buttondevteam.lib.chat.CoreCommandBuilder.literal;
|
|
||||||
import static buttondevteam.lib.chat.CoreCommandBuilder.literalNoOp;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method name is the subcommand, use underlines (_) to add further subcommands.
|
* The method name is the subcommand, use underlines (_) to add further subcommands.
|
||||||
* The args may be null if the conversion failed and it's optional.
|
* The args may be null if the conversion failed and it's optional.
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Sender> {
|
public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Sender> {
|
||||||
|
|
||||||
|
private static final String SENDER_ARG_NAME = "#$@Sender";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters annotated with this receive all the remaining arguments
|
* Parameters annotated with this receive all the remaining arguments
|
||||||
*/
|
*/
|
||||||
|
@ -137,7 +136,7 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
boolean sync = Bukkit.isPrimaryThread();
|
boolean sync = Bukkit.isPrimaryThread();
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
||||||
try {
|
try {
|
||||||
handleCommandAsync(sender, results, results.getContext().getNodes(), sync);
|
handleCommandAsync(sender, results, sync);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TBMCCoreAPI.SendException("Command execution failed for sender " + sender.getName() + "(" + sender.getClass().getCanonicalName() + ") and message " + commandline, e, MainPlugin.Instance);
|
TBMCCoreAPI.SendException("Command execution failed for sender " + sender.getName() + "(" + sender.getClass().getCanonicalName() + ") and message " + commandline, e, MainPlugin.Instance);
|
||||||
}
|
}
|
||||||
|
@ -155,7 +154,7 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
* @param sd The subcommand data
|
* @param sd The subcommand data
|
||||||
* @param sync Whether the command was originally sync
|
* @param sync Whether the command was originally sync
|
||||||
*/
|
*/
|
||||||
private void handleCommandAsync(TP sender, ParseResults<?> parsed, SubcommandData<TC> sd, boolean sync) {
|
private void handleCommandAsync(TP sender, ParseResults<?> parsed, boolean sync) {
|
||||||
if (sd.method == null || sd.command == null) { //Main command not registered, but we have subcommands
|
if (sd.method == null || sd.command == null) { //Main command not registered, but we have subcommands
|
||||||
sender.sendMessage(sd.helpText);
|
sender.sendMessage(sd.helpText);
|
||||||
return;
|
return;
|
||||||
|
@ -244,20 +243,15 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
* @return The processed command node
|
* @return The processed command node
|
||||||
* @throws Exception Something broke
|
* @throws Exception Something broke
|
||||||
*/
|
*/
|
||||||
protected LiteralCommandNode<TP> processSubcommand(TC command, Method method, Subcommand subcommand) throws Exception {
|
protected CoreCommandNode<TP, TC> getSubcommandNode(TC command, Method method, Subcommand subcommand) throws Exception {
|
||||||
val params = new ArrayList<Object>(method.getParameterCount());
|
var pdata = getParameterData(method);
|
||||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
val arguments = new HashMap<String, CommandArgument>(pdata.length - 1);
|
||||||
if (parameterTypes.length == 0)
|
for (var param : pdata) {
|
||||||
throw new Exception("No sender parameter for method '" + method + "'");
|
arguments.put(param.name, param);
|
||||||
val paramArr = method.getParameters();
|
|
||||||
val arguments = new HashMap<String, CommandArgument>(parameterTypes.length - 1);
|
|
||||||
for (int i1 = 1; i1 < parameterTypes.length; i1++) {
|
|
||||||
Class<?> cl = parameterTypes[i1];
|
|
||||||
var pdata = getParameterData(method, i1);
|
|
||||||
arguments.put(pdata.name, new CommandArgument(pdata.name, cl, pdata.description));
|
|
||||||
}
|
}
|
||||||
// TODO: Dynamic help text
|
// TODO: Dynamic help text
|
||||||
return getSubcommandNode(method, parameterTypes[0], command).helps(command.getHelpText(method, subcommand)).build();
|
//return new SubcommandData<>(pdata[0].type, command.getCommandPath() + getCommandPath(method.getName(), ' '), arguments, command, command.getHelpText(method, subcommand), null);
|
||||||
|
return getSubcommandNode(method, pdata[0].type, command).helps(command.getHelpText(method, subcommand)).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -267,9 +261,6 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
* @param i The index to use if no name was found
|
* @param i The index to use if no name was found
|
||||||
* @return Parameter data object
|
* @return Parameter data object
|
||||||
*/
|
*/
|
||||||
private ParameterData getParameterData(Method method, int i) {
|
|
||||||
return null; // TODO: Parameter data (from help text method)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a command in the command system. The way this command gets registered may change depending on the implementation.
|
* Register a command in the command system. The way this command gets registered may change depending on the implementation.
|
||||||
|
@ -286,36 +277,87 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
* @return The Brigadier command node if you need it for something (like tab completion)
|
* @return The Brigadier command node if you need it for something (like tab completion)
|
||||||
*/
|
*/
|
||||||
protected LiteralCommandNode<TP> registerCommandSuper(TC command) {
|
protected LiteralCommandNode<TP> registerCommandSuper(TC command) {
|
||||||
return dispatcher.register(getCommandNode(command));
|
for (val meth : command.getClass().getMethods()) {
|
||||||
|
val ann = meth.getAnnotation(Subcommand.class);
|
||||||
|
if (ann == null) continue;
|
||||||
|
String methodPath = getCommandPath(meth.getName(), ' ');
|
||||||
|
registerNodeFromPath(command.getCommandPath() + methodPath)
|
||||||
|
.addChild(getExecutableNode(meth, command, methodPath.substring(methodPath.lastIndexOf(' ') + 1)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiteralArgumentBuilder<TP> getCommandNode(TC command) {
|
/**
|
||||||
var path = command.getCommandPath().split(" ");
|
* Returns the node that can actually execute the given subcommand.
|
||||||
if (path.length == 0)
|
*
|
||||||
throw new IllegalArgumentException("Attempted to register a command with no command path!");
|
* @param method The subcommand method
|
||||||
CoreCommandBuilder<TP, TC> inner = literalNoOp(path[0]);
|
* @param command The command object
|
||||||
var outer = inner;
|
* @param path The command path
|
||||||
for (int i = path.length - 1; i >= 0; i--) {
|
* @return The executable node
|
||||||
// TODO: This looks like it will duplicate the first node
|
*/
|
||||||
CoreCommandBuilder<TP, TC> literal = literalNoOp(path[i]);
|
private LiteralCommandNode<TP> getExecutableNode(Method method, TC command, String path) {
|
||||||
outer = (CoreCommandBuilder<TP, TC>) literal.executes(this::executeHelpText).then(outer);
|
val params = getCommandParameters(method); // Param order is important
|
||||||
|
val paramMap = new HashMap<String, CommandArgument>();
|
||||||
|
for (val param : params) {
|
||||||
|
if (!Objects.equals(param.name, SENDER_ARG_NAME))
|
||||||
|
paramMap.put(param.name, param);
|
||||||
}
|
}
|
||||||
var subcommandMethods = command.getClass().getMethods();
|
val node = CoreCommandBuilder.<TP, TC>literal(path, params[0].type, paramMap, command).executes(this::executeCommand);
|
||||||
for (var subcommandMethod : subcommandMethods) {
|
ArgumentBuilder<TP, ?> parent = node;
|
||||||
var ann = subcommandMethod.getAnnotation(Subcommand.class);
|
for (val param : params) { // Register parameters in the right order
|
||||||
if (ann == null) continue; // TODO: Replace def nodes with executing ones if needed
|
parent.then(parent = CoreArgumentBuilder.argument(param.name, getParameterType(param.type), false)); // TODO: Optional arg
|
||||||
inner.then(getSubcommandNode(subcommandMethod, ann.helpText()));
|
|
||||||
}
|
}
|
||||||
return outer;
|
return node.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private CoreCommandBuilder<TP, TC> getSubcommandNode(Method method, Class<?> senderType, TC command) {
|
/**
|
||||||
CoreCommandBuilder<TP, TC> ret = literal(method.getName(), senderType, getCommandParameters(method.getParameters()), command);
|
* Registers all necessary no-op nodes for the given path.
|
||||||
return (CoreCommandBuilder<TP, TC>) ret.executes(this::executeCommand);
|
*
|
||||||
|
* @param path The full command path
|
||||||
|
* @return The last no-op node that can be used to register the executable node
|
||||||
|
*/
|
||||||
|
private CommandNode<TP> registerNodeFromPath(String path) {
|
||||||
|
String[] split = path.split(" ");
|
||||||
|
CommandNode<TP> parent = dispatcher.getRoot();
|
||||||
|
for (int i = 0; i < split.length - 1; i++) {
|
||||||
|
String part = split[i];
|
||||||
|
var child = parent.getChild(part);
|
||||||
|
if (child == null)
|
||||||
|
parent.addChild(parent = CoreCommandBuilder.<TP, TC>literalNoOp(part).executes(this::executeHelpText).build());
|
||||||
|
else parent = child;
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, CommandArgument> getCommandParameters(Parameter[] parameters) {
|
/**
|
||||||
return null; // TODO
|
* Get parameter data for the given subcommand. Attempts to read it from the commands file, if it fails, it will return generic info.
|
||||||
|
* The first parameter is always the sender both in the methods themselves and in the returned array.
|
||||||
|
*
|
||||||
|
* @param method The method the subcommand is created from
|
||||||
|
* @return Parameter data objects
|
||||||
|
* @throws RuntimeException If there is no sender parameter declared in the method
|
||||||
|
*/
|
||||||
|
private CommandArgument[] getCommandParameters(Method method) {
|
||||||
|
val parameters = method.getParameterTypes();
|
||||||
|
if (parameters.length == 0)
|
||||||
|
throw new RuntimeException("No sender parameter for method '" + method + "'");
|
||||||
|
val ret = new CommandArgument[parameters.length];
|
||||||
|
val usage = getParameterHelp(method);
|
||||||
|
ret[0] = new CommandArgument(SENDER_ARG_NAME, parameters[0], "Sender");
|
||||||
|
if (usage == null) {
|
||||||
|
for (int i = 1; i < parameters.length; i++) {
|
||||||
|
ret[i] = new CommandArgument("param" + i, parameters[i], "param" + i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val paramNames = usage.split(" ");
|
||||||
|
for (int i = 1; i < parameters.length; i++) {
|
||||||
|
ret[i] = new CommandArgument(paramNames[i], parameters[i], paramNames[i]); // TODO: Description (JavaDoc?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArgumentType<?> getParameterType(Class<?> type) {
|
||||||
|
// TODO: Move from registerTabcomplete
|
||||||
}
|
}
|
||||||
|
|
||||||
private int executeHelpText(CommandContext<TP> context) {
|
private int executeHelpText(CommandContext<TP> context) {
|
||||||
|
@ -383,13 +425,11 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
return addedSubcommands;
|
return addedSubcommands;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
private String[] getParameterHelp(Method method, String[] ht, String subcommand, String[] parameters) {
|
private String getParameterHelp(Method method) {
|
||||||
val str = method.getDeclaringClass().getResourceAsStream("/commands.yml");
|
val str = method.getDeclaringClass().getResourceAsStream("/commands.yml");
|
||||||
if (str == null)
|
if (str == null)
|
||||||
TBMCCoreAPI.SendException("Error while getting command data!", new Exception("Resource not found!"), MainPlugin.Instance);
|
TBMCCoreAPI.SendException("Error while getting command data!", new Exception("Resource not found!"), MainPlugin.Instance);
|
||||||
else {
|
else {
|
||||||
if (ht.length > 0)
|
|
||||||
ht[0] = "§6---- " + ht[0] + " ----";
|
|
||||||
YamlConfiguration yc = YamlConfiguration.loadConfiguration(new InputStreamReader(str)); //Generated by ButtonProcessor
|
YamlConfiguration yc = YamlConfiguration.loadConfiguration(new InputStreamReader(str)); //Generated by ButtonProcessor
|
||||||
val ccs = yc.getConfigurationSection(method.getDeclaringClass().getCanonicalName().replace('$', '.'));
|
val ccs = yc.getConfigurationSection(method.getDeclaringClass().getCanonicalName().replace('$', '.'));
|
||||||
if (ccs != null) {
|
if (ccs != null) {
|
||||||
|
@ -397,15 +437,9 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
if (cs != null) {
|
if (cs != null) {
|
||||||
val mname = cs.getString("method");
|
val mname = cs.getString("method");
|
||||||
val params = cs.getString("params");
|
val params = cs.getString("params");
|
||||||
//val goodname = method.getName() + "(" + Arrays.stream(method.getGenericParameterTypes()).map(cl -> cl.getTypeName()).collect(Collectors.joining(",")) + ")";
|
|
||||||
int i = mname.indexOf('('); //Check only the name - the whole method is still stored for backwards compatibility and in case it may be useful
|
int i = mname.indexOf('('); //Check only the name - the whole method is still stored for backwards compatibility and in case it may be useful
|
||||||
if (i != -1 && method.getName().equals(mname.substring(0, i)) && params != null) {
|
if (i != -1 && method.getName().equals(mname.substring(0, i)) && params != null) {
|
||||||
String[] both = Arrays.copyOf(ht, ht.length + 1);
|
return params;
|
||||||
both[ht.length] = "§6Usage:§r " + subcommand + " " + params;
|
|
||||||
ht = both;
|
|
||||||
var paramArray = params.split(" ");
|
|
||||||
for (int j = 0; j < paramArray.length && j < parameters.length; j++)
|
|
||||||
parameters[j] = paramArray[j];
|
|
||||||
} else
|
} else
|
||||||
TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("Method '" + method + "' != " + mname + " or params is " + params), MainPlugin.Instance);
|
TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("Method '" + method + "' != " + mname + " or params is " + params), MainPlugin.Instance);
|
||||||
} else
|
} else
|
||||||
|
@ -413,7 +447,7 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
} else
|
} else
|
||||||
MainPlugin.Instance.getLogger().warning("Failed to get command data for " + method + " (ccs is null)! Make sure to use 'clean install' when building the project.");
|
MainPlugin.Instance.getLogger().warning("Failed to get command data for " + method + " (ccs is null)! Make sure to use 'clean install' when building the project.");
|
||||||
}
|
}
|
||||||
return ht;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommand(String path, String methodName, Subcommand ann, SubcommandData<TC> sd) {
|
private void registerCommand(String path, String methodName, Subcommand ann, SubcommandData<TC> sd) {
|
||||||
|
@ -429,16 +463,6 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
return commandHelp.toArray(new String[0]);
|
return commandHelp.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getHelpText(String path) {
|
|
||||||
val scmd = subcommands.get(path);
|
|
||||||
if (scmd == null) return null;
|
|
||||||
return scmd.helpText;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*public Set<String> getAllSubcommands() {
|
|
||||||
return Collections.unmodifiableSet(subcommands.keySet());
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters all of the subcommands in the given command.
|
* Unregisters all of the subcommands in the given command.
|
||||||
*
|
*
|
||||||
|
|
|
@ -11,18 +11,16 @@ public class CoreArgumentBuilder<S, T> extends ArgumentBuilder<S, CoreArgumentBu
|
||||||
private final ArgumentType<T> type;
|
private final ArgumentType<T> type;
|
||||||
private final boolean optional;
|
private final boolean optional;
|
||||||
private SuggestionProvider<S> suggestionsProvider = null;
|
private SuggestionProvider<S> suggestionsProvider = null;
|
||||||
private String[] helpText = null; // TODO: Don't need the help text for arguments
|
|
||||||
|
public static <S, T> CoreArgumentBuilder<S, T> argument(String name, ArgumentType<T> type, boolean optional) {
|
||||||
|
return new CoreArgumentBuilder<S, T>(name, type, optional);
|
||||||
|
}
|
||||||
|
|
||||||
public CoreArgumentBuilder<S, T> suggests(SuggestionProvider<S> provider) {
|
public CoreArgumentBuilder<S, T> suggests(SuggestionProvider<S> provider) {
|
||||||
this.suggestionsProvider = provider;
|
this.suggestionsProvider = provider;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CoreArgumentBuilder<S, T> helps(String[] helpText) {
|
|
||||||
this.helpText = helpText;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CoreArgumentBuilder<S, T> getThis() {
|
protected CoreArgumentBuilder<S, T> getThis() {
|
||||||
return this;
|
return this;
|
||||||
|
@ -30,6 +28,6 @@ public class CoreArgumentBuilder<S, T> extends ArgumentBuilder<S, CoreArgumentBu
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CoreArgumentCommandNode<S, T> build() {
|
public CoreArgumentCommandNode<S, T> build() {
|
||||||
return new CoreArgumentCommandNode<>(name, type, getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), suggestionsProvider, optional, helpText);
|
return new CoreArgumentCommandNode<>(name, type, getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), suggestionsProvider, optional);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,10 @@ import java.util.function.Predicate;
|
||||||
|
|
||||||
public class CoreArgumentCommandNode<S, T> extends ArgumentCommandNode<S, T> {
|
public class CoreArgumentCommandNode<S, T> extends ArgumentCommandNode<S, T> {
|
||||||
private final boolean optional;
|
private final boolean optional;
|
||||||
@lombok.Getter private final String[] helpText;
|
|
||||||
|
|
||||||
public CoreArgumentCommandNode(String name, ArgumentType<T> type, Command<S> command, Predicate<S> requirement, CommandNode<S> redirect, RedirectModifier<S> modifier, boolean forks, SuggestionProvider<S> customSuggestions, boolean optional, String[] helpText) {
|
public CoreArgumentCommandNode(String name, ArgumentType<T> type, Command<S> command, Predicate<S> requirement, CommandNode<S> redirect, RedirectModifier<S> modifier, boolean forks, SuggestionProvider<S> customSuggestions, boolean optional) {
|
||||||
super(name, type, command, requirement, redirect, modifier, forks, customSuggestions);
|
super(name, type, command, requirement, redirect, modifier, forks, customSuggestions);
|
||||||
this.optional = optional;
|
this.optional = optional;
|
||||||
this.helpText = helpText;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -71,7 +71,7 @@ public abstract class ICommand2<TP extends Command2Sender> {
|
||||||
*
|
*
|
||||||
* @return The full command paths that this command should be registered under in addition to the default one.
|
* @return The full command paths that this command should be registered under in addition to the default one.
|
||||||
*/
|
*/
|
||||||
public String[] getCommandPaths() {
|
public String[] getCommandPaths() { // TODO: Deal with this (used for channel IDs)
|
||||||
return EMPTY_PATHS;
|
return EMPTY_PATHS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@ package buttondevteam.lib.chat.commands;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command argument's information to be used to construct the command.
|
||||||
|
*/
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class CommandArgument {
|
public class CommandArgument {
|
||||||
public final String name;
|
public final String name;
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
package buttondevteam.lib.chat.commands;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class ParameterData {
|
|
||||||
public final String name;
|
|
||||||
public final String description;
|
|
||||||
}
|
|
Loading…
Reference in a new issue