net.badbird5907.blib.command.CommandFramework Maven / Gradle / Ivy
package net.badbird5907.blib.command;
import lombok.Getter;
import net.badbird5907.blib.bLib;
import net.badbird5907.blib.util.Cooldown;
import net.badbird5907.blib.util.ReflectionUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
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.permissions.Permission;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.SimplePluginManager;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.Map.Entry;
/**
* Command Framework - CommandFramework
* The main command framework class used for controlling the framework.
*
* @author minnymin3
*
*/
public class CommandFramework implements CommandExecutor {
private Map> commandMap = new HashMap<>();
private Map otherMap = new HashMap<>();
private CommandMap map;
private Plugin plugin;
private static CommandFramework instance;
public static CommandFramework getInstance() {
return instance;
}
/**
* Initializes the command framework and sets up the command maps
* @param plugin {@link Plugin}
*/
public CommandFramework(Plugin plugin) {
this.plugin = plugin;
instance = this;
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 | NoSuchFieldException | IllegalAccessException | SecurityException 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 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--) {
StringBuffer buffer = new StringBuffer();
buffer.append(label.toLowerCase());
for (int x = 0; x < i; x++) buffer.append("." + args[x].toLowerCase());
String cmdLabel = buffer.toString().replaceFirst(plugin.getDescription().getName().toLowerCase() + ":","").replaceFirst("/" + plugin.getDescription().getName().toLowerCase() + ":","");
if (commandMap.containsKey(cmdLabel)) {
Method method = commandMap.get(cmdLabel).getKey();
Object methodObject = commandMap.get(cmdLabel).getValue();
Command command = method.getAnnotation(Command.class);
if (!command.permission().equals(""))
if (!sender.hasPermission(command.permission())) {
sender.sendMessage(ChatColor.RED + "You do not have permission to execute this command!");
return true;
}
if (command.playerOnly()) {
if(!(sender instanceof Player)){
sender.sendMessage(ChatColor.RED + "This command is player only!");
return true;
}
}
//if(command.argLength() > args.length){}
if(command.cooldown() >= 1){
if(sender instanceof Player){
Player p = (Player) sender;
//They are currently on cooldown
if(Cooldown.isOnCooldown(command.name() + "|cmd_cooldown", p.getUniqueId())){
p.sendMessage(ChatColor.RED + "You are currently on cooldown for this command! You may try again in " + ChatColor.GOLD + Cooldown.getCooldownForPlayerInt(command.name() + "|cmd_cooldown",p.getUniqueId()));
return true;
}
//They used to have a cooldown
if(Cooldown.wasOnCooldown(command.name() + "|cmd_cooldown", p.getUniqueId())){
//remove that cooldown
Cooldown.removeCooldown(command.name() + "|cmd_cooldown",p.getUniqueId());
}
//Create a new cooldown for that
}
}
try {
CommandResult result = (CommandResult) method.invoke(methodObject, new Sender(sender), args);
if(result == CommandResult.SUCCESS)
return true;
if (result == CommandResult.INVALID_ARGS){
sender.sendMessage(ChatColor.RED + "Usage: /" + command.name() + " " + ChatColor.translateAlternateColorCodes('&',command.usage().replace("Usage: /" + command.name() + " ","")));
return true;
}
else if(result == null){
return true;
}
else if(result.getMsg() == "" || result.getMsg() == " "){
return true;
}else if(result.getMsg() == null){
return true;
} else{
sender.sendMessage(result.getMsg());
return true;
}
} catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return true;
}
}
sender.sendMessage(ChatColor.RED + "Unhandled command! Please report this to the plugin author! (With the stack trace that has been printed in console.)");
Thread.dumpStack();
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 > 2 || m.getParameterTypes()[0] != Sender.class || m.getParameterTypes()[1] != String[].class) {
Bukkit.getLogger().severe("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 > 2 || m.getParameterTypes().length == 0
|| m.getParameterTypes()[0] != Sender.class || m.getParameterTypes()[1] != String[].class) {
Bukkit.getLogger().severe("Unable to register tab completer \"" + m.getName() + "\". Unexpected method arguments");
continue;
}
if (m.getReturnType() != List.class) {
Bukkit.getLogger().severe("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 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) {
if(command.disable())
return;
otherMap.put(label.toLowerCase(),command);
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.cooldown() >= 1){
if(!Cooldown.cooldownExists(command.name() + "|cmd_cooldown")){ //make sure that we're only registering 1 cooldown, use command.name(); and not label because label could be a alias
Cooldown.createCooldown(command.name() + "|cmd_cooldown");
}
}
if (!command.description().equalsIgnoreCase("") && cmdLabel.equals(label)) {
map.getCommand(cmdLabel).setDescription(command.description());
}
if (!command.usage().equalsIgnoreCase("") && cmdLabel.equals(label)) {
map.getCommand(cmdLabel).setUsage(command.usage());
}
if(!(command.permission()==null)&&!(command.permission()=="")&&!(command.permission().equals(""))){
registerPermission(command.permission(),"Permission of /" + command.name());
//if(!Bukkit.getPluginManager().getPermissions().contains())
// Bukkit.getPluginManager().addPermission(perm);
}
}
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 {
Bukkit.getLogger().severe("Unable to register tab completer " + m.getName()
+ ". A tab completer is already registered for that command!");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
private static void registerPermission(String name, String desc){
Permission perm = new Permission(name, desc);
if(!getRegisteredPermissionsString().contains(name)) {
Bukkit.getPluginManager().getPermissions().add(perm);
}
}
private static Set getRegisteredPermissionsString(){
Set permissions = new HashSet<>();
Bukkit.getPluginManager().getPermissions().forEach(perm -> permissions.add(perm.getName()));
return permissions;
}
public void registerCommandsInPackage(String packageName){
ReflectionUtils.getClassesInPackage(bLib.getPlugin(),packageName).forEach(clazz ->{
if(BaseCommand.class.isAssignableFrom(clazz) && clazz.getSuperclass() == BaseCommand.class){
try {
Constructor constructor = clazz.getDeclaredConstructor();
constructor.newInstance();
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
registerCommands(clazz);
}
});
}
public Map getOtherMap() {
return otherMap;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy