Store arguments in order, fix errors, perm check
- Resolved all Command2 errors, Command2MC is next
This commit is contained in:
parent
b53813fa2e
commit
c0c3fc68dc
4 changed files with 125 additions and 104 deletions
|
@ -7,10 +7,10 @@ import buttondevteam.lib.chat.commands.NumberArg;
|
||||||
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.arguments.*;
|
import com.mojang.brigadier.arguments.*;
|
||||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import com.mojang.brigadier.tree.CommandNode;
|
import com.mojang.brigadier.tree.CommandNode;
|
||||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
@ -26,11 +26,9 @@ import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
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;
|
||||||
|
@ -42,8 +40,6 @@ import java.util.stream.Collectors;
|
||||||
@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
|
||||||
*/
|
*/
|
||||||
|
@ -118,7 +114,14 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
private final ArrayList<String> commandHelp = new ArrayList<>(); //Mainly needed by Discord
|
private final ArrayList<String> commandHelp = new ArrayList<>(); //Mainly needed by Discord
|
||||||
private final CommandDispatcher<TP> dispatcher = new CommandDispatcher<>();
|
private final CommandDispatcher<TP> dispatcher = new CommandDispatcher<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first character in the command line that shows that it's a command.
|
||||||
|
*/
|
||||||
private final char commandChar;
|
private final char commandChar;
|
||||||
|
/**
|
||||||
|
* Whether the command's actual code has to be run on the primary thread.
|
||||||
|
*/
|
||||||
|
private final boolean runOnPrimaryThread;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a param converter that obtains a specific object from a string parameter.
|
* Adds a param converter that obtains a specific object from a string parameter.
|
||||||
|
@ -136,85 +139,26 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
|
|
||||||
public boolean handleCommand(TP sender, String commandline) {
|
public boolean handleCommand(TP sender, String commandline) {
|
||||||
var results = dispatcher.parse(commandline, sender);
|
var results = dispatcher.parse(commandline, sender);
|
||||||
boolean sync = Bukkit.isPrimaryThread();
|
if (results.getReader().canRead()) {
|
||||||
|
return false; // Unknown command
|
||||||
|
}
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
||||||
try {
|
try {
|
||||||
handleCommandAsync(sender, results, sync);
|
dispatcher.execute(results);
|
||||||
|
} catch (CommandSyntaxException e) {
|
||||||
|
sender.sendMessage(e.getMessage());
|
||||||
} 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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true; //We found a method - TODO
|
return true; //We found a method
|
||||||
}
|
}
|
||||||
|
|
||||||
//Needed because permission checking may load the (perhaps offline) sender's file which is disallowed on the main thread
|
//Needed because permission checking may load the (perhaps offline) sender's file which is disallowed on the main thread
|
||||||
|
|
||||||
/**
|
//TODO: Add to the help
|
||||||
* Handles a command asynchronously
|
|
||||||
*
|
|
||||||
* @param sender The command sender
|
|
||||||
* @param commandNode The processed command the sender sent
|
|
||||||
* @param sd The subcommand data
|
|
||||||
* @param sync Whether the command was originally 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
|
|
||||||
sender.sendMessage(sd.helpText);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!hasPermission(sender, sd.command, sd.method)) {
|
|
||||||
sender.sendMessage("§cYou don't have permission to use this command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: WIP
|
|
||||||
if (processSenderType(sender, sd, params, parameterTypes)) return; // Checks if the sender is the wrong type
|
|
||||||
val args = parsed.getContext().getArguments();
|
|
||||||
for (var arg : sd.arguments.entrySet()) {
|
|
||||||
// TODO: Invoke using custom method
|
|
||||||
/*if (pj == commandline.length() + 1) { //No param given
|
|
||||||
if (paramArr[i1].isAnnotationPresent(OptionalArg.class)) {
|
|
||||||
if (cl.isPrimitive())
|
|
||||||
params.add(Defaults.defaultValue(cl));
|
|
||||||
else if (Number.class.isAssignableFrom(cl)
|
|
||||||
|| Number.class.isAssignableFrom(cl))
|
|
||||||
params.add(Defaults.defaultValue(Primitives.unwrap(cl)));
|
|
||||||
else
|
|
||||||
params.add(null);
|
|
||||||
continue; //Fill the remaining params with nulls
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(sd.helpText); //Required param missing
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
/*if (paramArr[i1].isVarArgs()) { - TODO: Varargs support? (colors?)
|
|
||||||
params.add(commandline.substring(j + 1).split(" +"));
|
|
||||||
continue;
|
|
||||||
}*/
|
|
||||||
// TODO: Character handling (strlen)
|
|
||||||
// TODO: Param converter
|
|
||||||
}
|
|
||||||
Runnable invokeCommand = () -> {
|
|
||||||
try {
|
|
||||||
sd.method.setAccessible(true); //It may be part of a private class
|
|
||||||
val ret = sd.method.invoke(sd.command, params.toArray()); //I FORGOT TO TURN IT INTO AN ARRAY (for a long time)
|
|
||||||
if (ret instanceof Boolean) {
|
|
||||||
if (!(boolean) ret) //Show usage
|
|
||||||
sender.sendMessage(sd.helpText);
|
|
||||||
} else if (ret != null)
|
|
||||||
throw new Exception("Wrong return type! Must return a boolean or void. Return value: " + ret);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
TBMCCoreAPI.SendException("An error occurred in a command handler for " + subcommand + "!", e.getCause(), MainPlugin.Instance);
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("Command handling failed for sender " + sender + " and subcommand " + subcommand, e, MainPlugin.Instance);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (sync)
|
|
||||||
Bukkit.getScheduler().runTask(MainPlugin.Instance, invokeCommand);
|
|
||||||
else
|
|
||||||
invokeCommand.run();
|
|
||||||
} //TODO: Add to the help
|
|
||||||
|
|
||||||
private boolean processSenderType(TP sender, SubcommandData<TC> sd, ArrayList<Object> params) {
|
private boolean processSenderType(TP sender, SubcommandData<TC, TP> sd, ArrayList<Object> params) {
|
||||||
val sendertype = sd.senderType;
|
val sendertype = sd.senderType;
|
||||||
final ChromaGamerBase cg;
|
final ChromaGamerBase cg;
|
||||||
if (sendertype.isAssignableFrom(sender.getClass()))
|
if (sendertype.isAssignableFrom(sender.getClass()))
|
||||||
|
@ -280,17 +224,17 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
* @return The executable node
|
* @return The executable node
|
||||||
*/
|
*/
|
||||||
private LiteralCommandNode<TP> getExecutableNode(Method method, TC command, Subcommand ann, String path) {
|
private LiteralCommandNode<TP> getExecutableNode(Method method, TC command, Subcommand ann, String path) {
|
||||||
val params = getCommandParameters(method); // Param order is important
|
val paramsAndSenderType = getCommandParameters(method); // Param order is important
|
||||||
|
val params = paramsAndSenderType.getValue0();
|
||||||
val paramMap = new HashMap<String, CommandArgument>();
|
val paramMap = new HashMap<String, CommandArgument>();
|
||||||
for (val param : params) {
|
for (val param : params) {
|
||||||
if (!Objects.equals(param.name, SENDER_ARG_NAME))
|
|
||||||
paramMap.put(param.name, param);
|
paramMap.put(param.name, param);
|
||||||
}
|
}
|
||||||
val node = CoreCommandBuilder.<TP, TC>literal(path, params[0].type, paramMap, command)
|
val node = CoreCommandBuilder.<TP, TC>literal(path, params[0].type, paramMap, params, command)
|
||||||
.helps(command.getHelpText(method, ann)).executes(this::executeCommand);
|
.helps(command.getHelpText(method, ann)).permits(sender -> hasPermission(sender, command, method))
|
||||||
|
.executes(this::executeCommand);
|
||||||
ArgumentBuilder<TP, ?> parent = node;
|
ArgumentBuilder<TP, ?> parent = node;
|
||||||
for (val param : params) { // Register parameters in the right order
|
for (val param : params) { // Register parameters in the right order
|
||||||
if (!Objects.equals(param.name, SENDER_ARG_NAME))
|
|
||||||
parent.then(parent = CoreArgumentBuilder.argument(param.name, getParameterType(param), param.optional));
|
parent.then(parent = CoreArgumentBuilder.argument(param.name, getParameterType(param), param.optional));
|
||||||
}
|
}
|
||||||
return node.build();
|
return node.build();
|
||||||
|
@ -323,32 +267,31 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
* The first parameter is always the sender both in the methods themselves and in the returned array.
|
* 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
|
* @param method The method the subcommand is created from
|
||||||
* @return Parameter data objects
|
* @return Parameter data objects and the sender type
|
||||||
* @throws RuntimeException If there is no sender parameter declared in the method
|
* @throws RuntimeException If there is no sender parameter declared in the method
|
||||||
*/
|
*/
|
||||||
private CommandArgument[] getCommandParameters(Method method) {
|
private Pair<CommandArgument[], Class<?>> getCommandParameters(Method method) {
|
||||||
val parameters = method.getParameters();
|
val parameters = method.getParameters();
|
||||||
if (parameters.length == 0)
|
if (parameters.length == 0)
|
||||||
throw new RuntimeException("No sender parameter for method '" + method + "'");
|
throw new RuntimeException("No sender parameter for method '" + method + "'");
|
||||||
val ret = new CommandArgument[parameters.length];
|
val ret = new CommandArgument[parameters.length];
|
||||||
val usage = getParameterHelp(method);
|
val usage = getParameterHelp(method);
|
||||||
ret[0] = new CommandArgument(SENDER_ARG_NAME, parameters[0].getType(), false, null, false, "Sender");
|
|
||||||
if (usage == null) {
|
if (usage == null) {
|
||||||
for (int i = 1; i < parameters.length; i++) {
|
for (int i = 1; i < parameters.length; i++) {
|
||||||
ret[i] = new CommandArgument("param" + i, parameters[i].getType(), false, null, false, "param" + i);
|
ret[i - 1] = new CommandArgument("param" + i, parameters[i].getType(), false, null, false, "param" + i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val paramNames = usage.split(" ");
|
val paramNames = usage.split(" ");
|
||||||
for (int i = 1; i < parameters.length; i++) {
|
for (int i = 1; i < parameters.length; i++) {
|
||||||
val numAnn = parameters[i].getAnnotation(NumberArg.class);
|
val numAnn = parameters[i].getAnnotation(NumberArg.class);
|
||||||
ret[i] = new CommandArgument(paramNames[i], parameters[i].getType(),
|
ret[i - 1] = new CommandArgument(paramNames[i], parameters[i].getType(),
|
||||||
parameters[i].isVarArgs() || parameters[i].isAnnotationPresent(TextArg.class),
|
parameters[i].isVarArgs() || parameters[i].isAnnotationPresent(TextArg.class),
|
||||||
numAnn == null ? null : new Pair<>(numAnn.lowerLimit(), numAnn.upperLimit()),
|
numAnn == null ? null : new Pair<>(numAnn.lowerLimit(), numAnn.upperLimit()),
|
||||||
parameters[i].isAnnotationPresent(OptionalArg.class),
|
parameters[i].isAnnotationPresent(OptionalArg.class),
|
||||||
paramNames[i]); // TODO: Description (JavaDoc?)
|
paramNames[i]); // TODO: Description (JavaDoc?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return new Pair<>(ret, parameters[0].getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArgumentType<?> getParameterType(CommandArgument arg) {
|
private ArgumentType<?> getParameterType(CommandArgument arg) {
|
||||||
|
@ -384,6 +327,58 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
|
||||||
|
|
||||||
private int executeCommand(CommandContext<TP> context) {
|
private int executeCommand(CommandContext<TP> context) {
|
||||||
System.out.println("Execute command");
|
System.out.println("Execute command");
|
||||||
|
System.out.println("Should be running sync: " + runOnPrimaryThread);
|
||||||
|
|
||||||
|
/*if (!hasPermission(sender, sd.command, sd.method)) {
|
||||||
|
sender.sendMessage("§cYou don't have permission to use this command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: WIP
|
||||||
|
if (processSenderType(sender, sd, params, parameterTypes)) return; // Checks if the sender is the wrong type
|
||||||
|
val args = parsed.getContext().getArguments();
|
||||||
|
for (var arg : sd.arguments.entrySet()) {*/
|
||||||
|
// TODO: Invoke using custom method
|
||||||
|
/*if (pj == commandline.length() + 1) { //No param given
|
||||||
|
if (paramArr[i1].isAnnotationPresent(OptionalArg.class)) {
|
||||||
|
if (cl.isPrimitive())
|
||||||
|
params.add(Defaults.defaultValue(cl));
|
||||||
|
else if (Number.class.isAssignableFrom(cl)
|
||||||
|
|| Number.class.isAssignableFrom(cl))
|
||||||
|
params.add(Defaults.defaultValue(Primitives.unwrap(cl)));
|
||||||
|
else
|
||||||
|
params.add(null);
|
||||||
|
continue; //Fill the remaining params with nulls
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(sd.helpText); //Required param missing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
/*if (paramArr[i1].isVarArgs()) { - TODO: Varargs support? (colors?)
|
||||||
|
params.add(commandline.substring(j + 1).split(" +"));
|
||||||
|
continue;
|
||||||
|
}*/
|
||||||
|
// TODO: Character handling (strlen)
|
||||||
|
// TODO: Param converter
|
||||||
|
/*}
|
||||||
|
Runnable invokeCommand = () -> {
|
||||||
|
try {
|
||||||
|
sd.method.setAccessible(true); //It may be part of a private class
|
||||||
|
val ret = sd.method.invoke(sd.command, params.toArray()); //I FORGOT TO TURN IT INTO AN ARRAY (for a long time)
|
||||||
|
if (ret instanceof Boolean) {
|
||||||
|
if (!(boolean) ret) //Show usage
|
||||||
|
sender.sendMessage(sd.helpText);
|
||||||
|
} else if (ret != null)
|
||||||
|
throw new Exception("Wrong return type! Must return a boolean or void. Return value: " + ret);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
TBMCCoreAPI.SendException("An error occurred in a command handler for " + subcommand + "!", e.getCause(), MainPlugin.Instance);
|
||||||
|
} catch (Exception e) {
|
||||||
|
TBMCCoreAPI.SendException("Command handling failed for sender " + sender + " and subcommand " + subcommand, e, MainPlugin.Instance);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (sync)
|
||||||
|
Bukkit.getScheduler().runTask(MainPlugin.Instance, invokeCommand);
|
||||||
|
else
|
||||||
|
invokeCommand.run();*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import buttondevteam.core.MainPlugin;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.chat.commands.SubcommandData;
|
||||||
import buttondevteam.lib.player.ChromaGamerBase;
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
@ -39,7 +40,7 @@ import java.util.stream.Stream;
|
||||||
|
|
||||||
public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implements Listener {
|
public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implements Listener {
|
||||||
public Command2MC() {
|
public Command2MC() {
|
||||||
super('/');
|
super('/', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,8 +57,8 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
int i = cpath.indexOf(' ');
|
int i = cpath.indexOf(' ');
|
||||||
mainpath = cpath.substring(0, i == -1 ? cpath.length() : i);
|
mainpath = cpath.substring(0, i == -1 ? cpath.length() : i);
|
||||||
}*/
|
}*/
|
||||||
var subcmds = super.registerCommandSuper(command);
|
var commandNode = super.registerCommandSuper(command);
|
||||||
var bcmd = registerOfficially(command, subcmds);
|
var bcmd = registerOfficially(command, commandNode);
|
||||||
if (bcmd != null)
|
if (bcmd != null)
|
||||||
for (String alias : bcmd.getAliases())
|
for (String alias : bcmd.getAliases())
|
||||||
super.registerCommand(command, command.getCommandPath().replaceFirst("^" + bcmd.getName(), Matcher.quoteReplacement(alias)), '/');
|
super.registerCommand(command, command.getCommandPath().replaceFirst("^" + bcmd.getName(), Matcher.quoteReplacement(alias)), '/');
|
||||||
|
@ -208,7 +209,7 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
|
|
||||||
private boolean shouldRegisterOfficially = true;
|
private boolean shouldRegisterOfficially = true;
|
||||||
|
|
||||||
private Command registerOfficially(ICommand2MC command, List<SubcommandData<ICommand2MC>> subcmds) {
|
private Command registerOfficially(ICommand2MC command, LiteralCommandNode<Command2MCSender> node) {
|
||||||
if (!shouldRegisterOfficially || command.getPlugin() == null) return null;
|
if (!shouldRegisterOfficially || command.getPlugin() == null) return null;
|
||||||
try {
|
try {
|
||||||
var cmdmap = (SimpleCommandMap) Bukkit.getServer().getClass().getMethod("getCommandMap").invoke(Bukkit.getServer());
|
var cmdmap = (SimpleCommandMap) Bukkit.getServer().getClass().getMethod("getCommandMap").invoke(Bukkit.getServer());
|
||||||
|
@ -229,7 +230,7 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
bukkitCommand = oldcmd == null ? new BukkitCommand(mainPath) : oldcmd;
|
bukkitCommand = oldcmd == null ? new BukkitCommand(mainPath) : oldcmd;
|
||||||
}
|
}
|
||||||
if (CommodoreProvider.isSupported())
|
if (CommodoreProvider.isSupported())
|
||||||
TabcompleteHelper.registerTabcomplete(command, subcmds, bukkitCommand);
|
TabcompleteHelper.registerTabcomplete(command, node, bukkitCommand);
|
||||||
return bukkitCommand;
|
return bukkitCommand;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (command.getComponent() == null)
|
if (command.getComponent() == null)
|
||||||
|
@ -286,14 +287,14 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
if (subcommand != null)
|
if (subcommand != null)
|
||||||
scmdBuilder.requires(o -> {
|
scmdBuilder.requires(o -> {
|
||||||
var sender = commodore.getBukkitSender(o);
|
var sender = commodore.getBukkitSender(o);
|
||||||
return ButtonPlugin.getCommand2MC().hasPermission(sender, subcommand.command, subcommand.method);
|
return subcommand.hasPermission(sender);
|
||||||
});
|
});
|
||||||
scmd = scmdBuilder.build();
|
scmd = scmdBuilder.build();
|
||||||
parent.addChild(scmd);
|
parent.addChild(scmd);
|
||||||
return scmd;
|
return scmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerTabcomplete(ICommand2MC command2MC, List<SubcommandData<ICommand2MC>> subcmds, Command bukkitCommand) {
|
private static void registerTabcomplete(ICommand2MC command2MC, LiteralCommandNode<Command2MCSender> commandNode, Command bukkitCommand) {
|
||||||
if (commodore == null) {
|
if (commodore == null) {
|
||||||
commodore = CommodoreProvider.getCommodore(MainPlugin.Instance); //Register all to the Core, it's easier
|
commodore = CommodoreProvider.getCommodore(MainPlugin.Instance); //Register all to the Core, it's easier
|
||||||
commodore.register(LiteralArgumentBuilder.literal("un").redirect(RequiredArgumentBuilder.argument("unsomething",
|
commodore.register(LiteralArgumentBuilder.literal("un").redirect(RequiredArgumentBuilder.argument("unsomething",
|
||||||
|
@ -303,7 +304,7 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
var shouldRegister = new AtomicBoolean(true);
|
var shouldRegister = new AtomicBoolean(true);
|
||||||
@SuppressWarnings("unchecked") var maincmd = commodore.getRegisteredNodes().stream()
|
@SuppressWarnings("unchecked") var maincmd = commodore.getRegisteredNodes().stream()
|
||||||
.filter(node -> node.getLiteral().equalsIgnoreCase(path[0]))
|
.filter(node -> node.getLiteral().equalsIgnoreCase(path[0]))
|
||||||
.filter(node -> { shouldRegister.set(false); return true; })
|
.filter(node -> {shouldRegister.set(false); return true;})
|
||||||
.map(node -> (LiteralCommandNode<Object>) node).findAny()
|
.map(node -> (LiteralCommandNode<Object>) node).findAny()
|
||||||
.orElseGet(() -> LiteralArgumentBuilder.literal(path[0]).build()); //Commodore 1.8 removes previous nodes
|
.orElseGet(() -> LiteralArgumentBuilder.literal(path[0]).build()); //Commodore 1.8 removes previous nodes
|
||||||
var cmd = maincmd;
|
var cmd = maincmd;
|
||||||
|
|
|
@ -8,12 +8,13 @@ import com.mojang.brigadier.tree.CommandNode;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class CoreCommandBuilder<S, TC extends ICommand2<?>> extends LiteralArgumentBuilder<S> {
|
public class CoreCommandBuilder<S extends Command2Sender, TC extends ICommand2<?>> extends LiteralArgumentBuilder<S> {
|
||||||
private final SubcommandData.SubcommandDataBuilder<TC> dataBuilder;
|
private final SubcommandData.SubcommandDataBuilder<TC, S> dataBuilder;
|
||||||
|
|
||||||
protected CoreCommandBuilder(String literal, Class<?> senderType, Map<String, CommandArgument> arguments, TC command) {
|
protected CoreCommandBuilder(String literal, Class<?> senderType, Map<String, CommandArgument> arguments, CommandArgument[] argumentsInOrder, TC command) {
|
||||||
super(literal);
|
super(literal);
|
||||||
dataBuilder = SubcommandData.<TC>builder().senderType(senderType).arguments(arguments).command(command);
|
dataBuilder = SubcommandData.<TC, S>builder().senderType(senderType).arguments(arguments)
|
||||||
|
.argumentsInOrder(argumentsInOrder).command(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,12 +22,12 @@ public class CoreCommandBuilder<S, TC extends ICommand2<?>> extends LiteralArgum
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <S, TC extends ICommand2<?>> CoreCommandBuilder<S, TC> literal(String name, Class<?> senderType, Map<String, CommandArgument> arguments, TC command) {
|
public static <S extends Command2Sender, TC extends ICommand2<?>> CoreCommandBuilder<S, TC> literal(String name, Class<?> senderType, Map<String, CommandArgument> arguments, CommandArgument[] argumentsInOrder, TC command) {
|
||||||
return new CoreCommandBuilder<>(name, senderType, arguments, command);
|
return new CoreCommandBuilder<>(name, senderType, arguments, argumentsInOrder, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <S, TC extends ICommand2<?>> CoreCommandBuilder<S, TC> literalNoOp(String name) {
|
public static <S extends Command2Sender, TC extends ICommand2<?>> CoreCommandBuilder<S, TC> literalNoOp(String name) {
|
||||||
return literal(name, Command2Sender.class, Map.of(), null);
|
return literal(name, Command2Sender.class, Map.of(), new CommandArgument[0], null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,9 +54,14 @@ public class CoreCommandBuilder<S, TC extends ICommand2<?>> extends LiteralArgum
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CoreCommandBuilder<S, TC> permits(Function<S, Boolean> permChecker) {
|
||||||
|
dataBuilder.hasPermission(permChecker);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CoreCommandNode<S, TC> build() {
|
public CoreCommandNode<S, TC> build() {
|
||||||
var result = new CoreCommandNode<>(this.getLiteral(), this.getCommand(), this.getRequirement(),
|
var result = new CoreCommandNode<S, TC>(this.getLiteral(), this.getCommand(), this.getRequirement(),
|
||||||
this.getRedirect(), this.getRedirectModifier(), this.isFork(),
|
this.getRedirect(), this.getRedirectModifier(), this.isFork(),
|
||||||
dataBuilder.build());
|
dataBuilder.build());
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package buttondevteam.lib.chat.commands;
|
package buttondevteam.lib.chat.commands;
|
||||||
|
|
||||||
|
import buttondevteam.lib.chat.Command2Sender;
|
||||||
import buttondevteam.lib.chat.ICommand2;
|
import buttondevteam.lib.chat.ICommand2;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
@ -15,7 +16,7 @@ import java.util.function.Function;
|
||||||
*/
|
*/
|
||||||
@Builder
|
@Builder
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public final class SubcommandData<TC extends ICommand2<?>> {
|
public final class SubcommandData<TC extends ICommand2<?>, TP extends Command2Sender> {
|
||||||
/**
|
/**
|
||||||
* The type of the sender running the command.
|
* The type of the sender running the command.
|
||||||
* The actual sender type may not be represented by Command2Sender (TP).
|
* The actual sender type may not be represented by Command2Sender (TP).
|
||||||
|
@ -27,6 +28,10 @@ public final class SubcommandData<TC extends ICommand2<?>> {
|
||||||
* Used to construct the arguments for Brigadier and to hold extra information.
|
* Used to construct the arguments for Brigadier and to hold extra information.
|
||||||
*/
|
*/
|
||||||
public final Map<String, CommandArgument> arguments;
|
public final Map<String, CommandArgument> arguments;
|
||||||
|
/**
|
||||||
|
* Command arguments in the order they appear in code and in game.
|
||||||
|
*/
|
||||||
|
public final CommandArgument[] argumentsInOrder;
|
||||||
/**
|
/**
|
||||||
* The original command class that this data belongs to. If null, that meaans only the help text can be used.
|
* The original command class that this data belongs to. If null, that meaans only the help text can be used.
|
||||||
*/
|
*/
|
||||||
|
@ -43,6 +48,10 @@ public final class SubcommandData<TC extends ICommand2<?>> {
|
||||||
* It will either match or be a Command2Sender, however.
|
* It will either match or be a Command2Sender, however.
|
||||||
*/
|
*/
|
||||||
private final Function<Object, String[]> helpTextGetter;
|
private final Function<Object, String[]> helpTextGetter;
|
||||||
|
/**
|
||||||
|
* A function that determines whether the user has permission to run this subcommand.
|
||||||
|
*/
|
||||||
|
private final Function<TP, Boolean> hasPermission;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get help text for this subcommand.
|
* Get help text for this subcommand.
|
||||||
|
@ -53,4 +62,14 @@ public final class SubcommandData<TC extends ICommand2<?>> {
|
||||||
public String[] getHelpText(Object sender) {
|
public String[] getHelpText(Object sender) {
|
||||||
return staticHelpText == null ? helpTextGetter.apply(sender) : staticHelpText;
|
return staticHelpText == null ? helpTextGetter.apply(sender) : staticHelpText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the user has permission to execute this subcommand.
|
||||||
|
*
|
||||||
|
* @param sender The sender running the command
|
||||||
|
* @return Whether the user has permission
|
||||||
|
*/
|
||||||
|
public boolean hasPermission(TP sender) {
|
||||||
|
return hasPermission.apply(sender);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue