Core/src/main/java/eu/univento/core/api/command/CommandFramework.java

225 lines
10 KiB
Java

/*
* Copyright (c) 2017 univento.eu - All rights reserved
* You are not allowed to use, distribute or modify this code
*/
package eu.univento.core.api.command;
import eu.univento.commons.player.rank.Group;
import eu.univento.commons.player.rank.Rank;
import eu.univento.commons.server.ServerType;
import eu.univento.core.api.player.CustomPlayer;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.help.GenericCommandHelpTopic;
import org.bukkit.help.HelpTopic;
import org.bukkit.help.HelpTopicComparator;
import org.bukkit.help.IndexHelpTopic;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.SimplePluginManager;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
/**
* Command Framework - CommandFramework <br>
* The main command framework class used for controlling the framework.
*
* @author minnymin3, joethei
*/
public class CommandFramework implements CommandExecutor {
private Map<String, Map.Entry<Method, Object>> commandMap = new HashMap<>();
private CommandMap map;
private Plugin plugin;
/**
* Initializes the command framework and sets up the command maps
*/
public CommandFramework(Plugin plugin) {
this.plugin = plugin;
if (plugin.getServer().getPluginManager() instanceof SimplePluginManager) {
SimplePluginManager manager = (SimplePluginManager) plugin.getServer().getPluginManager();
try {
Field field = SimplePluginManager.class.getDeclaredField("commandMap");
field.setAccessible(true);
map = (CommandMap) field.get(manager);
} catch (IllegalArgumentException | SecurityException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
@Override
public boolean onCommand(CommandSender sender, org.bukkit.command.Command cmd, String label, String[] args) {
return handleCommand(sender, cmd, label, args);
}
/**
* Handles commands. Used in the onCommand method in your JavaPlugin class
*
* @param sender The {@link org.bukkit.command.CommandSender} parsed from
* onCommand
* @param cmd The {@link org.bukkit.command.Command} parsed from onCommand
* @param label The label parsed from onCommand
* @param args The arguments parsed from onCommand
* @return Always returns true for simplicity's sake in onCommand
*/
public boolean handleCommand(CommandSender sender, org.bukkit.command.Command cmd, String label, String[] args) {
for (int i = args.length; i >= 0; i--) {
StringBuilder buffer = new StringBuilder();
buffer.append(label.toLowerCase());
for (int x = 0; x < i; x++) {
buffer.append(".").append(args[x].toLowerCase());
}
String cmdLabel = buffer.toString();
if (commandMap.containsKey(cmdLabel)) {
Method method = commandMap.get(cmdLabel).getKey();
Object methodObject = commandMap.get(cmdLabel).getValue();
Command command = method.getAnnotation(Command.class);
CustomPlayer player = CustomPlayer.getPlayer((Player) sender);
if (Objects.equals(command.group(), Group.None) && !Objects.equals(command.rank(), Rank.Player) && !player.getDatabasePlayer().isAllowed(command.rank())) {
sender.sendMessage(command.notAllowed());
return true;
}
if (Objects.equals(command.rank(), Rank.Player) && !Objects.equals(command.group(), Group.None) && !player.getDatabasePlayer().isAllowed(command.group())) {
sender.sendMessage(command.notAllowed());
return true;
}
if (command.inGameOnly() && sender == null) {
sender.sendMessage("This command is only performable in game");
return true;
}
if (command.serverType() != ServerType.NONE && command.serverType() != ServerType.getServerType()) {
sender.sendMessage("This command can only be performed on " + command.serverType().getName() + " servers");
return true;
}
try {
method.invoke(methodObject, new CommandArgs(sender, cmd, label, args,
cmdLabel.split("\\.").length - 1));
} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return true;
}
}
defaultCommand(new CommandArgs(sender, cmd, label, args, 0));
return true;
}
/**
* Registers all command and completer methods inside of the object. Similar
* to Bukkit's registerEvents method.
*
* @param obj The object to register the commands of
*/
public void registerCommands(Object obj) {
for (Method m : obj.getClass().getMethods()) {
if (m.getAnnotation(Command.class) != null) {
Command command = m.getAnnotation(Command.class);
if (m.getParameterTypes().length > 1 || m.getParameterTypes()[0] != CommandArgs.class) {
System.out.println("Unable to register command " + m.getName() + ". Unexpected method arguments");
continue;
}
registerCommand(command, command.name(), m, obj);
for (String alias : command.aliases()) {
registerCommand(command, alias, m, obj);
}
} else if (m.getAnnotation(Completer.class) != null) {
Completer comp = m.getAnnotation(Completer.class);
if (m.getParameterTypes().length > 1 || m.getParameterTypes().length == 0
|| m.getParameterTypes()[0] != CommandArgs.class) {
System.out.println("Unable to register tab completer " + m.getName()
+ ". Unexpected method arguments");
continue;
}
if (m.getReturnType() != List.class) {
System.out.println("Unable to register tab completer " + m.getName() + ". Unexpected return type");
continue;
}
registerCompleter(comp.name(), m, obj);
for (String alias : comp.aliases()) {
registerCompleter(alias, m, obj);
}
}
}
}
/**
* Registers all the commands under the plugin's help
*/
public void registerHelp() {
Set<HelpTopic> help = new TreeSet<>(HelpTopicComparator.helpTopicComparatorInstance());
for (String s : commandMap.keySet()) {
if (!s.contains(".")) {
org.bukkit.command.Command cmd = map.getCommand(s);
HelpTopic topic = new GenericCommandHelpTopic(cmd);
help.add(topic);
}
}
IndexHelpTopic topic = new IndexHelpTopic(plugin.getName(), "All commands for " + plugin.getName(), null, help,
"Below is a list of all " + plugin.getName() + " commands:");
Bukkit.getServer().getHelpMap().addTopic(topic);
}
public void registerCommand(Command command, String label, Method m, Object obj) {
commandMap.put(label.toLowerCase(), new AbstractMap.SimpleEntry<>(m, obj));
commandMap.put(this.plugin.getName() + ':' + label.toLowerCase(), new AbstractMap.SimpleEntry<>(m, obj));
String cmdLabel = label.split("\\.")[0].toLowerCase();
if (map.getCommand(cmdLabel) == null) {
org.bukkit.command.Command cmd = new BukkitCommand(cmdLabel, this, plugin);
map.register(plugin.getName(), cmd);
}
if (!command.description().equalsIgnoreCase("") && Objects.equals(cmdLabel, label)) {
map.getCommand(cmdLabel).setDescription(command.description());
}
if (!command.usage().equalsIgnoreCase("") && Objects.equals(cmdLabel, label)) {
map.getCommand(cmdLabel).setUsage(command.usage());
}
}
public void registerCompleter(String label, Method m, Object obj) {
String cmdLabel = label.split("\\.")[0].toLowerCase();
if (map.getCommand(cmdLabel) == null) {
org.bukkit.command.Command command = new BukkitCommand(cmdLabel, this, plugin);
map.register(plugin.getName(), command);
}
if (map.getCommand(cmdLabel) instanceof BukkitCommand) {
BukkitCommand command = (BukkitCommand) map.getCommand(cmdLabel);
if (command.completer == null) {
command.completer = new BukkitCompleter();
}
command.completer.addCompleter(label, m, obj);
} else if (map.getCommand(cmdLabel) instanceof PluginCommand) {
try {
Object command = map.getCommand(cmdLabel);
Field field = command.getClass().getDeclaredField("completer");
field.setAccessible(true);
if (field.get(command) == null) {
BukkitCompleter completer = new BukkitCompleter();
completer.addCompleter(label, m, obj);
field.set(command, completer);
} else if (field.get(command) instanceof BukkitCompleter) {
BukkitCompleter completer = (BukkitCompleter) field.get(command);
completer.addCompleter(label, m, obj);
} else {
System.out.println("Unable to register tab completer " + m.getName()
+ ". A tab completer is already registered for that command!");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
private void defaultCommand(CommandArgs args) {
args.getSender().sendMessage(args.getLabel() + " is not handled! Oh noes!");
}
}