List commands on /chroma, fixed arg names
And broke the game (can't connect atm) #84 #82
This commit is contained in:
parent
792a127bdd
commit
95a8e92b51
4 changed files with 95 additions and 26 deletions
|
@ -20,4 +20,14 @@ public class ChromaCommand extends ICommand2MC {
|
||||||
else
|
else
|
||||||
sender.sendMessage("§cFailed to reload config. Check console.");
|
sender.sendMessage("§cFailed to reload config. Check console.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public void def(CommandSender sender) {
|
||||||
|
sender.sendMessage(ButtonPlugin.getCommand2MC().getCommandsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public void test(CommandSender sender, char test) {
|
||||||
|
sender.sendMessage(test + "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import lombok.RequiredArgsConstructor;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
@ -23,14 +22,17 @@ import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
public abstract class Command2<TC extends ICommand2, TP extends Command2Sender> {
|
public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Sender> {
|
||||||
protected Command2() {
|
protected Command2() {
|
||||||
commandHelp.add("§6---- Commands ----");
|
commandHelp.add("§6---- Commands ----");
|
||||||
}
|
}
|
||||||
|
@ -60,10 +62,10 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
String[] helpText() default {};
|
String[] helpText() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main permission which allows using this command (individual access can be still granted with "chroma.command.X").
|
* The main permission which allows using this command (individual access can be still revoked with "chroma.command.X").
|
||||||
* Used to be "tbmc.admin". The {@link #MOD_GROUP} is provided to use with this.
|
* Used to be "tbmc.admin". The {@link #MOD_GROUP} is provided to use with this.
|
||||||
*/
|
*/
|
||||||
String permGroup() default ""; //TODO
|
String permGroup() default "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Target(ElementType.PARAMETER)
|
@Target(ElementType.PARAMETER)
|
||||||
|
@ -72,13 +74,14 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
}
|
}
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
protected static class SubcommandData<T extends ICommand2> {
|
protected static class SubcommandData<T extends ICommand2<?>> {
|
||||||
public final Method method;
|
public final Method method;
|
||||||
public final T command;
|
public final T command;
|
||||||
|
public final String[] parameters;
|
||||||
public String[] helpText;
|
public String[] helpText;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class SubcommandHelpData<T extends ICommand2> extends SubcommandData<T> {
|
/*protected static class SubcommandHelpData<T extends ICommand2> extends SubcommandData<T> {
|
||||||
private final TreeSet<String> ht = new TreeSet<>();
|
private final TreeSet<String> ht = new TreeSet<>();
|
||||||
private BukkitTask task;
|
private BukkitTask task;
|
||||||
|
|
||||||
|
@ -101,7 +104,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
task = null; //Run again, if needed
|
task = null; //Run again, if needed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
protected static class ParamConverter<T> {
|
protected static class ParamConverter<T> {
|
||||||
|
@ -131,7 +134,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
public boolean handleCommand(TP sender, String commandline) {
|
public boolean handleCommand(TP sender, String commandline) {
|
||||||
for (int i = commandline.length(); i != -1; i = commandline.lastIndexOf(' ', i - 1)) {
|
for (int i = commandline.length(); i != -1; i = commandline.lastIndexOf(' ', i - 1)) {
|
||||||
String subcommand = commandline.substring(0, i).toLowerCase();
|
String subcommand = commandline.substring(0, i).toLowerCase();
|
||||||
SubcommandData<TC> sd = subcommands.get(subcommand); //O(1)
|
SubcommandData<TC> sd = subcommands.get(subcommand);
|
||||||
if (sd == null) continue;
|
if (sd == null) continue;
|
||||||
boolean sync = Bukkit.isPrimaryThread();
|
boolean sync = Bukkit.isPrimaryThread();
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
||||||
|
@ -307,8 +310,9 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
if (ht != null) { //The method is a subcommand
|
if (ht != null) { //The method is a subcommand
|
||||||
val subcommand = commandChar + path + //Add command path (class name by default)
|
val subcommand = commandChar + path + //Add command path (class name by default)
|
||||||
getCommandPath(method.getName(), ' '); //Add method name, unless it's 'def'
|
getCommandPath(method.getName(), ' '); //Add method name, unless it's 'def'
|
||||||
ht = getParameterHelp(method, ht, subcommand);
|
var params = new String[method.getParameterCount() - 1];
|
||||||
var sd = new SubcommandData<>(method, command, ht);
|
ht = getParameterHelp(method, ht, subcommand, params);
|
||||||
|
var sd = new SubcommandData<>(method, command, params, ht);
|
||||||
subcommands.put(subcommand, sd); //Result of the above (def) is that it will show the help text
|
subcommands.put(subcommand, sd); //Result of the above (def) is that it will show the help text
|
||||||
addedSubcommands.add(sd);
|
addedSubcommands.add(sd);
|
||||||
scmdHelpList.add(subcommand);
|
scmdHelpList.add(subcommand);
|
||||||
|
@ -318,24 +322,24 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
if (nosubs && scmdHelpList.size() > 0)
|
if (nosubs && scmdHelpList.size() > 0)
|
||||||
scmdHelpList.remove(scmdHelpList.size() - 1); //Remove Subcommands header
|
scmdHelpList.remove(scmdHelpList.size() - 1); //Remove Subcommands header
|
||||||
if (mainMethod != null && !subcommands.containsKey(commandChar + path)) { //Command specified by the class
|
if (mainMethod != null && !subcommands.containsKey(commandChar + path)) { //Command specified by the class
|
||||||
var sd = new SubcommandData<>(mainMethod, command, scmdHelpList.toArray(new String[0]));
|
var sd = new SubcommandData<>(mainMethod, command, null, scmdHelpList.toArray(new String[0]));
|
||||||
subcommands.put(commandChar + path, sd);
|
subcommands.put(commandChar + path, sd);
|
||||||
addedSubcommands.add(sd);
|
addedSubcommands.add(sd);
|
||||||
}
|
}
|
||||||
if (mainMethod != null && !mainPath.equals(commandChar + path)) { //Main command, typically the same as the above
|
if (mainMethod != null && !mainPath.equals(commandChar + path)) { //Main command, typically the same as the above
|
||||||
if (isSubcommand) { //The class itself is a subcommand
|
if (isSubcommand) { //The class itself is a subcommand
|
||||||
val scmd = subcommands.computeIfAbsent(mainPath, p -> new SubcommandData<>(null, null, new String[]{"§6---- Subcommands ----"}));
|
val scmd = subcommands.computeIfAbsent(mainPath, p -> new SubcommandData<>(null, null, new String[0], new String[]{"§6---- Subcommands ----"}));
|
||||||
val scmdHelp = Arrays.copyOf(scmd.helpText, scmd.helpText.length + scmdHelpList.size());
|
val scmdHelp = Arrays.copyOf(scmd.helpText, scmd.helpText.length + scmdHelpList.size());
|
||||||
for (int i = 0; i < scmdHelpList.size(); i++)
|
for (int i = 0; i < scmdHelpList.size(); i++)
|
||||||
scmdHelp[scmd.helpText.length + i] = scmdHelpList.get(i);
|
scmdHelp[scmd.helpText.length + i] = scmdHelpList.get(i);
|
||||||
scmd.helpText = scmdHelp;
|
scmd.helpText = scmdHelp;
|
||||||
} else if (!subcommands.containsKey(mainPath))
|
} else if (!subcommands.containsKey(mainPath))
|
||||||
subcommands.put(mainPath, new SubcommandData<>(null, null, scmdHelpList.toArray(new String[0])));
|
subcommands.put(mainPath, new SubcommandData<>(null, null, new String[0], scmdHelpList.toArray(new String[0])));
|
||||||
}
|
}
|
||||||
return addedSubcommands;
|
return addedSubcommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[] getParameterHelp(Method method, String[] ht, String subcommand) {
|
private String[] getParameterHelp(Method method, String[] ht, String subcommand, String[] parameters) {
|
||||||
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!"));
|
TBMCCoreAPI.SendException("Error while getting command data!", new Exception("Resource not found!"));
|
||||||
|
@ -355,6 +359,9 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
String[] both = Arrays.copyOf(ht, ht.length + 1);
|
String[] both = Arrays.copyOf(ht, ht.length + 1);
|
||||||
both[ht.length] = "§6Usage:§r " + subcommand + " " + params;
|
both[ht.length] = "§6Usage:§r " + subcommand + " " + params;
|
||||||
ht = both;
|
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.toString() + "' != " + mname + " or params is " + params));
|
TBMCCoreAPI.SendException("Error while getting command data for " + method + "!", new Exception("Method '" + method.toString() + "' != " + mname + " or params is " + params));
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -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.commandargs.BetterStringArgumentType;
|
||||||
import com.mojang.brigadier.arguments.*;
|
import com.mojang.brigadier.arguments.*;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||||
|
@ -231,7 +232,7 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
if (parameter.isAnnotationPresent(TextArg.class))
|
if (parameter.isAnnotationPresent(TextArg.class))
|
||||||
type = StringArgumentType.greedyString();
|
type = StringArgumentType.greedyString();
|
||||||
else
|
else
|
||||||
type = StringArgumentType.word();
|
type = BetterStringArgumentType.word();
|
||||||
else if (ptype == int.class || ptype == Integer.class
|
else if (ptype == int.class || ptype == Integer.class
|
||||||
|| ptype == byte.class || ptype == Byte.class
|
|| ptype == byte.class || ptype == Byte.class
|
||||||
|| ptype == short.class || ptype == Short.class)
|
|| ptype == short.class || ptype == Short.class)
|
||||||
|
@ -243,17 +244,26 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
else if (ptype == double.class || ptype == Double.class)
|
else if (ptype == double.class || ptype == Double.class)
|
||||||
type = DoubleArgumentType.doubleArg();
|
type = DoubleArgumentType.doubleArg();
|
||||||
else if (ptype == char.class || ptype == Character.class)
|
else if (ptype == char.class || ptype == Character.class)
|
||||||
type = StringArgumentType.word();
|
type = BetterStringArgumentType.word(1);
|
||||||
else if (ptype == boolean.class || ptype == Boolean.class)
|
else if (ptype == boolean.class || ptype == Boolean.class)
|
||||||
type = BoolArgumentType.bool();
|
type = BoolArgumentType.bool();
|
||||||
else //TODO: Custom parameter types
|
else //TODO: Custom parameter types
|
||||||
type = StringArgumentType.word();
|
type = BetterStringArgumentType.word();
|
||||||
var arg = RequiredArgumentBuilder.argument(parameter.getName(), type).build();
|
var arg = RequiredArgumentBuilder.argument(subcmd.parameters[i - 1], type).build();
|
||||||
scmd.addChild(arg);
|
scmd.addChild(arg);
|
||||||
scmd = arg;
|
scmd = arg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
commodore.register(maincmd);
|
/*try {
|
||||||
|
Class.forName("net.minecraft.server.v1_15_R1.ArgumentRegistry").getMethod("a", String.class, Class.class,
|
||||||
|
Class.forName("net.minecraft.server.v1_15_R1.ArgumentSerializer"))
|
||||||
|
.invoke(null, "chroma:string", BetterStringArgumentType.class,
|
||||||
|
Class.forName("net.minecraft.server.v1_15_R1.ArgumentSerializerVoid").getConstructors()[0]
|
||||||
|
.newInstance((Supplier<BetterStringArgumentType>) BetterStringArgumentType::word));
|
||||||
|
} catch (Exception e) { - Client log: Could not deserialize chroma:string
|
||||||
|
e.printStackTrace();
|
||||||
|
}*/
|
||||||
|
commodore.register(bukkitCommand, maincmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package buttondevteam.lib.chat.commandargs;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.LiteralMessage;
|
||||||
|
import com.mojang.brigadier.StringReader;
|
||||||
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class BetterStringArgumentType implements ArgumentType<String> {
|
||||||
|
private final int len;
|
||||||
|
|
||||||
|
public static BetterStringArgumentType word() {
|
||||||
|
return new BetterStringArgumentType(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BetterStringArgumentType word(int maxlen) {
|
||||||
|
return new BetterStringArgumentType(maxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String parse(StringReader reader) throws CommandSyntaxException {
|
||||||
|
if (len < 1)
|
||||||
|
return reader.readStringUntil(' ');
|
||||||
|
|
||||||
|
final int start = reader.getCursor();
|
||||||
|
if (reader.canRead(len + 1) && reader.peek(len) != ' ')
|
||||||
|
throw new SimpleCommandExceptionType(new LiteralMessage("String too long")).createWithContext(reader);
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
reader.skip();
|
||||||
|
return reader.getString().substring(start, reader.getCursor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getExamples() {
|
||||||
|
return StringArgumentType.StringType.SINGLE_WORD.getExamples();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue