mirror of
https://github.com/SimplexDevelopment/SimplexCore.git
synced 2024-12-22 08:37:37 +00:00
Update Command System
This commit is contained in:
parent
cdee236c88
commit
e617b0f87a
@ -42,7 +42,7 @@ public final class SimplexCorePlugin extends SimplexModule<SimplexCorePlugin> {
|
|||||||
public void start() {
|
public void start() {
|
||||||
try {
|
try {
|
||||||
getRegistry().register(this);
|
getRegistry().register(this);
|
||||||
getCommandLoader().classpath(Command_info.class).load(this);
|
getCommandLoader().classpath(this, Command_info.class).load();
|
||||||
getYamlConfig().reload();
|
getYamlConfig().reload();
|
||||||
getInternals().reload();
|
getInternals().reload();
|
||||||
//
|
//
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package io.github.simplexdev.simplexcore.command;
|
package io.github.simplexdev.simplexcore.command;
|
||||||
|
|
||||||
import io.github.simplexdev.api.annotations.CommandInfo;
|
import io.github.simplexdev.api.annotations.CommandInfo;
|
||||||
import io.github.simplexdev.simplexcore.command.defaults.DefaultCommand;
|
import io.github.simplexdev.simplexcore.SimplexCorePlugin;
|
||||||
import io.github.simplexdev.simplexcore.module.SimplexModule;
|
import io.github.simplexdev.simplexcore.module.SimplexModule;
|
||||||
import io.github.simplexdev.simplexcore.utils.ReflectionTools;
|
import io.github.simplexdev.simplexcore.utils.ReflectionTools;
|
||||||
import io.github.simplexdev.simplexcore.SimplexCorePlugin;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.command.CommandMap;
|
||||||
import org.bukkit.command.*;
|
import org.bukkit.command.PluginCommand;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.SimplePluginManager;
|
import org.bukkit.plugin.SimplePluginManager;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -20,7 +21,10 @@ import java.util.MissingResourceException;
|
|||||||
|
|
||||||
public final class CommandLoader {
|
public final class CommandLoader {
|
||||||
private Reflections reflections;
|
private Reflections reflections;
|
||||||
|
private ClassLoader classLoader;
|
||||||
|
private SimplexModule<?> plugin;
|
||||||
private static final CommandLoader instance = new CommandLoader();
|
private static final CommandLoader instance = new CommandLoader();
|
||||||
|
private final Registry registry = new Registry();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A Singleton Pattern instance of this class.
|
* @return A Singleton Pattern instance of this class.
|
||||||
@ -38,15 +42,15 @@ public final class CommandLoader {
|
|||||||
* If the class provided does not have the {@link CommandInfo} annotation, the loader will throw a new
|
* If the class provided does not have the {@link CommandInfo} annotation, the loader will throw a new
|
||||||
* {@link MissingResourceException} and will not load your plugin's commands.
|
* {@link MissingResourceException} and will not load your plugin's commands.
|
||||||
* If the class provided does not extend {@link SimplexCommand}, the loader will throw a new
|
* If the class provided does not extend {@link SimplexCommand}, the loader will throw a new
|
||||||
* {@link RuntimeException} and your commands will not be loaded.
|
* {@link CommandLoaderException} and your commands will not be loaded.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param clazz The command class to load from
|
* @param clazz The command class to load from
|
||||||
* @return An instance of this where the classpath has been prepared for loading the commands.
|
* @return An instance of this where the classpath has been prepared for loading the commands.
|
||||||
*/
|
*/
|
||||||
public <T extends SimplexCommand> CommandLoader classpath(Class<T> clazz) {
|
public <T extends SimplexCommand> CommandLoader classpath(SimplexModule<?> plugin, Class<T> clazz) {
|
||||||
if (clazz == null) {
|
if (clazz == null) {
|
||||||
throw new IllegalStateException("The class provided cannot be found!");
|
throw new IllegalArgumentException("The class provided cannot be found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clazz.isAnnotationPresent(CommandInfo.class)) {
|
if (!clazz.isAnnotationPresent(CommandInfo.class)) {
|
||||||
@ -54,22 +58,26 @@ public final class CommandLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!SimplexCommand.class.isAssignableFrom(clazz)) {
|
if (!SimplexCommand.class.isAssignableFrom(clazz)) {
|
||||||
throw new RuntimeException("Your command must extend SimplexCommand.class for it to be used as the reference point for loading commands.");
|
throw new CommandLoaderException("Your command must extend SimplexCommand.class for it to be used as the reference point for loading commands.");
|
||||||
}
|
}
|
||||||
|
|
||||||
reflections = ReflectionTools.reflect(clazz);
|
this.reflections = ReflectionTools.reflect(clazz);
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.classLoader = plugin.getClass().getClassLoader();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all the commands from the specified classpath.
|
* Loads all the commands from the specified classpath.
|
||||||
* This should be used immediately after {@link CommandLoader#classpath(Class)} has been called.
|
* This should be used immediately after {@link CommandLoader#classpath(SimplexModule, Class)} has been called.
|
||||||
* If used before, an exception will be thrown, and your commands will not be loaded.
|
* If used before, an exception will be thrown, and your commands will not be loaded.
|
||||||
*
|
|
||||||
* @param plugin An instance of your plugin to assign as the parent plugin for each command.
|
|
||||||
*/
|
*/
|
||||||
public void load(SimplexModule<?> plugin) {
|
public void load() {
|
||||||
|
if (reflections == null || plugin == null || classLoader == null) {
|
||||||
|
throw new CommandLoaderException("Please run CommandLoader#classpath(SimplexModule, Class) first!");
|
||||||
|
}
|
||||||
|
|
||||||
reflections.getTypesAnnotatedWith(CommandInfo.class).forEach(annotated -> {
|
reflections.getTypesAnnotatedWith(CommandInfo.class).forEach(annotated -> {
|
||||||
CommandInfo info = annotated.getDeclaredAnnotation(CommandInfo.class);
|
CommandInfo info = annotated.getDeclaredAnnotation(CommandInfo.class);
|
||||||
|
|
||||||
@ -89,7 +97,7 @@ public final class CommandLoader {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginCommand command = Registry.create(plugin, info.name().toLowerCase());
|
PluginCommand command = registry.create(plugin, info.name().toLowerCase());
|
||||||
command.setAliases(Arrays.asList(info.aliases().split(",")));
|
command.setAliases(Arrays.asList(info.aliases().split(",")));
|
||||||
command.setDescription(info.description());
|
command.setDescription(info.description());
|
||||||
command.setExecutor(getExecutorFromName(info.name()));
|
command.setExecutor(getExecutorFromName(info.name()));
|
||||||
@ -98,7 +106,7 @@ public final class CommandLoader {
|
|||||||
command.setPermissionMessage(info.permissionMessage());
|
command.setPermissionMessage(info.permissionMessage());
|
||||||
command.setTabCompleter(getTabFromName(info.name()));
|
command.setTabCompleter(getTabFromName(info.name()));
|
||||||
command.setUsage(info.usage());
|
command.setUsage(info.usage());
|
||||||
Registry.registerCommand(command);
|
registry.registerCommand(command);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,28 +118,27 @@ public final class CommandLoader {
|
|||||||
* @param name The name of the command.
|
* @param name The name of the command.
|
||||||
* @return An instance of the command class as a CommandExecutor.
|
* @return An instance of the command class as a CommandExecutor.
|
||||||
*/
|
*/
|
||||||
public CommandExecutor getExecutorFromName(String name) {
|
private CommandExecutor getExecutorFromName(String name) {
|
||||||
for (Class<? extends CommandExecutor> obj : reflections.getSubTypesOf(CommandExecutor.class)) {
|
for (Class<? extends SimplexCommand> obj : reflections.getSubTypesOf(SimplexCommand.class)) {
|
||||||
if (!obj.isAnnotationPresent(CommandInfo.class)) {
|
if (!obj.isAnnotationPresent(CommandInfo.class)) {
|
||||||
SimplexCorePlugin.getInstance()
|
plugin.getLogger().warning(obj.getSimpleName()
|
||||||
.getLogger().warning(obj.getSimpleName()
|
|
||||||
+ " is missing a required annotation: "
|
+ " is missing a required annotation: "
|
||||||
+ CommandInfo.class.getSimpleName());
|
+ CommandInfo.class.getSimpleName());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandInfo info = obj.getDeclaredAnnotation(CommandInfo.class);
|
CommandInfo info = obj.getDeclaredAnnotation(CommandInfo.class);
|
||||||
|
|
||||||
if (name.equalsIgnoreCase(info.name())) {
|
if (name.equalsIgnoreCase(info.name())) {
|
||||||
try {
|
Constructor<? extends CommandExecutor> constr =
|
||||||
Constructor<? extends CommandExecutor> constr = obj.getDeclaredConstructor();
|
ReflectionTools.getDeclaredConstructor(obj, SimplexModule.class);
|
||||||
constr.setAccessible(true);
|
if (constr == null) {
|
||||||
return constr.newInstance();
|
throw new CommandLoaderException("Constructor does not exist! Are you extending SimplexCommand properly?");
|
||||||
} catch (ReflectiveOperationException ignored) {
|
|
||||||
return new DefaultCommand();
|
|
||||||
}
|
}
|
||||||
|
return ReflectionTools.initConstructor(constr, plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Unable to assign a CommandExecutor from the provided classes!");
|
throw new CommandLoaderException("Unable to assign a CommandExecutor from the provided classes!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,52 +150,50 @@ public final class CommandLoader {
|
|||||||
* @return The command as an instance of TabCompleter
|
* @return The command as an instance of TabCompleter
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public TabCompleter getTabFromName(String name) {
|
private TabCompleter getTabFromName(String name) {
|
||||||
for (Class<? extends TabCompleter> obj : reflections.getSubTypesOf(TabCompleter.class)) {
|
for (Class<? extends SimplexCommand> obj : reflections.getSubTypesOf(SimplexCommand.class)) {
|
||||||
if (!obj.isAnnotationPresent(CommandInfo.class)) {
|
if (!obj.isAnnotationPresent(CommandInfo.class)) {
|
||||||
SimplexCorePlugin.getInstance()
|
plugin.getLogger().warning(obj.getSimpleName()
|
||||||
.getLogger().warning(obj.getSimpleName()
|
|
||||||
+ " is missing required annotation: "
|
+ " is missing required annotation: "
|
||||||
+ CommandInfo.class.getSimpleName());
|
+ CommandInfo.class.getSimpleName());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandInfo info = obj.getDeclaredAnnotation(CommandInfo.class);
|
CommandInfo info = obj.getDeclaredAnnotation(CommandInfo.class);
|
||||||
|
|
||||||
if (name.equalsIgnoreCase(info.name())) {
|
if (name.equalsIgnoreCase(info.name())) {
|
||||||
try {
|
Constructor<? extends TabCompleter> constr = ReflectionTools.getDeclaredConstructor(obj, SimplexModule.class);
|
||||||
Constructor<? extends TabCompleter> constr = obj.getDeclaredConstructor();
|
if (constr == null) {
|
||||||
constr.setAccessible(true);
|
throw new CommandLoaderException("Constructor does not exist! Are you extending SimplexCommand properly?");
|
||||||
return constr.newInstance();
|
|
||||||
} catch (ReflectiveOperationException ignored) {
|
|
||||||
return new DefaultCommand();
|
|
||||||
}
|
}
|
||||||
|
return ReflectionTools.initConstructor(constr, plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
throw new CommandLoaderException("Unable to assign a TabCompleter from the provided classes!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registry class, which forces all necessary fields to accessible.
|
* Registry class, which forces all necessary fields to accessible.
|
||||||
*/
|
*/
|
||||||
private static class Registry {
|
private final class Registry {
|
||||||
private static final Constructor<PluginCommand> constructor;
|
private final Constructor<PluginCommand> constructor;
|
||||||
private static final Field cmdMapField;
|
private final Field cmdMapField;
|
||||||
|
|
||||||
static {
|
public Registry() {
|
||||||
constructor = ReflectionTools.getDeclaredConstructor(PluginCommand.class, String.class, Plugin.class);
|
constructor = ReflectionTools.getDeclaredConstructor(PluginCommand.class, String.class, Plugin.class);
|
||||||
cmdMapField = ReflectionTools.getDeclaredField(SimplePluginManager.class, "commandMap");
|
cmdMapField = ReflectionTools.getDeclaredField(SimplePluginManager.class, "commandMap");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PluginCommand create(@NotNull Plugin plugin, @NotNull String name) {
|
public PluginCommand create(@NotNull SimplexModule<?> plugin, @NotNull String name) {
|
||||||
return ReflectionTools.initConstructor(constructor, name, plugin);
|
return ReflectionTools.initConstructor(constructor, name, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerCommand(PluginCommand command) {
|
public void registerCommand(PluginCommand command) {
|
||||||
try {
|
try {
|
||||||
CommandMap map = (CommandMap) cmdMapField.get(Bukkit.getPluginManager());
|
CommandMap map = (CommandMap) cmdMapField.get(plugin.getManager());
|
||||||
map.register(command.getName().toLowerCase(), command);
|
map.register(command.getName().toLowerCase(), command);
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
throw new RuntimeException(e);
|
throw new CommandLoaderException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package io.github.simplexdev.simplexcore.command;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||||
|
|
||||||
|
public class CommandLoaderException extends RuntimeException {
|
||||||
|
public CommandLoaderException() {
|
||||||
|
super("The Command Loader has encountered an exception and has failed to execute properly. " +
|
||||||
|
"Some commands may not be loaded.");
|
||||||
|
ExceptionUtils.getMessage(super.getCause());
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandLoaderException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandLoaderException(Throwable th) {
|
||||||
|
super(th);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package io.github.simplexdev.simplexcore.command;
|
package io.github.simplexdev.simplexcore.command;
|
||||||
|
|
||||||
import io.github.simplexdev.simplexcore.SimplexCorePlugin;
|
import io.github.simplexdev.simplexcore.SimplexCorePlugin;
|
||||||
|
import io.github.simplexdev.simplexcore.module.SimplexModule;
|
||||||
import io.github.simplexdev.simplexcore.utils.Utilities;
|
import io.github.simplexdev.simplexcore.utils.Utilities;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
@ -15,6 +16,15 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
|
public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
|
||||||
|
private final SimplexModule<?> plugin;
|
||||||
|
|
||||||
|
public SimplexCommand(SimplexModule<?> plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final SimplexModule<?> getPlugin() {
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPlayer(CommandSender sender) {
|
public boolean isPlayer(CommandSender sender) {
|
||||||
return sender instanceof Player;
|
return sender instanceof Player;
|
||||||
@ -22,6 +32,7 @@ public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an online player from their username
|
* Gets an online player from their username
|
||||||
|
*
|
||||||
* @param name The player's username
|
* @param name The player's username
|
||||||
* @return An instance of {@link Player} which represents the online player in question.
|
* @return An instance of {@link Player} which represents the online player in question.
|
||||||
*/
|
*/
|
||||||
@ -32,6 +43,7 @@ public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an online player from their {@link UUID}.
|
* Gets an online player from their {@link UUID}.
|
||||||
|
*
|
||||||
* @param uuid The player's UUID
|
* @param uuid The player's UUID
|
||||||
* @return An instance of {@link Player} which represents the online player in question.
|
* @return An instance of {@link Player} which represents the online player in question.
|
||||||
*/
|
*/
|
||||||
@ -43,6 +55,7 @@ public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
|
|||||||
/**
|
/**
|
||||||
* Gets an instance of {@link Player} based off an instance of {@link CommandSender}.
|
* Gets an instance of {@link Player} based off an instance of {@link CommandSender}.
|
||||||
* This will be null if the condition {CommandSender instanceof Player} is false.
|
* This will be null if the condition {CommandSender instanceof Player} is false.
|
||||||
|
*
|
||||||
* @param sender The CommandSender to cast
|
* @param sender The CommandSender to cast
|
||||||
* @return An instance of Player relating to CommandSender.
|
* @return An instance of Player relating to CommandSender.
|
||||||
*/
|
*/
|
||||||
@ -54,7 +67,8 @@ public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
|
|||||||
/**
|
/**
|
||||||
* Send a message or a group of messages to a {@link Player}.
|
* Send a message or a group of messages to a {@link Player}.
|
||||||
* If you want the messages to send on new lines, put \n at the end of each message to send.
|
* If you want the messages to send on new lines, put \n at the end of each message to send.
|
||||||
* @param player The Player to send a message to
|
*
|
||||||
|
* @param player The Player to send a message to
|
||||||
* @param messages The messages to send.
|
* @param messages The messages to send.
|
||||||
*/
|
*/
|
||||||
public void playerMsg(Player player, String... messages) {
|
public void playerMsg(Player player, String... messages) {
|
||||||
@ -66,7 +80,8 @@ public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
|
|||||||
/**
|
/**
|
||||||
* Send a message or a group of messages to a {@link CommandSender}
|
* Send a message or a group of messages to a {@link CommandSender}
|
||||||
* If you want the messages to send on new lines, put \n at the end of each message to send.
|
* If you want the messages to send on new lines, put \n at the end of each message to send.
|
||||||
* @param sender The CommandSender to send a message to.
|
*
|
||||||
|
* @param sender The CommandSender to send a message to.
|
||||||
* @param messages The messages to send.
|
* @param messages The messages to send.
|
||||||
*/
|
*/
|
||||||
public void msg(CommandSender sender, String... messages) {
|
public void msg(CommandSender sender, String... messages) {
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
package io.github.simplexdev.simplexcore.command.defaults;
|
package io.github.simplexdev.simplexcore.command.defaults;
|
||||||
|
|
||||||
import io.github.simplexdev.api.annotations.CommandInfo;
|
import io.github.simplexdev.api.annotations.CommandInfo;
|
||||||
|
import io.github.simplexdev.simplexcore.chat.Messages;
|
||||||
import io.github.simplexdev.simplexcore.command.SimplexCommand;
|
import io.github.simplexdev.simplexcore.command.SimplexCommand;
|
||||||
|
import io.github.simplexdev.simplexcore.module.SimplexModule;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@CommandInfo(name = "Info", description = "Gets info on this API / Library.", usage = "/<command>", permission = "simplex.core.info")
|
@CommandInfo(name = "Info", description = "Gets info on this API / Library.", usage = "/<command>", permission = "simplex.core.info")
|
||||||
public class Command_info extends SimplexCommand {
|
public class Command_info extends SimplexCommand {
|
||||||
|
|
||||||
|
public Command_info(SimplexModule<?> plugin) {
|
||||||
|
super(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
sender.sendMessage("This is an API!");
|
sender.sendMessage(Messages.DISCORD.getMessage());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,17 @@ package io.github.simplexdev.simplexcore.command.defaults;
|
|||||||
|
|
||||||
import io.github.simplexdev.api.annotations.CommandInfo;
|
import io.github.simplexdev.api.annotations.CommandInfo;
|
||||||
import io.github.simplexdev.simplexcore.command.SimplexCommand;
|
import io.github.simplexdev.simplexcore.command.SimplexCommand;
|
||||||
|
import io.github.simplexdev.simplexcore.module.SimplexModule;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@CommandInfo(name = "default", usage = "/<command>", description = "Default plugin command.")
|
@CommandInfo(name = "default", usage = "/<command>", description = "Default plugin command.")
|
||||||
public final class DefaultCommand extends SimplexCommand {
|
public final class DefaultCommand extends SimplexCommand {
|
||||||
|
public DefaultCommand(SimplexModule<?> plugin) {
|
||||||
|
super(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
sender.sendMessage("If you are seeing this when running your command, your command didn't register properly.");
|
sender.sendMessage("If you are seeing this when running your command, your command didn't register properly.");
|
||||||
|
Loading…
Reference in New Issue
Block a user