Reload cmd fix, parameter tabcomplete
Made reload cmd only for ButtonPlugins Implemented parameter tabcomplete using Commodore Only works for one subcommand at the moment #82
This commit is contained in:
parent
2cca2e2096
commit
3c4f9f6c7a
4 changed files with 124 additions and 23 deletions
|
@ -29,7 +29,7 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>2.4.2</version>
|
<version>3.2.1</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
|
@ -38,7 +38,17 @@
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<artifactSet>
|
<artifactSet>
|
||||||
|
<includes>
|
||||||
|
<include>me.lucko:commodore</include>
|
||||||
|
</includes>
|
||||||
</artifactSet>
|
</artifactSet>
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>me.lucko.commodore</pattern>
|
||||||
|
<!-- vvv Replace with the package of your plugin vvv -->
|
||||||
|
<shadedPattern>buttondevteam.core.commodore</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
@ -115,6 +125,10 @@
|
||||||
<id>Multiverse-Core</id>
|
<id>Multiverse-Core</id>
|
||||||
<url>http://repo.onarandombox.com/content/repositories/multiverse/</url>
|
<url>http://repo.onarandombox.com/content/repositories/multiverse/</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>minecraft-repo</id>
|
||||||
|
<url>https://libraries.minecraft.net/</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -176,6 +190,12 @@
|
||||||
<version>4.0.1</version>
|
<version>4.0.1</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>me.lucko</groupId>
|
||||||
|
<artifactId>commodore</artifactId>
|
||||||
|
<version>1.5</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<organization>
|
<organization>
|
||||||
<name>TBMCPlugins</name>
|
<name>TBMCPlugins</name>
|
||||||
|
|
|
@ -13,8 +13,8 @@ public class ChromaCommand extends ICommand2MC {
|
||||||
public void reload(CommandSender sender, @Command2.OptionalArg Plugin plugin) {
|
public void reload(CommandSender sender, @Command2.OptionalArg Plugin plugin) {
|
||||||
if (plugin == null)
|
if (plugin == null)
|
||||||
plugin = MainPlugin.Instance;
|
plugin = MainPlugin.Instance;
|
||||||
if(!(plugin instanceof ButtonPlugin))
|
if (!(plugin instanceof ButtonPlugin)) //Probably not a good idea to allow reloading any plugin's config
|
||||||
plugin.reloadConfig();
|
sender.sendMessage("§c" + plugin.getName() + " doesn't support this.");
|
||||||
else if (((ButtonPlugin) plugin).tryReloadConfig())
|
else if (((ButtonPlugin) plugin).tryReloadConfig())
|
||||||
sender.sendMessage("§b" + plugin.getName() + " config reloaded.");
|
sender.sendMessage("§b" + plugin.getName() + " config reloaded.");
|
||||||
else
|
else
|
||||||
|
|
|
@ -274,7 +274,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
|
|
||||||
public abstract void registerCommand(TC command);
|
public abstract void registerCommand(TC command);
|
||||||
|
|
||||||
protected void registerCommand(TC command, @SuppressWarnings("SameParameterValue") char commandChar) {
|
protected List<SubcommandData<TC>> registerCommand(TC command, @SuppressWarnings("SameParameterValue") char commandChar) {
|
||||||
this.commandChar = commandChar;
|
this.commandChar = commandChar;
|
||||||
val path = command.getCommandPath();
|
val path = command.getCommandPath();
|
||||||
int x = path.indexOf(' ');
|
int x = path.indexOf(' ');
|
||||||
|
@ -298,6 +298,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TBMCCoreAPI.SendException("Could not register default handler for command /" + path, e);
|
TBMCCoreAPI.SendException("Could not register default handler for command /" + path, e);
|
||||||
}
|
}
|
||||||
|
var addedSubcommands = new ArrayList<SubcommandData<TC>>();
|
||||||
for (val method : command.getClass().getMethods()) {
|
for (val method : command.getClass().getMethods()) {
|
||||||
val ann = method.getAnnotation(Subcommand.class);
|
val ann = method.getAnnotation(Subcommand.class);
|
||||||
if (ann == null) continue; //Don't call the method on non-subcommands because they're not in the yaml
|
if (ann == null) continue; //Don't call the method on non-subcommands because they're not in the yaml
|
||||||
|
@ -306,15 +307,20 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
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);
|
ht = getParameterHelp(method, ht, subcommand);
|
||||||
subcommands.put(subcommand, new SubcommandData<>(method, command, ht)); //Result of the above (def) is that it will show the help text
|
var sd = new SubcommandData<>(method, command, ht);
|
||||||
|
subcommands.put(subcommand, sd); //Result of the above (def) is that it will show the help text
|
||||||
|
addedSubcommands.add(sd);
|
||||||
scmdHelpList.add(subcommand);
|
scmdHelpList.add(subcommand);
|
||||||
nosubs = false;
|
nosubs = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
||||||
subcommands.put(commandChar + path, new SubcommandData<>(mainMethod, command, scmdHelpList.toArray(new String[0])));
|
var sd = new SubcommandData<>(mainMethod, command, scmdHelpList.toArray(new String[0]));
|
||||||
|
subcommands.put(commandChar + path, 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[]{"§6---- Subcommands ----"}));
|
||||||
|
@ -325,6 +331,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
} 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, scmdHelpList.toArray(new String[0])));
|
||||||
}
|
}
|
||||||
|
return addedSubcommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[] getParameterHelp(Method method, String[] ht, String subcommand) {
|
private String[] getParameterHelp(Method method, String[] ht, String subcommand) {
|
||||||
|
|
|
@ -4,7 +4,13 @@ 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 com.mojang.brigadier.arguments.*;
|
||||||
|
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
import me.lucko.commodore.Commodore;
|
||||||
|
import me.lucko.commodore.CommodoreProvider;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
|
@ -20,8 +26,10 @@ import org.bukkit.permissions.PermissionDefault;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Parameter;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@ -33,7 +41,7 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void registerCommand(ICommand2MC command) {
|
public void registerCommand(ICommand2MC command) {
|
||||||
super.registerCommand(command, '/');
|
var subcmds = super.registerCommand(command, '/');
|
||||||
var perm = "chroma.command." + command.getCommandPath().replace(' ', '.');
|
var perm = "chroma.command." + command.getCommandPath().replace(' ', '.');
|
||||||
if (Bukkit.getPluginManager().getPermission(perm) == null) //Check needed for plugin reset
|
if (Bukkit.getPluginManager().getPermission(perm) == null) //Check needed for plugin reset
|
||||||
Bukkit.getPluginManager().addPermission(new Permission(perm,
|
Bukkit.getPluginManager().addPermission(new Permission(perm,
|
||||||
|
@ -55,7 +63,7 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
PermissionDefault.OP)); //Do not allow any commands that belong to a group
|
PermissionDefault.OP)); //Do not allow any commands that belong to a group
|
||||||
}
|
}
|
||||||
|
|
||||||
registerOfficially(command);
|
registerOfficially(command, subcmds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -257,8 +265,13 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldRegisterOfficially = true;
|
private boolean shouldRegisterOfficially = true;
|
||||||
private void registerOfficially(ICommand2MC command) {
|
|
||||||
|
private void registerOfficially(ICommand2MC command, List<SubcommandData<ICommand2MC>> subcmds) {
|
||||||
if (!shouldRegisterOfficially) return;
|
if (!shouldRegisterOfficially) return;
|
||||||
|
if (CommodoreProvider.isSupported()) {
|
||||||
|
TabcompleteHelper.registerTabcomplete(command, subcmds);
|
||||||
|
return; //Commodore registers the command as well
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
var cmdmap = (SimpleCommandMap) Bukkit.getServer().getClass().getMethod("getCommandMap").invoke(Bukkit.getServer());
|
var cmdmap = (SimpleCommandMap) Bukkit.getServer().getClass().getMethod("getCommandMap").invoke(Bukkit.getServer());
|
||||||
var path = command.getCommandPath();
|
var path = command.getCommandPath();
|
||||||
|
@ -282,4 +295,65 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implemen
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class TabcompleteHelper {
|
||||||
|
private static Commodore commodore;
|
||||||
|
|
||||||
|
private static void registerTabcomplete(ICommand2MC command2MC, List<SubcommandData<ICommand2MC>> subcmds) {
|
||||||
|
if (commodore == null)
|
||||||
|
commodore = CommodoreProvider.getCommodore(MainPlugin.Instance); //Register all to the Core, it's easier
|
||||||
|
System.out.println("Registering tabcomplete for path: " + command2MC.getCommandPath());
|
||||||
|
String[] path = command2MC.getCommandPath().split(" ");
|
||||||
|
var maincmd = LiteralArgumentBuilder.literal(path[0]);
|
||||||
|
var cmd = maincmd;
|
||||||
|
for (int i = 1; i < path.length; i++) {
|
||||||
|
var subcmd = LiteralArgumentBuilder.literal(path[i]);
|
||||||
|
cmd.then(subcmd);
|
||||||
|
cmd = subcmd; //Add each part of the path as a child of the previous one
|
||||||
|
}
|
||||||
|
for (SubcommandData<ICommand2MC> subcmd : subcmds) {
|
||||||
|
String[] subpath = ButtonPlugin.getCommand2MC().getCommandPath(subcmd.method.getName(), ' ').trim().split(" ");
|
||||||
|
ArgumentBuilder<Object, ?> scmd = cmd;
|
||||||
|
if (subpath[0].length() > 0) { //If the method is def, it will contain one empty string
|
||||||
|
for (String s : subpath) {
|
||||||
|
var subsubcmd = LiteralArgumentBuilder.literal(s);
|
||||||
|
scmd.then(subsubcmd);
|
||||||
|
scmd = subsubcmd; //Add method name part of the path (could_be_multiple())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Parameter[] parameters = subcmd.method.getParameters();
|
||||||
|
for (int i = 1; i < parameters.length; i++) { //Skip sender
|
||||||
|
Parameter parameter = parameters[i];
|
||||||
|
ArgumentType<?> type;
|
||||||
|
final Class<?> ptype = parameter.getType();
|
||||||
|
if (ptype == String.class)
|
||||||
|
if (parameter.isAnnotationPresent(TextArg.class))
|
||||||
|
type = StringArgumentType.greedyString();
|
||||||
|
else
|
||||||
|
type = StringArgumentType.word();
|
||||||
|
else if (ptype == int.class || ptype == Integer.class)
|
||||||
|
type = IntegerArgumentType.integer(); //TODO: Min, max
|
||||||
|
else if (ptype == long.class || ptype == Long.class)
|
||||||
|
type = LongArgumentType.longArg();
|
||||||
|
else if (ptype == float.class || ptype == Float.class)
|
||||||
|
type = FloatArgumentType.floatArg();
|
||||||
|
else if (ptype == double.class || ptype == Double.class)
|
||||||
|
type = DoubleArgumentType.doubleArg();
|
||||||
|
else if (ptype == char.class || ptype == Character.class)
|
||||||
|
type = StringArgumentType.word();
|
||||||
|
else if (ptype == boolean.class || ptype == Boolean.class)
|
||||||
|
type = BoolArgumentType.bool();
|
||||||
|
else //TODO: Custom parameter types
|
||||||
|
type = StringArgumentType.word();
|
||||||
|
var arg = RequiredArgumentBuilder.argument(parameter.getName(), type);
|
||||||
|
scmd.then(arg);
|
||||||
|
scmd = arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("maincmd: " + maincmd);
|
||||||
|
System.out.println("Children:");
|
||||||
|
maincmd.build().getChildren().forEach(System.out::println);
|
||||||
|
commodore.register(maincmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue