diff --git a/src/me/commandBlock/CheckCommand.java b/src/me/commandBlock/CheckCommand.java
index fb3c84e..3df1293 100644
--- a/src/me/commandBlock/CheckCommand.java
+++ b/src/me/commandBlock/CheckCommand.java
@@ -5,17 +5,20 @@
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
+import org.bukkit.entity.Player;
+
public final class CheckCommand {
private static CommandBlock ins = CommandBlock.getIns();
/**
* 根据配置文件检查玩家输入的指令是否需要拦截
+ *
* @param commandStr 玩家输入的命令字符串
* @param playerName 玩家名字
- * @return true 匹配成功
false 匹配失败
+ * @return true 匹配成功
+ * false 匹配失败
*/
- public static boolean check(String commandStr, String playerName) {
-
+ public static boolean check(String commandStr, Player player) {
// 从ConfigFile中接收玩家白名单列表和禁用指令列表
List playerList = ConfigFile.getPlayerWhiteList();
List commandList = ConfigFile.getCommandList();
@@ -23,12 +26,12 @@ public static boolean check(String commandStr, String playerName) {
// 如果玩家白名单列表匹配成功,则直接返回false
if (playerList.size() > 0) {
for (int i = 0; i < playerList.size(); i++) {
- if (playerList.get(i).equals(playerName)) {
+ if (playerList.get(i).equals(player.getName())) {
return false;
}
}
}
-
+
// 如果配置文件中有需要拦截的命令
if (commandList.size() > 0) {
// 处理用户输入的信息
@@ -37,18 +40,36 @@ public static boolean check(String commandStr, String playerName) {
commandStrs[0] = temp[temp.length - 1].replace("/", "");
// 如果玩家将要执行的指令和禁用指令列表匹配成功,则返回true
- outer: for (int i = 0; i < commandList.size(); i++) {
+ outer: for (int i = 0; i < commandList.size(); i++) {
String[] regs = tr(commandList.get(i)).split(" ");
+ regs[0] = regs[0].replace("/", "");
+
+ // 如果规则表达式第一个字符为'+'号进入白名单匹配模式
+ if (regs[0].charAt(0) == '+') {
+ regs[0] = regs[0].substring(1);
+ if (whiteMatch(regs, commandStrs)) {
+ if (CmdCb.debug)
+ ins.getLogger().info("reg:" + tr(commandList.get(i)) + " str:" + commandStr.substring(1)
+ + " mode:white true");
+ return false;
+ } else {
+ if (CmdCb.debug)
+ ins.getLogger().info("reg:" + tr(commandList.get(i)) + " str:" + commandStr.substring(1)
+ + " mode:white false");
+ continue;
+ }
+ }
+
+ // 正常黑名单匹配模式
if (commandStrs.length >= regs.length) {
// 如果第count个子字符串没有匹配成功,那后续的子字符串不用再匹配了,直接继续匹配配置文件中下一条命令
// 最大循环次数是配置文件中每条命令分割后的字符串数组的长度
- regs[0] = regs[0].replace("/", "");
for (int count = 0; count < regs.length; count++) {
if (!match(regs[count], commandStrs[count])) {
continue outer;
}
}
- if (CmdCb.debug) ins.getLogger().info("命令列表匹配成功:" + commandList.get(i));
+ if (CmdCb.debug) ins.getLogger().info("命令列表匹配成功:" + commandList.get(i));
return true;
}
}
@@ -57,38 +78,55 @@ public static boolean check(String commandStr, String playerName) {
// 如果全部没有匹配成功,则表示玩家不在白名单,而且玩家执行的指令也没有被禁止,返回false
return false;
}
-
+
/**
* 根据自定义规则匹配两个字符串, * 表示零个或多个有效字符, ? 表示一个有效字符
* 有效字符: 小写a-z, 大写A-Z, 数字0-9, 下划线_
- * @param reg 规则字符串
- * @param strs 目标字符串
- * @return true 匹配成功
false 匹配失败
+ *
+ * @param reg 规则字符串
+ * @param str 目标字符串
+ * @return true 匹配成功
+ * false 匹配失败
*/
- private static boolean match(String reg, String strs) {
+ private static boolean match(String reg, String str) {
boolean result = false;
try {
- reg = reg.toLowerCase()
- .replace("\\", "")
- .replaceAll("\\*{1,}", "\\\\w*")
- .replace("?", "\\w")
- .replace(".", "[.]")
- .replace("+", "[+]");
- Matcher matcher = Pattern.compile(reg).matcher(strs.toLowerCase());
+ reg = reg.toLowerCase().replace("\\", "").replace("+", "[+]").replaceAll("\\*{1,}", "[-\\\\w]*")
+ .replace("?", "[-\\w]").replace(".", "[.]");
+ Matcher matcher = Pattern.compile(reg).matcher(str.toLowerCase());
result = matcher.matches();
} catch (PatternSyntaxException e) {
- System.out.println("错误的正则表达式:" + e.getPattern());
+ ins.getLogger().info("错误的正则表达式:" + e.getPattern());
}
- if (CmdCb.debug) ins.getLogger().info("reg:" + reg + " " + "strs:" + strs + " " + String.valueOf(result));
+ if (CmdCb.debug)
+ ins.getLogger().info("reg:" + reg + " str:" + str + " mode:black " + String.valueOf(result));
return result;
}
-
+
/**
* 去除首尾空格以及把两个及两个以上的空格替换成一个空格
+ *
* @param 源字符串
* @return 结果字符串
*/
private static String tr(String string) {
return string.trim().replaceAll(" {2,}", " ");
}
+
+ /**
+ * 判断命令字符串是否包含规则字符串(忽略大小写)
+ *
+ * @param regs 规则字符串数组
+ * @param strs 命令字符串数组
+ * @return true 包含
+ * false 不包含
+ */
+ private static boolean whiteMatch(String[] regs, String[] strs) {
+ if (strs.length < regs.length) return false;
+ for (int i = 0; i < regs.length; i++) {
+ if (!regs[i].equalsIgnoreCase(strs[i]))
+ return false;
+ }
+ return true;
+ }
}
diff --git a/src/me/commandBlock/CmdCb.java b/src/me/commandBlock/CmdCb.java
index c962edf..c766abc 100644
--- a/src/me/commandBlock/CmdCb.java
+++ b/src/me/commandBlock/CmdCb.java
@@ -38,7 +38,7 @@ public static List tab(CommandSender sender, String[] args) {
return new ArrayList();
}
- private static boolean checkPermissions(CommandSender sender) {
+ public static boolean checkPermissions(CommandSender sender) {
if (sender instanceof ConsoleCommandSender) return true;
if (sender instanceof Player) return sender.isOp();
ins.getLogger().warning("未处理的命令发送者:" + sender.getClass().getName());
diff --git a/src/me/commandBlock/CommandListener.java b/src/me/commandBlock/CommandListener.java
index 12614ed..bdb4ab0 100644
--- a/src/me/commandBlock/CommandListener.java
+++ b/src/me/commandBlock/CommandListener.java
@@ -9,7 +9,7 @@ public class CommandListener implements Listener {
@EventHandler
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent e) {
- if (CheckCommand.check(e.getMessage(), e.getPlayer().getName())) {
+ if (CheckCommand.check(e.getMessage(), e.getPlayer())) {
e.setCancelled(true);
Bukkit.getLogger().info(
ConfigFile.PREFIX_C + "玩家 " + e.getPlayer().getName() + " 试图执行:" + e.getMessage() + ", 已拦截操作!");