23/8/31更新 版本6.0.0

1. 完善了 AbstractCommendExecutor,新增了类型检查,并发限制,异步支持,执行冷却,可选参数。
pull/25/head
qianmo 3 years ago
parent 9620473fee
commit 440cd45bda

@ -3,15 +3,13 @@ package com.ultikits.ultitools.abstracts;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.ultikits.ultitools.UltiTools;
import com.ultikits.ultitools.annotations.command.CmdExecutor;
import com.ultikits.ultitools.annotations.command.CmdMapping;
import com.ultikits.ultitools.annotations.command.CmdParam;
import com.ultikits.ultitools.annotations.command.CmdTarget;
import com.ultikits.ultitools.annotations.command.*;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -22,11 +20,18 @@ import java.util.*;
public abstract class AbstractCommendExecutor implements TabExecutor {
private final BiMap<String, Method> mappings = HashBiMap.create();
private final BiMap<UUID, Method> SenderLock = HashBiMap.create();
private final BiMap<UUID, Method> CmdCoolDown = HashBiMap.create();
private boolean ServerLock = false;
public AbstractCommendExecutor() {
scanCommandMappings();
}
public AbstractCommendExecutor getInstance() {
return this;
}
private void scanCommandMappings() {
Class<? extends AbstractCommendExecutor> clazz = this.getClass();
Method[] methods = clazz.getDeclaredMethods();
@ -44,6 +49,9 @@ public abstract class AbstractCommendExecutor implements TabExecutor {
if (formatArgs[i].startsWith("<") && formatArgs[i].endsWith(">")) {
params.put(formatArgs[i].substring(1, formatArgs[i].length() - 1), args[i]);
}
if (formatArgs[i].startsWith("[") && formatArgs[i].endsWith("]")) {
params.put(formatArgs[i].substring(1, formatArgs[i].length() - 1), args[i]);
}
}
return params;
}
@ -52,21 +60,42 @@ public abstract class AbstractCommendExecutor implements TabExecutor {
for (Map.Entry<String, Method> entry : mappings.entrySet()) {
String format = entry.getKey();
String[] formatArgs = format.split(" ");
if (formatArgs.length != args.length) {
continue;
}
boolean match = true;
for (int i = 0; i < formatArgs.length; i++) {
String formatArg = formatArgs[i];
String actualArg = args[i];
if (formatArg.startsWith("<") && formatArg.endsWith(">")) {
String lastArg = formatArgs[formatArgs.length - 1];
boolean match;
if (lastArg.startsWith("[") && lastArg.endsWith("]")) {
if (formatArgs.length - args.length == 1) {
continue;
}
if (!formatArg.equals(actualArg)) {
match = false;
break;
match = true;
for (int i = 0; i < formatArgs.length - 1; i++) {
String formatArg = formatArgs[i];
String actualArg = args[i];
if (formatArg.startsWith("<") && formatArg.endsWith(">")) {
continue;
}
if (!formatArg.equalsIgnoreCase(actualArg)) {
match = false;
break;
}
}
} else {
if (formatArgs.length != args.length) {
continue;
}
match = true;
for (int i = 0; i < formatArgs.length; i++) {
String formatArg = formatArgs[i];
String actualArg = args[i];
if (formatArg.startsWith("<") && formatArg.endsWith(">")) {
continue;
}
if (!formatArg.equalsIgnoreCase(actualArg)) {
match = false;
break;
}
}
}
if (match) {
return entry.getValue();
}
@ -165,6 +194,135 @@ public abstract class AbstractCommendExecutor implements TabExecutor {
return true;
}
private boolean checkLock(CommandSender sender, Method method) {
if (method.isAnnotationPresent(UsageLimit.class)) {
if (method.getAnnotation(UsageLimit.class).value().equals(UsageLimit.LimitType.SENDER)) {
if (sender instanceof Player) {
sender.sendMessage(ChatColor.RED + UltiTools.getInstance().i18n("请先等待上一条命令执行完毕!"));
return SenderLock.get(((Player) sender).getUniqueId()).equals(method);
}
return false;
}
if (method.getAnnotation(UsageLimit.class).value().equals(UsageLimit.LimitType.ALL)) {
sender.sendMessage(ChatColor.RED + UltiTools.getInstance().i18n("请先等待其他玩家发送的命令执行完毕!"));
return ServerLock;
}
}
return false;
}
private boolean checkCD(CommandSender sender) {
if (!(sender instanceof Player)) {
return false;
}
Player player = (Player) sender;
if(CmdCoolDown.containsKey(player.getUniqueId())) {
sender.sendMessage(ChatColor.RED + UltiTools.getInstance().i18n("操作频繁,请稍后再试"));
return true;
}
return false;
}
private Object[] parseParams(String[] strings, Method method, CommandSender commandSender) {
Map<String, String> params = getParams(strings, mappings.inverse().get(method));
Parameter[] parameters = method.getParameters();
if (parameters.length == 0) {
return new Object[0];
}
List<Object> ParamList = new ArrayList<>();
for (Parameter parameter : parameters) {
if (parameter.getType().equals(Player.class) ) {
Player player = (Player) commandSender;
ParamList.add(parameter.isAnnotationPresent(CmdSender.class) ? player : null);
continue;
}
if (parameter.getType().equals(CommandSender.class)) {
ParamList.add(parameter.isAnnotationPresent(CmdSender.class) ? commandSender : null);
continue;
}
if (parameter.isAnnotationPresent(CmdParam.class)) {
CmdParam cmdParam = parameter.getAnnotation(CmdParam.class);
String value = params.get(cmdParam.value());
try {
if (parameter.getType() == float.class || parameter.getType() == Float.class) {
ParamList.add(Float.parseFloat(value));
continue;
}
if (parameter.getType() == double.class || parameter.getType() == Double.class) {
ParamList.add(Double.parseDouble(value));
continue;
}
if (parameter.getType() == int.class || parameter.getType() == Integer.class) {
ParamList.add(Integer.parseInt(value));
continue;
}
} catch (NumberFormatException e) {
commandSender.sendMessage(
ChatColor.RED + String.format(
UltiTools.getInstance().i18n("参数 \"%s\" 格式错误:\"%s\" 不是一个有效的 %s 类型"),
cmdParam.value(), value, parameter.getType().getName()
));
return null;
}
ParamList.add(value);
} else {
ParamList.add(null);
}
if (parameter.isAnnotationPresent(OptionalParam.class)) {
if (parameter.getType() == Map.class) {
String format = method.getAnnotation(CmdMapping.class).format();
String OptionParams = params.get(format.split(" ")[format.split(" ").length - 1]);
ParamList.add(parseOptionalParams(OptionParams));
} else {
ParamList.add(null);
}
}
}
return ParamList.toArray();
}
private Map<String, List<String>> parseOptionalParams(String OptionalParam) {
Map<String, List<String>> resultMap = new HashMap<>();
String[] optionGroups = OptionalParam.split(";");
for (String optionGroup : optionGroups) {
String[] parts = optionGroup.split("=");
if (parts.length == 2) {
String optionName = parts[0];
String[] arguments = parts[1].split(",");
resultMap.put(optionName, Arrays.asList(arguments));
}
}
return resultMap;
}
private void setCoolDown(CommandSender commandSender, Method method) {
if (!(commandSender instanceof Player)) {
return;
}
CmdCD cmdCD = method.getAnnotation(CmdCD.class);
if (cmdCD.value() == 0) {
return;
}
Player player = (Player) commandSender;
CmdCoolDown.put(player.getUniqueId(), method);
new BukkitRunnable() {
int time = cmdCD.value();
@Override
public void run() {
if (time > 0) {
time--;
} else {
CmdCoolDown.remove(player.getUniqueId(), method);
this.cancel();
}
}
}.runTaskTimerAsynchronously(UltiTools.getInstance(), 0L, 20L);
}
abstract protected void handleHelp(CommandSender sender);
protected void sendErrorMessage(CommandSender sender, Command command) {
@ -187,82 +345,69 @@ public abstract class AbstractCommendExecutor implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
if(!checkSender(commandSender)){
if (strings.length == 1 && getHelpCommand().equals(strings[0])){
handleHelp(commandSender);
return true;
}
if (!checkPermission(commandSender)) {
Method method = matchMethod(strings);
if (method == null) {
commandSender.sendMessage(ChatColor.RED + String.format(UltiTools.getInstance().i18n("未知指令,请使用/%s %s获取帮助"), command.getName(), getHelpCommand()));
handleHelp(commandSender);
return true;
}
if (!checkOp(commandSender)) {
if (!checkSender(commandSender) && !checkSender(commandSender, method)) {
return true;
}
if (strings.length > 0 && getHelpCommand().equals(strings[0])){
handleHelp(commandSender);
if (!checkPermission(commandSender) && !checkPermission(commandSender, method)) {
return true;
}
Method method = matchMethod(strings);
if (method == null) {
commandSender.sendMessage(ChatColor.RED + UltiTools.getInstance().i18n("未知指令!"));
handleHelp(commandSender);
if (!checkOp(commandSender) && !checkOp(commandSender, method)) {
return true;
}
Map<String, String> params = getParams(strings, mappings.inverse().get(method));
Parameter[] parameters = method.getParameters();
ArrayList<Object> ParamList = new ArrayList<>();
if (parameters.length == 0) {
try {
if (!checkSender(commandSender, method)) {
return true;
}
if (!checkPermission(commandSender, method)) {
return true;
}
if (!checkOp(commandSender, method)) {
return true;
}
method.invoke(this);
} catch (IllegalAccessException | InvocationTargetException e) {
sendErrorMessage(commandSender, command);
throw new RuntimeException(e);
}
if (checkLock(commandSender, method)) {
return true;
}
for (Parameter parameter : parameters) {
if (parameter.getType().equals(Player.class)) {
Player player = (Player) commandSender;
ParamList.add(player);
continue;
}
if (parameter.getType().equals(CommandSender.class)) {
ParamList.add(commandSender);
continue;
}
if (parameter.getType().equals(Command.class)) {
ParamList.add(command);
continue;
}
if (parameter.isAnnotationPresent(CmdParam.class)) {
CmdParam cmdParam = parameter.getAnnotation(CmdParam.class);
String value = params.get(cmdParam.value());
ParamList.add(value);
} else {
ParamList.add(null);
}
if (checkCD(commandSender)) {
return true;
}
try {
if (!checkSender(commandSender, method)) {
return true;
}
if (!checkPermission(commandSender, method)) {
return true;
}
if (!checkOp(commandSender, method)) {
return true;
Object[] params = parseParams(strings, method, commandSender);
BukkitRunnable bukkitRunnable = new BukkitRunnable() {
@Override
public void run() {
if (method.isAnnotationPresent(UsageLimit.class)) {
if (method.getAnnotation(UsageLimit.class).value().equals(UsageLimit.LimitType.ALL)) {
ServerLock = true;
}
if (method.getAnnotation(UsageLimit.class).value().equals(UsageLimit.LimitType.SENDER)) {
if (commandSender instanceof Player) {
SenderLock.put(((Player) commandSender).getUniqueId(), method);
}
}
}
try {
setCoolDown(commandSender, method);
method.invoke(getInstance(), params);
} catch (IllegalAccessException | InvocationTargetException e) {
sendErrorMessage(commandSender, command);
throw new RuntimeException(e);
} finally {
if (method.isAnnotationPresent(UsageLimit.class)) {
if (method.getAnnotation(UsageLimit.class).value().equals(UsageLimit.LimitType.ALL)) {
ServerLock = false;
}
if (method.getAnnotation(UsageLimit.class).value().equals(UsageLimit.LimitType.SENDER)) {
if (commandSender instanceof Player) {
SenderLock.remove(((Player) commandSender).getUniqueId());
}
}
}
}
}
method.invoke(this, ParamList.toArray());
} catch (IllegalAccessException | InvocationTargetException e) {
sendErrorMessage(commandSender, command);
throw new RuntimeException(e);
};
if (method.isAnnotationPresent(RunAsync.class)) {
bukkitRunnable.runTaskAsynchronously(UltiTools.getInstance());
} else {
bukkitRunnable.runTask(UltiTools.getInstance());
}
return true;
}

@ -0,0 +1,12 @@
package com.ultikits.ultitools.annotations.command;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CmdCD {
int value() default 0;
}

@ -0,0 +1,11 @@
package com.ultikits.ultitools.annotations.command;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CmdSender {
}

@ -0,0 +1,11 @@
package com.ultikits.ultitools.annotations.command;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface OptionalParam {
}

@ -0,0 +1,11 @@
package com.ultikits.ultitools.annotations.command;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RunAsync {
}

@ -0,0 +1,17 @@
package com.ultikits.ultitools.annotations.command;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UsageLimit {
LimitType value();
enum LimitType {
NONE,
SENDER,
ALL
}
}

@ -2,10 +2,7 @@ package com.ultikits.ultitools.commands;
import com.ultikits.ultitools.UltiTools;
import com.ultikits.ultitools.abstracts.AbstractCommendExecutor;
import com.ultikits.ultitools.annotations.command.CmdExecutor;
import com.ultikits.ultitools.annotations.command.CmdMapping;
import com.ultikits.ultitools.annotations.command.CmdParam;
import com.ultikits.ultitools.annotations.command.CmdTarget;
import com.ultikits.ultitools.annotations.command.*;
import com.ultikits.ultitools.entities.PluginEntity;
import com.ultikits.ultitools.utils.PluginInstallUtils;
import org.bukkit.ChatColor;
@ -18,7 +15,7 @@ import java.util.List;
@CmdTarget(CmdTarget.CmdTargetType.BOTH)
public class PluginInstallCommands extends AbstractCommendExecutor {
@CmdMapping(format = "list <page>")
public void listPlugins(CommandSender sender, @CmdParam("page") String page) {
public void listPlugins(@CmdSender CommandSender sender, @CmdParam("page") String page) {
int pageInt = 1;
if (page != null && !page.isEmpty()) {
try {
@ -51,12 +48,12 @@ public class PluginInstallCommands extends AbstractCommendExecutor {
}
@CmdMapping(format = "list")
public void listPlugins(CommandSender sender) {
public void listPlugins(@CmdSender CommandSender sender) {
listPlugins(sender, "1");
}
@CmdMapping(format = "install <plugin> <version>")
public void installPlugin(CommandSender sender, @CmdParam("plugin") String plugin, @CmdParam("version") String version) {
public void installPlugin(@CmdSender CommandSender sender, @CmdParam("plugin") String plugin, @CmdParam("version") String version) {
if (PluginInstallUtils.installPlugin(plugin, version)) {
sender.sendMessage(ChatColor.GREEN + UltiTools.getInstance().i18n("安装成功!请重启服务器!"));
} else {
@ -65,7 +62,7 @@ public class PluginInstallCommands extends AbstractCommendExecutor {
}
@CmdMapping(format = "install <plugin>")
public void installPlugin(CommandSender sender, @CmdParam("plugin") String plugin) {
public void installPlugin(@CmdSender CommandSender sender, @CmdParam("plugin") String plugin) {
if (PluginInstallUtils.installLatestPlugin(plugin)) {
sender.sendMessage(ChatColor.GREEN + UltiTools.getInstance().i18n("安装成功!请重启服务器!"));
} else {
@ -74,7 +71,7 @@ public class PluginInstallCommands extends AbstractCommendExecutor {
}
@CmdMapping(format = "versions <plugin>")
public void listVersions(CommandSender sender, @CmdParam("plugin") String plugin) {
public void listVersions(@CmdSender CommandSender sender, @CmdParam("plugin") String plugin) {
List<String> pluginVersions = PluginInstallUtils.getPluginVersions(plugin);
if (pluginVersions == null) {
sender.sendMessage(ChatColor.RED + UltiTools.getInstance().i18n("获取版本列表失败!"));
@ -101,7 +98,7 @@ public class PluginInstallCommands extends AbstractCommendExecutor {
}
@CmdMapping(format = "uninstall <plugin>")
public void uninstallPlugin(CommandSender sender, @CmdParam("plugin") String plugin) {
public void uninstallPlugin(@CmdSender CommandSender sender, @CmdParam("plugin") String plugin) {
try {
if (PluginInstallUtils.uninstallPlugin(plugin)) {
sender.sendMessage(ChatColor.GREEN + UltiTools.getInstance().i18n("卸载成功!请手动删除本地文件,否则重启之后还会启用!"));

@ -17,6 +17,10 @@
"你没有权限!": "You don't have permission to do that!",
"未知指令,请使用/%s %s获取帮助": "Unknown command, please enter /%s %s for help",
"指令执行错误,请使用/%s %s获取帮助": "Command execution error, please enter /%s %s for help",
"请先等待上一条命令执行完毕!": "Please wait for last Command Processing!",
"请先等待其他玩家发送的命令执行完毕!": "Please wait for last Command Processing which sent by other players!",
"操作频繁,请稍后再试": "Frequent operations, please try again later",
"参数 \"%s\" 格式错误:\"%s\" 不是一个有效的 %s 类型": "Parameter \"%s\" has a formatting error: \"%s\" is not a valid %s type.",
"=== UltiTools 命令列表 ===\n/ul reload 重载插件模块\n================": "=== UltiTools Commands ===\n/ul reload Reload modules\n================",
"========|可用插件列表|========\n": "========|Available Plugin List|========\n",
". 名字:": ". Name:",

@ -17,5 +17,9 @@
"你没有权限!": "你没有权限!",
"指令执行错误,请使用/%s %s获取帮助": "指令执行错误,请使用/%s %s获取帮助",
"未知指令,请使用/%s %s获取帮助": "未知指令,请使用/%s %s获取帮助",
"请先等待上一条命令执行完毕!": "请先等待上一条命令执行完毕!",
"请先等待其他玩家发送的命令执行完毕!": "请先等待其他玩家发送的命令执行完毕!",
"操作频繁,请稍后再试": "操作频繁,请稍后再试",
"参数 \"%s\" 格式错误:\"%s\" 不是一个有效的 %s 类型": "参数 \"%s\" 格式错误:\"%s\" 不是一个有效的 %s 类型",
"=== UltiTools 命令列表 ===\n/ul reload 重载插件模块\n================": "=== UltiTools 命令列表 ===\n/ul reload 重载插件模块\n================"
}

Loading…
Cancel
Save