YumCore/src/main/java/pw/yumc/YumCore/commands/CommandManager.java

283 lines
8.7 KiB
Java
Raw Normal View History

package pw.yumc.YumCore.commands;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.StringUtil;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.bukkit.compatible.C;
/**
*
*
* @since 2016723 9:06:03
* @author
*/
public class CommandManager implements TabExecutor {
private final String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 应只有 CommandArgument 参数!";
private final String returnTypeError = "注解命令补全 %s 位于 %s 的返回值错误 应实现 List 接口!";
/**
*
*/
JavaPlugin plugin = P.instance;
/**
*
*/
CommandInfo defCmd = null;
/**
*
*/
Set<CommandInfo> cmds = new HashSet<>();
/**
* Tab
*/
Set<TabInfo> tabs = new HashSet<>();
/**
*
*/
Map<String, CommandInfo> cmdCache = new HashMap<>();
/**
*
*/
List<String> cmdNameCache = new ArrayList<>();
/**
*
*/
CommandHelp help;
/**
*
*/
PluginCommand cmd;
/**
*
*
* @param name
*
*/
public CommandManager(final String name) {
cmd = plugin.getCommand(name);
if (cmd == null) {
throw new IllegalStateException("未找到命令 必须在plugin.yml先注册 " + name + " 命令!");
}
cmd.setExecutor(this);
cmd.setTabCompleter(this);
}
/**
*
*
* @param name
*
* @param executor
*
*/
public CommandManager(final String name, final CommandExecutor... executor) {
this(name);
register(executor);
}
@Override
public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) {
if (args.length == 0) {
if (defCmd != null) {
return defCmd.execute(new CommandArgument(sender, command, label, args));
}
help.send(sender, command, label, args);
return true;
}
final String subcmd = args[0].toLowerCase();
if (subcmd.equalsIgnoreCase("help")) {
help.send(sender, command, label, args);
return true;
}
final CommandArgument cmdArgs = new CommandArgument(sender, command, label, moveStrings(args, 1));
final CommandInfo ci = checkCache(subcmd);
return ci.execute(cmdArgs);
}
@Override
public List<String> onTabComplete(final CommandSender sender, final Command command, final String alias, final String[] args) {
final List<String> completions = new ArrayList<>();
final String token = args[args.length - 1];
if (args.length == 1) {
StringUtil.copyPartialMatches(args[0], cmdNameCache, completions);
} else if (args.length >= 2) {
for (final TabInfo tab : tabs) {
StringUtil.copyPartialMatches(token, tab.execute(sender, command, token, args), completions);
}
StringUtil.copyPartialMatches(token, getPlayerTabComplete(sender, command, alias, args), completions);
}
Collections.sort(completions, String.CASE_INSENSITIVE_ORDER);
return completions;
}
/**
*
*
* @param clazz
*
*/
public void register(final CommandExecutor... clazzs) {
for (final CommandExecutor clazz : clazzs) {
final Method[] methods = clazz.getClass().getDeclaredMethods();
for (final Method method : methods) {
if (registerCommand(method, clazz)) {
continue;
}
registerTab(method, clazz);
}
}
help = new CommandHelp(cmds);
buildCmdNameCache();
}
/**
*
*
* @param helpParse
*
*/
public void setHelpParse(final CommandHelpParse helpParse) {
help.setHelpParse(helpParse);
}
/**
*
*/
private void buildCmdNameCache() {
cmdNameCache.clear();
for (final CommandInfo cmd : cmds) {
cmdNameCache.add(cmd.getName());
cmdNameCache.addAll(Arrays.asList(cmd.getCommand().aliases()));
}
cmdNameCache.add("help");
}
/**
*
*
* @param subcmd
*
* @return
*/
private CommandInfo checkCache(final String subcmd) {
if (!cmdCache.containsKey(subcmd)) {
for (final CommandInfo cmdinfo : cmds) {
if (cmdinfo.isValid(subcmd)) {
cmdCache.put(subcmd, cmdinfo);
break;
}
}
if (!cmdCache.containsKey(subcmd)) {
cmdCache.put(subcmd, CommandInfo.Unknow);
}
}
return cmdCache.get(subcmd);
}
/**
*
*
* @param sender
*
* @param command
*
* @param alias
*
* @param args
*
* @return 线
*/
private List<String> getPlayerTabComplete(final CommandSender sender, final Command command, final String alias, final String[] args) {
final String lastWord = args[args.length - 1];
final Player senderPlayer = sender instanceof Player ? (Player) sender : null;
final ArrayList<String> matchedPlayers = new ArrayList<>();
for (final Player player : C.Player.getOnlinePlayers()) {
final String name = player.getName();
if ((senderPlayer == null || senderPlayer.canSee(player)) && StringUtil.startsWithIgnoreCase(name, lastWord)) {
matchedPlayers.add(name);
}
}
return matchedPlayers;
}
/**
*
*
* @param args
*
* @param start
*
* @return
*/
private String[] moveStrings(final String[] args, final int start) {
final String[] ret = new String[args.length - start];
System.arraycopy(args, start, ret, 0, ret.length);
return ret;
}
/**
*
*
* @param method
*
* @param clazz
*
* @return
*/
private boolean registerCommand(final Method method, final CommandExecutor clazz) {
final CommandInfo ci = CommandInfo.parse(method, clazz);
if (ci != null) {
final Class<?>[] params = method.getParameterTypes();
if (params.length == 1 && params[0].equals(CommandArgument.class)) {
if (method.getReturnType() == boolean.class) {
defCmd = ci;
return true;
}
cmds.add(ci);
cmdCache.put(ci.getName(), ci);
return true;
}
Log.warning(String.format(argumentTypeError, method.getName(), clazz.getClass().getName()));
}
return false;
}
/**
* Tab
*
* @param method
*
* @param clazz
*
* @return
*/
private boolean registerTab(final Method method, final CommandExecutor clazz) {
final TabInfo ti = TabInfo.parse(method, clazz);
if (ti != null) {
if (method.getReturnType().equals(List.class)) {
tabs.add(ti);
return true;
}
Log.warning(String.format(returnTypeError, method.getName(), clazz.getClass().getName()));
}
return false;
}
}