mirror of
https://github.com/SimplexDevelopment/SimplexCore.git
synced 2024-12-22 00:37:36 +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() {
|
||||
try {
|
||||
getRegistry().register(this);
|
||||
getCommandLoader().classpath(Command_info.class).load(this);
|
||||
getCommandLoader().classpath(this, Command_info.class).load();
|
||||
getYamlConfig().reload();
|
||||
getInternals().reload();
|
||||
//
|
||||
|
@ -1,12 +1,13 @@
|
||||
package io.github.simplexdev.simplexcore.command;
|
||||
|
||||
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.utils.ReflectionTools;
|
||||
import io.github.simplexdev.simplexcore.SimplexCorePlugin;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.*;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.SimplePluginManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -20,7 +21,10 @@ import java.util.MissingResourceException;
|
||||
|
||||
public final class CommandLoader {
|
||||
private Reflections reflections;
|
||||
private ClassLoader classLoader;
|
||||
private SimplexModule<?> plugin;
|
||||
private static final CommandLoader instance = new CommandLoader();
|
||||
private final Registry registry = new Registry();
|
||||
|
||||
/**
|
||||
* @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
|
||||
* {@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
|
||||
* {@link RuntimeException} and your commands will not be loaded.
|
||||
* {@link CommandLoaderException} and your commands will not be loaded.
|
||||
* </p>
|
||||
*
|
||||
* @param clazz The command class to load from
|
||||
* @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) {
|
||||
throw new IllegalStateException("The class provided cannot be found!");
|
||||
throw new IllegalArgumentException("The class provided cannot be found!");
|
||||
}
|
||||
|
||||
if (!clazz.isAnnotationPresent(CommandInfo.class)) {
|
||||
@ -54,22 +58,26 @@ public final class CommandLoader {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @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 -> {
|
||||
CommandInfo info = annotated.getDeclaredAnnotation(CommandInfo.class);
|
||||
|
||||
@ -89,7 +97,7 @@ public final class CommandLoader {
|
||||
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.setDescription(info.description());
|
||||
command.setExecutor(getExecutorFromName(info.name()));
|
||||
@ -98,7 +106,7 @@ public final class CommandLoader {
|
||||
command.setPermissionMessage(info.permissionMessage());
|
||||
command.setTabCompleter(getTabFromName(info.name()));
|
||||
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.
|
||||
* @return An instance of the command class as a CommandExecutor.
|
||||
*/
|
||||
public CommandExecutor getExecutorFromName(String name) {
|
||||
for (Class<? extends CommandExecutor> obj : reflections.getSubTypesOf(CommandExecutor.class)) {
|
||||
private CommandExecutor getExecutorFromName(String name) {
|
||||
for (Class<? extends SimplexCommand> obj : reflections.getSubTypesOf(SimplexCommand.class)) {
|
||||
if (!obj.isAnnotationPresent(CommandInfo.class)) {
|
||||
SimplexCorePlugin.getInstance()
|
||||
.getLogger().warning(obj.getSimpleName()
|
||||
plugin.getLogger().warning(obj.getSimpleName()
|
||||
+ " is missing a required annotation: "
|
||||
+ CommandInfo.class.getSimpleName());
|
||||
continue;
|
||||
}
|
||||
|
||||
CommandInfo info = obj.getDeclaredAnnotation(CommandInfo.class);
|
||||
|
||||
if (name.equalsIgnoreCase(info.name())) {
|
||||
try {
|
||||
Constructor<? extends CommandExecutor> constr = obj.getDeclaredConstructor();
|
||||
constr.setAccessible(true);
|
||||
return constr.newInstance();
|
||||
} catch (ReflectiveOperationException ignored) {
|
||||
return new DefaultCommand();
|
||||
Constructor<? extends CommandExecutor> constr =
|
||||
ReflectionTools.getDeclaredConstructor(obj, SimplexModule.class);
|
||||
if (constr == null) {
|
||||
throw new CommandLoaderException("Constructor does not exist! Are you extending SimplexCommand properly?");
|
||||
}
|
||||
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
|
||||
*/
|
||||
@Nullable
|
||||
public TabCompleter getTabFromName(String name) {
|
||||
for (Class<? extends TabCompleter> obj : reflections.getSubTypesOf(TabCompleter.class)) {
|
||||
private TabCompleter getTabFromName(String name) {
|
||||
for (Class<? extends SimplexCommand> obj : reflections.getSubTypesOf(SimplexCommand.class)) {
|
||||
if (!obj.isAnnotationPresent(CommandInfo.class)) {
|
||||
SimplexCorePlugin.getInstance()
|
||||
.getLogger().warning(obj.getSimpleName()
|
||||
plugin.getLogger().warning(obj.getSimpleName()
|
||||
+ " is missing required annotation: "
|
||||
+ CommandInfo.class.getSimpleName());
|
||||
continue;
|
||||
}
|
||||
|
||||
CommandInfo info = obj.getDeclaredAnnotation(CommandInfo.class);
|
||||
|
||||
if (name.equalsIgnoreCase(info.name())) {
|
||||
try {
|
||||
Constructor<? extends TabCompleter> constr = obj.getDeclaredConstructor();
|
||||
constr.setAccessible(true);
|
||||
return constr.newInstance();
|
||||
} catch (ReflectiveOperationException ignored) {
|
||||
return new DefaultCommand();
|
||||
Constructor<? extends TabCompleter> constr = ReflectionTools.getDeclaredConstructor(obj, SimplexModule.class);
|
||||
if (constr == null) {
|
||||
throw new CommandLoaderException("Constructor does not exist! Are you extending SimplexCommand properly?");
|
||||
}
|
||||
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.
|
||||
*/
|
||||
private static class Registry {
|
||||
private static final Constructor<PluginCommand> constructor;
|
||||
private static final Field cmdMapField;
|
||||
private final class Registry {
|
||||
private final Constructor<PluginCommand> constructor;
|
||||
private final Field cmdMapField;
|
||||
|
||||
static {
|
||||
public Registry() {
|
||||
constructor = ReflectionTools.getDeclaredConstructor(PluginCommand.class, String.class, Plugin.class);
|
||||
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);
|
||||
}
|
||||
|
||||
public static void registerCommand(PluginCommand command) {
|
||||
public void registerCommand(PluginCommand command) {
|
||||
try {
|
||||
CommandMap map = (CommandMap) cmdMapField.get(Bukkit.getPluginManager());
|
||||
CommandMap map = (CommandMap) cmdMapField.get(plugin.getManager());
|
||||
map.register(command.getName().toLowerCase(), command);
|
||||
} 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;
|
||||
|
||||
import io.github.simplexdev.simplexcore.SimplexCorePlugin;
|
||||
import io.github.simplexdev.simplexcore.module.SimplexModule;
|
||||
import io.github.simplexdev.simplexcore.utils.Utilities;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
@ -15,6 +16,15 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
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) {
|
||||
return sender instanceof Player;
|
||||
@ -22,6 +32,7 @@ public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
|
||||
|
||||
/**
|
||||
* Gets an online player from their username
|
||||
*
|
||||
* @param name The player's username
|
||||
* @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}.
|
||||
*
|
||||
* @param uuid The player's UUID
|
||||
* @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}.
|
||||
* This will be null if the condition {CommandSender instanceof Player} is false.
|
||||
*
|
||||
* @param sender The CommandSender to cast
|
||||
* @return An instance of Player relating to CommandSender.
|
||||
*/
|
||||
@ -54,6 +67,7 @@ public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param player The Player to send a message to
|
||||
* @param messages The messages to send.
|
||||
*/
|
||||
@ -66,6 +80,7 @@ public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param sender The CommandSender to send a message to.
|
||||
* @param messages The messages to send.
|
||||
*/
|
||||
|
@ -1,16 +1,23 @@
|
||||
package io.github.simplexdev.simplexcore.command.defaults;
|
||||
|
||||
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.module.SimplexModule;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@CommandInfo(name = "Info", description = "Gets info on this API / Library.", usage = "/<command>", permission = "simplex.core.info")
|
||||
public class Command_info extends SimplexCommand {
|
||||
|
||||
public Command_info(SimplexModule<?> plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,17 @@ package io.github.simplexdev.simplexcore.command.defaults;
|
||||
|
||||
import io.github.simplexdev.api.annotations.CommandInfo;
|
||||
import io.github.simplexdev.simplexcore.command.SimplexCommand;
|
||||
import io.github.simplexdev.simplexcore.module.SimplexModule;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@CommandInfo(name = "default", usage = "/<command>", description = "Default plugin command.")
|
||||
public final class DefaultCommand extends SimplexCommand {
|
||||
public DefaultCommand(SimplexModule<?> plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
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.");
|
||||
|
Loading…
Reference in New Issue
Block a user