New command system improvements, broadcast toggles, config fixes #62
10 changed files with 137 additions and 90 deletions
|
@ -2,6 +2,7 @@ package buttondevteam.core;
|
|||
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.Command2.Subcommand;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
|
@ -13,29 +14,27 @@ import org.bukkit.plugin.Plugin;
|
|||
import java.util.Optional;
|
||||
|
||||
@CommandClass(modOnly = true, helpText = {
|
||||
"§6---- Component command ----",
|
||||
"Component command",
|
||||
"Can be used to enable/disable/list components"
|
||||
})
|
||||
public class ComponentCommand extends ICommand2MC {
|
||||
public ComponentCommand() {
|
||||
getManager().addParamConverter(Plugin.class, arg -> Bukkit.getPluginManager().getPlugin(arg));
|
||||
getManager().addParamConverter(Plugin.class, arg -> Bukkit.getPluginManager().getPlugin(arg), "Plugin not found!");
|
||||
}
|
||||
|
||||
@Subcommand
|
||||
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
|
||||
return enable_disable(sender, plugin, component, true);
|
||||
}
|
||||
|
||||
@Subcommand
|
||||
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);
|
||||
}
|
||||
|
||||
@Subcommand
|
||||
public boolean list(CommandSender sender, String plugin) {
|
||||
public boolean list(CommandSender sender, @Command2.OptionalArg String plugin) {
|
||||
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
|
||||
.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.ConfigData;
|
||||
import buttondevteam.lib.chat.Color;
|
||||
import buttondevteam.lib.chat.Command2MC;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import buttondevteam.lib.player.ChromaGamerBase;
|
||||
import buttondevteam.lib.player.TBMCPlayer;
|
||||
|
@ -30,7 +29,6 @@ import org.bukkit.entity.Player;
|
|||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -42,7 +40,6 @@ import java.util.logging.Logger;
|
|||
|
||||
public class MainPlugin extends ButtonPlugin {
|
||||
public static MainPlugin Instance;
|
||||
@Nullable
|
||||
public static Permission permission;
|
||||
public static boolean Test;
|
||||
public static Essentials ess;
|
||||
|
@ -59,7 +56,8 @@ public class MainPlugin extends ButtonPlugin {
|
|||
Instance = this;
|
||||
PluginDescriptionFile pdf = getDescription();
|
||||
logger = getLogger();
|
||||
setupPermissions();
|
||||
if (!setupPermissions())
|
||||
throw new NullPointerException("No permission plugin found!");
|
||||
Test = getConfig().getBoolean("test", true);
|
||||
saveConfig();
|
||||
Component.registerComponent(this, new PluginUpdaterComponent());
|
||||
|
@ -69,7 +67,7 @@ public class MainPlugin extends ButtonPlugin {
|
|||
Component.registerComponent(this, new MemberComponent());
|
||||
Component.registerComponent(this, new TownyComponent());
|
||||
ComponentManager.enableComponents();
|
||||
Command2MC.registerCommand(new ComponentCommand());
|
||||
getCommand2MC().registerCommand(new ComponentCommand());
|
||||
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this);
|
||||
ChromaGamerBase.addConverter(commandSender -> Optional.ofNullable(commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender
|
||||
? 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.TBMCCoreAPI;
|
||||
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||
import buttondevteam.lib.chat.Command2MC;
|
||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
|
@ -64,7 +64,7 @@ public class PlayerListener implements Listener {
|
|||
public void onTBMCPreprocess(TBMCCommandPreprocessEvent event) {
|
||||
if (event.isCancelled()) return;
|
||||
try {
|
||||
event.setCancelled(Command2MC.handleCommand(event.getSender(), event.getMessage()));
|
||||
event.setCancelled(ButtonPlugin.getCommand2MC().handleCommand(event.getSender(), event.getMessage()));
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Command processing failed for sender '" + event.getSender() + "' and message '" + event.getMessage() + "'", e);
|
||||
}
|
||||
|
|
|
@ -1,56 +1,47 @@
|
|||
package buttondevteam.core.component.members;
|
||||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
||||
import lombok.val;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@CommandClass(modOnly = true, path = "member")
|
||||
public class MemberCommand extends TBMCCommandBase {
|
||||
@Override
|
||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
||||
if (args.length < 2)
|
||||
return false;
|
||||
final boolean add;
|
||||
if (args[0].equalsIgnoreCase("add"))
|
||||
add = true;
|
||||
else if (args[0].equalsIgnoreCase("remove"))
|
||||
add = false;
|
||||
else
|
||||
return false;
|
||||
@CommandClass(modOnly = true, path = "member", helpText = { //
|
||||
"Member command", //
|
||||
"Add or remove server members.", //
|
||||
})
|
||||
public class MemberCommand extends ICommand2MC {
|
||||
private final MemberComponent component;
|
||||
|
||||
public MemberCommand(MemberComponent component) {
|
||||
getManager().addParamConverter(OfflinePlayer.class, Bukkit::getOfflinePlayer, "Player not found!");
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
@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 (MainPlugin.permission == null) {
|
||||
sender.sendMessage("§cError: No permission plugin found!");
|
||||
return;
|
||||
}
|
||||
val op = Bukkit.getOfflinePlayer(args[1]);
|
||||
if (!op.hasPlayedBefore()) {
|
||||
sender.sendMessage("§cCannot find player or haven't played before.");
|
||||
return;
|
||||
}
|
||||
if (add) {
|
||||
if (MainPlugin.permission.playerAddGroup(null, op, "member"))
|
||||
sender.sendMessage("§b" + op.getName() + " added as a member!");
|
||||
else
|
||||
sender.sendMessage("§cFailed to add " + 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!");
|
||||
}
|
||||
if (add ? MainPlugin.permission.playerAddGroup(null, op, component.memberGroup().get())
|
||||
: MainPlugin.permission.playerRemoveGroup(null, op, component.memberGroup().get()))
|
||||
sender.sendMessage("§b" + op.getName() + " " + (add ? "added" : "removed") + " as a member!");
|
||||
else
|
||||
sender.sendMessage("§cFailed to " + (add ? "add" : "remove") + " " + op.getName() + " as a member!");
|
||||
});
|
||||
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;
|
||||
|
||||
public class MemberComponent extends Component implements Listener {
|
||||
private ConfigData<String> memberGroup() {
|
||||
ConfigData<String> memberGroup() {
|
||||
return getConfig().getData("memberGroup", "member");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void enable() {
|
||||
registerListener(this);
|
||||
registerCommand(new MemberCommand());
|
||||
registerCommand(new MemberCommand(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,7 +3,7 @@ package buttondevteam.lib.architecture;
|
|||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
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.TBMCCommandBase;
|
||||
import lombok.Getter;
|
||||
|
@ -197,7 +197,7 @@ public abstract class Component {
|
|||
*
|
||||
* @param commandBase Custom coded command class
|
||||
*/
|
||||
protected final void registerCommand(ICommand2 commandBase) {
|
||||
protected final void registerCommand(ICommand2MC 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 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
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
|
@ -46,12 +48,24 @@ public abstract class Command2 {
|
|||
String[] helpText() default {};
|
||||
}
|
||||
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface OptionalArg {
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
protected static class SubcommandData<T extends ICommand2> {
|
||||
public final Method method;
|
||||
public final T command;
|
||||
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.
|
||||
* The converter may return null.
|
||||
|
@ -60,20 +74,29 @@ public abstract class Command2 {
|
|||
* @param converter The converter to use
|
||||
* @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) {
|
||||
map.put(cl, converter);
|
||||
protected <T> void addParamConverter(Class<T> cl, Function<String, T> converter, String errormsg, HashMap<Class<?>, ParamConverter<?>> map) {
|
||||
map.put(cl, new ParamConverter<>(converter, errormsg));
|
||||
}
|
||||
|
||||
public abstract boolean handleCommand(CommandSender sender, String commandLine) throws Exception;
|
||||
|
||||
protected <T extends ICommand2> boolean handleCommand(CommandSender sender, String commandline,
|
||||
HashMap<String, SubcommandData<T>> subcommands, HashMap<Class<?>, Function<String, ?>> paramConverters) throws Exception {
|
||||
protected boolean handleCommand(CommandSender sender, String commandline,
|
||||
HashMap<String, SubcommandData<TC>> subcommands,
|
||||
HashMap<Class<?>, ParamConverter<?>> paramConverters) throws Exception {
|
||||
for (int i = commandline.length(); i != -1; i = commandline.lastIndexOf(' ', i - 1)) {
|
||||
String subcommand = commandline.substring(0, i).toLowerCase();
|
||||
SubcommandData sd = subcommands.get(subcommand); //O(1)
|
||||
if (sd == null) continue; //TODO: This will run each time someone runs any command
|
||||
SubcommandData<TC> sd = subcommands.get(subcommand); //O(1)
|
||||
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());
|
||||
int j = subcommand.length(), pj;
|
||||
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.");
|
||||
return true;
|
||||
}
|
||||
val paramArr = sd.method.getParameters();
|
||||
for (int i1 = 1; i1 < parameterTypes.length; i1++) {
|
||||
Class<?> cl = parameterTypes[i1];
|
||||
pj = j + 1; //Start index
|
||||
if (pj == commandline.length() + 1) { //No param given
|
||||
params.add(null);
|
||||
continue; //Fill the remaining params with nulls
|
||||
if (paramArr[i1].isAnnotationPresent(OptionalArg.class)) {
|
||||
params.add(null);
|
||||
continue; //Fill the remaining params with nulls
|
||||
} else {
|
||||
sender.sendMessage(sd.helpText); //Required param missing
|
||||
return true;
|
||||
}
|
||||
}
|
||||
j = commandline.indexOf(' ', j + 1); //End index
|
||||
if (j == -1) //Last parameter
|
||||
|
@ -109,7 +138,12 @@ public abstract class Command2 {
|
|||
val conv = paramConverters.get(cl);
|
||||
if (conv == null)
|
||||
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);
|
||||
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
|
||||
} //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();
|
||||
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
|
||||
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);
|
||||
var ht = cc == null ? new String[0] : cc.helpText();
|
||||
String[] both = Arrays.copyOf(ht, ht.length + 1);
|
||||
both[ht.length] = "Usage: " + commandChar + path; //TODO: Print subcommands
|
||||
ht = both;
|
||||
subcommands.put(commandChar + path, new SubcommandData<>(method, command, ht)); //TODO: Disable components when the plugin is disabled
|
||||
if (ht.length > 0)
|
||||
ht[0] = "§6---- " + ht[0] + " ----";
|
||||
scmdHelpList.addAll(Arrays.asList(ht));
|
||||
scmdHelpList.add("§6Subcommands:");
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Could not register default handler for command /" + path, e);
|
||||
} //Continue on
|
||||
}
|
||||
for (val method : command.getClass().getMethods()) {
|
||||
val ann = method.getAnnotation(Subcommand.class);
|
||||
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'
|
||||
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
|
||||
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");
|
||||
if (str == null)
|
||||
TBMCCoreAPI.SendException("Error while getting command data!", new Exception("Resource not found!"));
|
||||
else {
|
||||
if (ht.length > 0)
|
||||
ht[0] = "§6---- " + ht[0] + " ----";
|
||||
YamlConfiguration yc = YamlConfiguration.loadConfiguration(new InputStreamReader(str)); //Generated by ButtonProcessor
|
||||
val ccs = yc.getConfigurationSection(method.getDeclaringClass().getCanonicalName());
|
||||
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(",")) + ")";
|
||||
if (goodname.equals(mname) && params != null) {
|
||||
String[] both = Arrays.copyOf(ht, ht.length + 1);
|
||||
both[ht.length] = "Usage: " + subcommand + " " + params;
|
||||
both[ht.length] = "§6Usage:§r " + subcommand + " " + params;
|
||||
ht = both;
|
||||
} else
|
||||
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;
|
||||
}
|
||||
|
||||
public abstract boolean hasPermission(CommandSender sender, ICommand2 command);
|
||||
public abstract boolean hasPermission(CommandSender sender, TC command);
|
||||
} //TODO: Test support of Player instead of CommandSender
|
||||
|
|
|
@ -1,24 +1,36 @@
|
|||
package buttondevteam.lib.chat;
|
||||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class Command2MC extends Command2 {
|
||||
|
||||
private HashMap<String, SubcommandData<ICommand2>> subcommands = new HashMap<>();
|
||||
private HashMap<Class<?>, Function<String, ?>> paramConverters = new HashMap<>();
|
||||
public class Command2MC extends Command2<ICommand2MC> {
|
||||
private HashMap<String, SubcommandData<ICommand2MC>> subcommands = new HashMap<>();
|
||||
private HashMap<Class<?>, ParamConverter<?>> paramConverters = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public boolean handleCommand(CommandSender sender, String commandLine) throws Exception {
|
||||
return handleCommand(sender, commandLine, subcommands, paramConverters);
|
||||
}
|
||||
|
||||
public void registerCommand(ICommand2 command) {
|
||||
@Override
|
||||
public void registerCommand(ICommand2MC command) {
|
||||
registerCommand(command, subcommands, '/');
|
||||
}
|
||||
|
||||
public <T> void addParamConverter(Class<T> cl, Function<String, T> converter) {
|
||||
addParamConverter(cl, converter, paramConverters);
|
||||
@Override
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -31,9 +31,9 @@ public abstract class ICommand2 {
|
|||
|
||||
private final String path;
|
||||
@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();
|
||||
this.manager = manager;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue