Listing subcommands, other fixes
Member command converted Now requiring the permissions plugin Added support for optional arguments Automatically sending an error if parameter conversion fails Automatically sending the help text if there aren't enough args Automatically converting the first line of the help text to a header
This commit is contained in:
parent
ab24480f89
commit
e32805c1fc
10 changed files with 137 additions and 90 deletions
|
@ -2,6 +2,7 @@ package buttondevteam.core;
|
||||||
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
import buttondevteam.lib.chat.Command2.Subcommand;
|
import buttondevteam.lib.chat.Command2.Subcommand;
|
||||||
import buttondevteam.lib.chat.CommandClass;
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
import buttondevteam.lib.chat.ICommand2MC;
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
@ -13,29 +14,27 @@ import org.bukkit.plugin.Plugin;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@CommandClass(modOnly = true, helpText = {
|
@CommandClass(modOnly = true, helpText = {
|
||||||
"§6---- Component command ----",
|
"Component command",
|
||||||
"Can be used to enable/disable/list components"
|
"Can be used to enable/disable/list components"
|
||||||
})
|
})
|
||||||
public class ComponentCommand extends ICommand2MC {
|
public class ComponentCommand extends ICommand2MC {
|
||||||
public ComponentCommand() {
|
public ComponentCommand() {
|
||||||
getManager().addParamConverter(Plugin.class, arg -> Bukkit.getPluginManager().getPlugin(arg));
|
getManager().addParamConverter(Plugin.class, arg -> Bukkit.getPluginManager().getPlugin(arg), "Plugin not found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subcommand
|
@Subcommand
|
||||||
public boolean enable(CommandSender sender, Plugin plugin, String component) {
|
public boolean enable(CommandSender sender, Plugin plugin, String component) {
|
||||||
if (plugin == null) return respond(sender, "§cPlugin not found!");
|
|
||||||
plugin.reloadConfig(); //Reload config so the new config values are read - All changes are saved to disk on disable
|
plugin.reloadConfig(); //Reload config so the new config values are read - All changes are saved to disk on disable
|
||||||
return enable_disable(sender, plugin, component, true);
|
return enable_disable(sender, plugin, component, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subcommand
|
@Subcommand
|
||||||
public boolean disable(CommandSender sender, Plugin plugin, String component) {
|
public boolean disable(CommandSender sender, Plugin plugin, String component) {
|
||||||
if (plugin == null) return respond(sender, "§cPlugin not found!");
|
|
||||||
return enable_disable(sender, plugin, component, false);
|
return enable_disable(sender, plugin, component, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subcommand
|
@Subcommand
|
||||||
public boolean list(CommandSender sender, String plugin) {
|
public boolean list(CommandSender sender, @Command2.OptionalArg String plugin) {
|
||||||
sender.sendMessage("§6List of components:");
|
sender.sendMessage("§6List of components:");
|
||||||
Component.getComponents().values().stream().filter(c -> plugin == null || c.getPlugin().getName().equalsIgnoreCase(plugin)) //If plugin is null, don't check
|
Component.getComponents().values().stream().filter(c -> plugin == null || c.getPlugin().getName().equalsIgnoreCase(plugin)) //If plugin is null, don't check
|
||||||
.map(c -> c.getPlugin().getName() + " - " + c.getClass().getSimpleName() + " - " + (c.isEnabled() ? "en" : "dis") + "abled").forEach(sender::sendMessage);
|
.map(c -> c.getPlugin().getName() + " - " + c.getClass().getSimpleName() + " - " + (c.isEnabled() ? "en" : "dis") + "abled").forEach(sender::sendMessage);
|
||||||
|
|
|
@ -14,7 +14,6 @@ import buttondevteam.lib.architecture.ButtonPlugin;
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component;
|
||||||
import buttondevteam.lib.architecture.ConfigData;
|
import buttondevteam.lib.architecture.ConfigData;
|
||||||
import buttondevteam.lib.chat.Color;
|
import buttondevteam.lib.chat.Color;
|
||||||
import buttondevteam.lib.chat.Command2MC;
|
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
import buttondevteam.lib.player.ChromaGamerBase;
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
import buttondevteam.lib.player.TBMCPlayer;
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
@ -30,7 +29,6 @@ import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.PluginDescriptionFile;
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
@ -42,7 +40,6 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
public class MainPlugin extends ButtonPlugin {
|
public class MainPlugin extends ButtonPlugin {
|
||||||
public static MainPlugin Instance;
|
public static MainPlugin Instance;
|
||||||
@Nullable
|
|
||||||
public static Permission permission;
|
public static Permission permission;
|
||||||
public static boolean Test;
|
public static boolean Test;
|
||||||
public static Essentials ess;
|
public static Essentials ess;
|
||||||
|
@ -59,7 +56,8 @@ public class MainPlugin extends ButtonPlugin {
|
||||||
Instance = this;
|
Instance = this;
|
||||||
PluginDescriptionFile pdf = getDescription();
|
PluginDescriptionFile pdf = getDescription();
|
||||||
logger = getLogger();
|
logger = getLogger();
|
||||||
setupPermissions();
|
if (!setupPermissions())
|
||||||
|
throw new NullPointerException("No permission plugin found!");
|
||||||
Test = getConfig().getBoolean("test", true);
|
Test = getConfig().getBoolean("test", true);
|
||||||
saveConfig();
|
saveConfig();
|
||||||
Component.registerComponent(this, new PluginUpdaterComponent());
|
Component.registerComponent(this, new PluginUpdaterComponent());
|
||||||
|
@ -69,7 +67,7 @@ public class MainPlugin extends ButtonPlugin {
|
||||||
Component.registerComponent(this, new MemberComponent());
|
Component.registerComponent(this, new MemberComponent());
|
||||||
Component.registerComponent(this, new TownyComponent());
|
Component.registerComponent(this, new TownyComponent());
|
||||||
ComponentManager.enableComponents();
|
ComponentManager.enableComponents();
|
||||||
Command2MC.registerCommand(new ComponentCommand());
|
getCommand2MC().registerCommand(new ComponentCommand());
|
||||||
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this);
|
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this);
|
||||||
ChromaGamerBase.addConverter(commandSender -> Optional.ofNullable(commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender
|
ChromaGamerBase.addConverter(commandSender -> Optional.ofNullable(commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender
|
||||||
? TBMCPlayer.getPlayer(new UUID(0, 0), TBMCPlayer.class) : null)); //Console & cmdblocks
|
? TBMCPlayer.getPlayer(new UUID(0, 0), TBMCPlayer.class) : null)); //Console & cmdblocks
|
||||||
|
|
|
@ -3,7 +3,7 @@ package buttondevteam.core;
|
||||||
import buttondevteam.lib.TBMCCommandPreprocessEvent;
|
import buttondevteam.lib.TBMCCommandPreprocessEvent;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.lib.TBMCSystemChatEvent;
|
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||||
import buttondevteam.lib.chat.Command2MC;
|
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||||
import buttondevteam.lib.player.TBMCPlayerBase;
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
@ -64,7 +64,7 @@ public class PlayerListener implements Listener {
|
||||||
public void onTBMCPreprocess(TBMCCommandPreprocessEvent event) {
|
public void onTBMCPreprocess(TBMCCommandPreprocessEvent event) {
|
||||||
if (event.isCancelled()) return;
|
if (event.isCancelled()) return;
|
||||||
try {
|
try {
|
||||||
event.setCancelled(Command2MC.handleCommand(event.getSender(), event.getMessage()));
|
event.setCancelled(ButtonPlugin.getCommand2MC().handleCommand(event.getSender(), event.getMessage()));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TBMCCoreAPI.SendException("Command processing failed for sender '" + event.getSender() + "' and message '" + event.getMessage() + "'", e);
|
TBMCCoreAPI.SendException("Command processing failed for sender '" + event.getSender() + "' and message '" + event.getMessage() + "'", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +1,47 @@
|
||||||
package buttondevteam.core.component.members;
|
package buttondevteam.core.component.members;
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
import buttondevteam.lib.chat.CommandClass;
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
import lombok.val;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
@CommandClass(modOnly = true, path = "member")
|
@CommandClass(modOnly = true, path = "member", helpText = { //
|
||||||
public class MemberCommand extends TBMCCommandBase {
|
"Member command", //
|
||||||
@Override
|
"Add or remove server members.", //
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
})
|
||||||
if (args.length < 2)
|
public class MemberCommand extends ICommand2MC {
|
||||||
return false;
|
private final MemberComponent component;
|
||||||
final boolean add;
|
|
||||||
if (args[0].equalsIgnoreCase("add"))
|
public MemberCommand(MemberComponent component) {
|
||||||
add = true;
|
getManager().addParamConverter(OfflinePlayer.class, Bukkit::getOfflinePlayer, "Player not found!");
|
||||||
else if (args[0].equalsIgnoreCase("remove"))
|
this.component = component;
|
||||||
add = false;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
|
||||||
if (MainPlugin.permission == null) {
|
|
||||||
sender.sendMessage("§cError: No permission plugin found!");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
val op = Bukkit.getOfflinePlayer(args[1]);
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean add(CommandSender sender, OfflinePlayer player) {
|
||||||
|
return addRemove(sender, player, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean remove(CommandSender sender, OfflinePlayer player) {
|
||||||
|
return addRemove(sender, player, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addRemove(CommandSender sender, OfflinePlayer op, boolean add) {
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> {
|
||||||
if (!op.hasPlayedBefore()) {
|
if (!op.hasPlayedBefore()) {
|
||||||
sender.sendMessage("§cCannot find player or haven't played before.");
|
sender.sendMessage("§cCannot find player or haven't played before.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (add) {
|
if (add ? MainPlugin.permission.playerAddGroup(null, op, component.memberGroup().get())
|
||||||
if (MainPlugin.permission.playerAddGroup(null, op, "member"))
|
: MainPlugin.permission.playerRemoveGroup(null, op, component.memberGroup().get()))
|
||||||
sender.sendMessage("§b" + op.getName() + " added as a member!");
|
sender.sendMessage("§b" + op.getName() + " " + (add ? "added" : "removed") + " as a member!");
|
||||||
else
|
else
|
||||||
sender.sendMessage("§cFailed to add " + op.getName() + " as a member!");
|
sender.sendMessage("§cFailed to " + (add ? "add" : "remove") + " " + op.getName() + " as a member!");
|
||||||
} else {
|
|
||||||
if (MainPlugin.permission.playerRemoveGroup(null, op, "member"))
|
|
||||||
sender.sendMessage("§b" + op.getName() + " removed as a member!");
|
|
||||||
else
|
|
||||||
sender.sendMessage("§bFailed to remove " + op.getName() + " as a member!");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[]{ //
|
|
||||||
"06---- Member ----", //
|
|
||||||
"Add or remove server members.", //
|
|
||||||
"Usage: /member <add|remove> <player>" //
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,14 @@ import java.util.Date;
|
||||||
import static buttondevteam.core.MainPlugin.permission;
|
import static buttondevteam.core.MainPlugin.permission;
|
||||||
|
|
||||||
public class MemberComponent extends Component implements Listener {
|
public class MemberComponent extends Component implements Listener {
|
||||||
private ConfigData<String> memberGroup() {
|
ConfigData<String> memberGroup() {
|
||||||
return getConfig().getData("memberGroup", "member");
|
return getConfig().getData("memberGroup", "member");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void enable() {
|
protected void enable() {
|
||||||
registerListener(this);
|
registerListener(this);
|
||||||
registerCommand(new MemberCommand());
|
registerCommand(new MemberCommand(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -3,7 +3,7 @@ package buttondevteam.lib.architecture;
|
||||||
import buttondevteam.core.ComponentManager;
|
import buttondevteam.core.ComponentManager;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.lib.architecture.exceptions.UnregisteredComponentException;
|
import buttondevteam.lib.architecture.exceptions.UnregisteredComponentException;
|
||||||
import buttondevteam.lib.chat.ICommand2;
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
import buttondevteam.lib.chat.TBMCCommandBase;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
@ -197,7 +197,7 @@ public abstract class Component {
|
||||||
*
|
*
|
||||||
* @param commandBase Custom coded command class
|
* @param commandBase Custom coded command class
|
||||||
*/
|
*/
|
||||||
protected final void registerCommand(ICommand2 commandBase) {
|
protected final void registerCommand(ICommand2MC commandBase) {
|
||||||
ButtonPlugin.getCommand2MC().registerCommand(commandBase);
|
ButtonPlugin.getCommand2MC().registerCommand(commandBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,13 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
* The args may be null if the conversion failed and it's optional.
|
||||||
*/
|
*/
|
||||||
public abstract class Command2 {
|
public abstract class Command2<TC extends ICommand2> {
|
||||||
|
protected Command2() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: @CommandClass(helpText=...)
|
|
||||||
* Parameters annotated with this receive all of the remaining arguments
|
* Parameters annotated with this receive all of the remaining arguments
|
||||||
*/
|
*/
|
||||||
@Target(ElementType.PARAMETER)
|
@Target(ElementType.PARAMETER)
|
||||||
|
@ -46,12 +48,24 @@ public abstract class Command2 {
|
||||||
String[] helpText() default {};
|
String[] helpText() default {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface OptionalArg {
|
||||||
|
}
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
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[] helpText;
|
public final String[] helpText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
protected static class ParamConverter<T> {
|
||||||
|
public final Function<String, T> converter;
|
||||||
|
public final String errormsg;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
* The converter may return null.
|
* The converter may return null.
|
||||||
|
@ -60,20 +74,29 @@ public abstract class Command2 {
|
||||||
* @param converter The converter to use
|
* @param converter The converter to use
|
||||||
* @param <T> The type of the result
|
* @param <T> The type of the result
|
||||||
*/
|
*/
|
||||||
public abstract <T> void addParamConverter(Class<T> cl, Function<String, T> converter);
|
public abstract <T> void addParamConverter(Class<T> cl, Function<String, T> converter, String errormsg);
|
||||||
|
|
||||||
protected <T> void addParamConverter(Class<T> cl, Function<String, T> converter, HashMap<Class<?>, Function<String, ?>> map) {
|
protected <T> void addParamConverter(Class<T> cl, Function<String, T> converter, String errormsg, HashMap<Class<?>, ParamConverter<?>> map) {
|
||||||
map.put(cl, converter);
|
map.put(cl, new ParamConverter<>(converter, errormsg));
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean handleCommand(CommandSender sender, String commandLine) throws Exception;
|
public abstract boolean handleCommand(CommandSender sender, String commandLine) throws Exception;
|
||||||
|
|
||||||
protected <T extends ICommand2> boolean handleCommand(CommandSender sender, String commandline,
|
protected boolean handleCommand(CommandSender sender, String commandline,
|
||||||
HashMap<String, SubcommandData<T>> subcommands, HashMap<Class<?>, Function<String, ?>> paramConverters) throws Exception {
|
HashMap<String, SubcommandData<TC>> subcommands,
|
||||||
|
HashMap<Class<?>, ParamConverter<?>> paramConverters) throws Exception {
|
||||||
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 sd = subcommands.get(subcommand); //O(1)
|
SubcommandData<TC> sd = subcommands.get(subcommand); //O(1)
|
||||||
if (sd == null) continue; //TODO: This will run each time someone runs any command
|
if (sd == null) continue;
|
||||||
|
if (sd.method == null || sd.command == null) { //Main command not registered, but we have subcommands
|
||||||
|
sender.sendMessage(sd.helpText);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!hasPermission(sender, sd.command)) {
|
||||||
|
sender.sendMessage("§cYou don't have permission to use this command");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
val params = new ArrayList<Object>(sd.method.getParameterCount());
|
val params = new ArrayList<Object>(sd.method.getParameterCount());
|
||||||
int j = subcommand.length(), pj;
|
int j = subcommand.length(), pj;
|
||||||
Class<?>[] parameterTypes = sd.method.getParameterTypes();
|
Class<?>[] parameterTypes = sd.method.getParameterTypes();
|
||||||
|
@ -91,12 +114,18 @@ public abstract class Command2 {
|
||||||
sender.sendMessage("§cYou need to be a " + sendertype.getSimpleName() + " to use this command.");
|
sender.sendMessage("§cYou need to be a " + sendertype.getSimpleName() + " to use this command.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
val paramArr = sd.method.getParameters();
|
||||||
for (int i1 = 1; i1 < parameterTypes.length; i1++) {
|
for (int i1 = 1; i1 < parameterTypes.length; i1++) {
|
||||||
Class<?> cl = parameterTypes[i1];
|
Class<?> cl = parameterTypes[i1];
|
||||||
pj = j + 1; //Start index
|
pj = j + 1; //Start index
|
||||||
if (pj == commandline.length() + 1) { //No param given
|
if (pj == commandline.length() + 1) { //No param given
|
||||||
|
if (paramArr[i1].isAnnotationPresent(OptionalArg.class)) {
|
||||||
params.add(null);
|
params.add(null);
|
||||||
continue; //Fill the remaining params with nulls
|
continue; //Fill the remaining params with nulls
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(sd.helpText); //Required param missing
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
j = commandline.indexOf(' ', j + 1); //End index
|
j = commandline.indexOf(' ', j + 1); //End index
|
||||||
if (j == -1) //Last parameter
|
if (j == -1) //Last parameter
|
||||||
|
@ -109,7 +138,12 @@ public abstract class Command2 {
|
||||||
val conv = paramConverters.get(cl);
|
val conv = paramConverters.get(cl);
|
||||||
if (conv == null)
|
if (conv == null)
|
||||||
throw new Exception("No suitable converter found for parameter type '" + cl.getCanonicalName() + "' for command '" + sd.method.toString() + "'");
|
throw new Exception("No suitable converter found for parameter type '" + cl.getCanonicalName() + "' for command '" + sd.method.toString() + "'");
|
||||||
params.add(conv.apply(param));
|
val cparam = conv.converter.apply(param);
|
||||||
|
if (cparam == null) {
|
||||||
|
sender.sendMessage(conv.errormsg); //Param conversion failed - ex. plugin not found
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
params.add(cparam);
|
||||||
}
|
}
|
||||||
//System.out.println("Our params: "+params);
|
//System.out.println("Our params: "+params);
|
||||||
val ret = sd.method.invoke(sd.command, params.toArray()); //I FORGOT TO TURN IT INTO AN ARRAY (for a long time)
|
val ret = sd.method.invoke(sd.command, params.toArray()); //I FORGOT TO TURN IT INTO AN ARRAY (for a long time)
|
||||||
|
@ -123,21 +157,26 @@ public abstract class Command2 {
|
||||||
return false; //Didn't handle
|
return false; //Didn't handle
|
||||||
} //TODO: Add to the help
|
} //TODO: Add to the help
|
||||||
|
|
||||||
public abstract void registerCommand(ICommand2 command);
|
public abstract void registerCommand(TC command);
|
||||||
|
|
||||||
protected <T extends ICommand2> void registerCommand(T command, HashMap<String, SubcommandData<T>> subcommands, char commandChar) {
|
protected void registerCommand(TC command, HashMap<String, SubcommandData<TC>> subcommands, char commandChar) {
|
||||||
val path = command.getCommandPath();
|
val path = command.getCommandPath();
|
||||||
|
int x = path.indexOf(' ');
|
||||||
|
val mainPath = commandChar + path.substring(0, x == -1 ? path.length() : x);
|
||||||
|
//var scmdmap = subcommandStrings.computeIfAbsent(mainPath, k -> new HashSet<>()); //Used to display subcommands
|
||||||
|
val scmdHelpList = new ArrayList<String>();
|
||||||
|
Method mainMethod = null;
|
||||||
try { //Register the default handler first so it can be reliably overwritten
|
try { //Register the default handler first so it can be reliably overwritten
|
||||||
val method = command.getClass().getMethod("def", CommandSender.class, String.class);
|
mainMethod = command.getClass().getMethod("def", CommandSender.class, String.class);
|
||||||
val cc = command.getClass().getAnnotation(CommandClass.class);
|
val cc = command.getClass().getAnnotation(CommandClass.class);
|
||||||
var ht = cc == null ? new String[0] : cc.helpText();
|
var ht = cc == null ? new String[0] : cc.helpText();
|
||||||
String[] both = Arrays.copyOf(ht, ht.length + 1);
|
if (ht.length > 0)
|
||||||
both[ht.length] = "Usage: " + commandChar + path; //TODO: Print subcommands
|
ht[0] = "§6---- " + ht[0] + " ----";
|
||||||
ht = both;
|
scmdHelpList.addAll(Arrays.asList(ht));
|
||||||
subcommands.put(commandChar + path, new SubcommandData<>(method, command, ht)); //TODO: Disable components when the plugin is disabled
|
scmdHelpList.add("§6Subcommands:");
|
||||||
} 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);
|
||||||
} //Continue on
|
}
|
||||||
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) {
|
if (ann != null) {
|
||||||
|
@ -147,15 +186,22 @@ public abstract class Command2 {
|
||||||
(method.getName().equals("def") ? "" : " " + method.getName().replace('_', ' ').toLowerCase()); //Add method name, unless it's 'def'
|
(method.getName().equals("def") ? "" : " " + method.getName().replace('_', ' ').toLowerCase()); //Add method name, unless it's 'def'
|
||||||
ht = getHelpText(method, ht, subcommand);
|
ht = getHelpText(method, ht, subcommand);
|
||||||
subcommands.put(subcommand, new SubcommandData<>(method, command, ht)); //Result of the above (def) is that it will show the help text
|
subcommands.put(subcommand, new SubcommandData<>(method, command, ht)); //Result of the above (def) is that it will show the help text
|
||||||
|
scmdHelpList.add(subcommand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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])));
|
||||||
|
if (mainMethod != null && !subcommands.containsKey(mainPath)) //Main command, typically the same as the above
|
||||||
|
subcommands.put(mainPath, new SubcommandData<>(null, null, scmdHelpList.toArray(new String[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] getHelpText(Method method, String[] ht, String subcommand) { //TODO: helpText[0]="§6---- "+helpText[0]+" ----";
|
private String[] getHelpText(Method method, String[] ht, String subcommand) {
|
||||||
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!"));
|
||||||
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());
|
val ccs = yc.getConfigurationSection(method.getDeclaringClass().getCanonicalName());
|
||||||
if (ccs != null) {
|
if (ccs != null) {
|
||||||
|
@ -166,7 +212,7 @@ public abstract class Command2 {
|
||||||
val goodname = method.getName() + "(" + Arrays.stream(method.getParameterTypes()).map(cl -> cl.getCanonicalName()).collect(Collectors.joining(",")) + ")";
|
val goodname = method.getName() + "(" + Arrays.stream(method.getParameterTypes()).map(cl -> cl.getCanonicalName()).collect(Collectors.joining(",")) + ")";
|
||||||
if (goodname.equals(mname) && params != null) {
|
if (goodname.equals(mname) && params != null) {
|
||||||
String[] both = Arrays.copyOf(ht, ht.length + 1);
|
String[] both = Arrays.copyOf(ht, ht.length + 1);
|
||||||
both[ht.length] = "Usage: " + subcommand + " " + params;
|
both[ht.length] = "§6Usage:§r " + subcommand + " " + params;
|
||||||
ht = both;
|
ht = both;
|
||||||
} 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));
|
||||||
|
@ -178,5 +224,5 @@ public abstract class Command2 {
|
||||||
return ht;
|
return ht;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean hasPermission(CommandSender sender, ICommand2 command);
|
public abstract boolean hasPermission(CommandSender sender, TC command);
|
||||||
} //TODO: Test support of Player instead of CommandSender
|
} //TODO: Test support of Player instead of CommandSender
|
||||||
|
|
|
@ -1,24 +1,36 @@
|
||||||
package buttondevteam.lib.chat;
|
package buttondevteam.lib.chat;
|
||||||
|
|
||||||
|
import buttondevteam.core.MainPlugin;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class Command2MC extends Command2 {
|
public class Command2MC extends Command2<ICommand2MC> {
|
||||||
|
private HashMap<String, SubcommandData<ICommand2MC>> subcommands = new HashMap<>();
|
||||||
private HashMap<String, SubcommandData<ICommand2>> subcommands = new HashMap<>();
|
private HashMap<Class<?>, ParamConverter<?>> paramConverters = new HashMap<>();
|
||||||
private HashMap<Class<?>, Function<String, ?>> paramConverters = new HashMap<>();
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean handleCommand(CommandSender sender, String commandLine) throws Exception {
|
public boolean handleCommand(CommandSender sender, String commandLine) throws Exception {
|
||||||
return handleCommand(sender, commandLine, subcommands, paramConverters);
|
return handleCommand(sender, commandLine, subcommands, paramConverters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerCommand(ICommand2 command) {
|
@Override
|
||||||
|
public void registerCommand(ICommand2MC command) {
|
||||||
registerCommand(command, subcommands, '/');
|
registerCommand(command, subcommands, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void addParamConverter(Class<T> cl, Function<String, T> converter) {
|
@Override
|
||||||
addParamConverter(cl, converter, paramConverters);
|
public boolean hasPermission(CommandSender sender, ICommand2MC command) {
|
||||||
|
return MainPlugin.permission.has(sender, "thorpe.command." + command.getCommandPath().replace(' ', '.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically colors the message red.
|
||||||
|
* {@see super#addParamConverter}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public <T> void addParamConverter(Class<T> cl, Function<String, T> converter, String errormsg) {
|
||||||
|
addParamConverter(cl, converter, "§c" + errormsg, paramConverters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,8 @@ public @interface CommandClass {
|
||||||
boolean excludeFromPath() default false;
|
boolean excludeFromPath() default false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The help text to show for the players. A usage message will be also shown below it.
|
* The help text to show for the players. A usage message will be also shown below it.<br>
|
||||||
|
* <b>The fist line will be converted to a header.</b>
|
||||||
*
|
*
|
||||||
* @return The help text
|
* @return The help text
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -31,9 +31,9 @@ public abstract class ICommand2 {
|
||||||
|
|
||||||
private final String path;
|
private final String path;
|
||||||
@Getter
|
@Getter
|
||||||
private final Command2 manager;
|
private final Command2<?> manager; //TIL that if I use a raw type on a variable then none of the type args will work (including what's defined on a method, not on the type)
|
||||||
|
|
||||||
public ICommand2(Command2 manager) {
|
public <T extends ICommand2> ICommand2(Command2<T> manager) {
|
||||||
path = getcmdpath();
|
path = getcmdpath();
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue