@2026-07-04 23:40 Java修复: 1) illegal_domains.txt 热更新恢复-每次玩家加入时重读配置文件 2) N+1验证码机制-pendingMessages改为List缓存列表,答对第N题释放N条消息 3) 非法域名Kick抑制join/quit消息 4) onEnable自动释放illegal_domains.txt到插件目录 5) 编译打包通过
This commit is contained in:
@@ -450,18 +450,27 @@ public class ChatFilterManager {
|
||||
return VerificationResult.FAILED;
|
||||
}
|
||||
|
||||
// ★ 临时缓存玩家未验证的消息,等验证通过后由插件代为广播
|
||||
public final Map<String, String> pendingMessages = new ConcurrentHashMap<>();
|
||||
// ★ 临时缓存玩家未验证的消息(N+1 机制:缓存列表,答对第N题后释放N条)
|
||||
public final Map<String, List<String>> pendingMessages = new ConcurrentHashMap<>();
|
||||
|
||||
/** 缓存玩家消息,等验证通过时代为广播 */
|
||||
public void cachePendingMessage(String playerName, String message) {
|
||||
pendingMessages.put(playerName, message);
|
||||
pendingMessages.computeIfAbsent(playerName, k -> new ArrayList<>()).add(message);
|
||||
}
|
||||
|
||||
/** 广播缓存的消息给全服 */
|
||||
public void broadcastCachedMessage(String playerName, String message) {
|
||||
pendingMessages.remove(playerName); // 广播后清除缓存
|
||||
Bukkit.broadcastMessage(message); // 普通广播,无前缀
|
||||
/** 广播所有缓存的消息(N+1机制:广播缓存的N-1条 + 当前第N条) */
|
||||
public void broadcastCachedMessages(String playerName) {
|
||||
List<String> messages = pendingMessages.remove(playerName);
|
||||
if (messages != null) {
|
||||
for (String msg : messages) {
|
||||
Bukkit.broadcastMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 清除玩家缓存的消息(验证失败时调用) */
|
||||
public void clearPendingMessages(String playerName) {
|
||||
pendingMessages.remove(playerName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1176,13 +1185,15 @@ public class ChatFilterManager {
|
||||
|
||||
/**
|
||||
* 加载非法域名后缀配置文件(支持热更新)
|
||||
* 配置文件: plugins/Sdf1_login/illegal_domains.txt
|
||||
* 每行一个后缀,如: com, cn, test 等
|
||||
*/
|
||||
public void loadIllegalDomains() {
|
||||
illegalDomainSuffixes.clear();
|
||||
File f = new File(plugin.getDataFolder(), "illegal_domains.txt");
|
||||
if (!f.exists()) {
|
||||
plugin.getLogger().info("[非法域名] 配置文件不存在,已加载默认内置后缀");
|
||||
// 内置默认后缀
|
||||
// 内置默认后缀作为兜底
|
||||
for (String s : new String[]{"com", "cn", "net", "org", "io", "xyz", "top", "club", "site", "online", "store", "tech", "info", "biz"}) {
|
||||
illegalDomainSuffixes.add(s.toLowerCase());
|
||||
}
|
||||
@@ -1199,9 +1210,13 @@ public class ChatFilterManager {
|
||||
illegalDomainSuffixes.add(suffix);
|
||||
}
|
||||
}
|
||||
plugin.getLogger().info("[非法域名] 已加载 " + illegalDomainSuffixes.size() + " 个非法后缀");
|
||||
plugin.getLogger().info("[非法域名] 已加载 " + illegalDomainSuffixes.size() + " 个非法后缀(来自配置文件)");
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().warning("[非法域名] 加载失败: " + e.getMessage());
|
||||
plugin.getLogger().warning("[非法域名] 加载失败,使用内置默认后缀: " + e.getMessage());
|
||||
// 加载失败时用内置兜底
|
||||
for (String s : new String[]{"com", "cn", "net", "org", "io", "xyz", "top", "club", "site", "online", "store", "tech", "info", "biz"}) {
|
||||
illegalDomainSuffixes.add(s.toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -294,6 +294,13 @@ public class Main extends JavaPlugin
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent e) {
|
||||
// ★ 抑制非法域名/Kick玩家的退出消息
|
||||
if (illegalNameKickedPlayers.contains(e.getPlayer().getName())) {
|
||||
e.setQuitMessage(null);
|
||||
illegalNameKickedPlayers.remove(e.getPlayer().getName());
|
||||
return;
|
||||
}
|
||||
|
||||
if (areaProtection != null) {
|
||||
Player p = e.getPlayer();
|
||||
areaProtection.onPlayerOffline(
|
||||
@@ -301,7 +308,6 @@ public class Main extends JavaPlugin
|
||||
if (areaProtection != null) {
|
||||
areaProtection.onPlayerQuit(p.getName());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,6 +316,12 @@ public class Main extends JavaPlugin
|
||||
@Override
|
||||
public void onEnable() {
|
||||
getDataFolder().mkdirs();
|
||||
// ★ 自动释放 illegal_domains.txt 配置文件(jar打包的复制到插件数据目录,仅文件不存在时)
|
||||
File illegalDomainsFile = new File(getDataFolder(), "illegal_domains.txt");
|
||||
if (!illegalDomainsFile.exists()) {
|
||||
saveResource("illegal_domains.txt", false);
|
||||
getLogger().info("[配置] 已自动释放 illegal_domains.txt 到插件目录");
|
||||
}
|
||||
// 启动时清理.sdf1临时文件
|
||||
cleanupSdf1Files();
|
||||
salesStats = new SalesStatsManager(this);
|
||||
@@ -1785,7 +1797,9 @@ public class Main extends JavaPlugin
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Events =====
|
||||
// ===== 非法URL/非法域名用户名拦截(最高优先级) =====
|
||||
private final Set<String> illegalNameKickedPlayers = ConcurrentHashMap.newKeySet();
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
|
||||
@@ -1795,11 +1809,16 @@ public class Main extends JavaPlugin
|
||||
|
||||
// ===== 非法URL/非法域名用户名拦截(最高优先级) =====
|
||||
if (chatFilter != null && chatFilter.isEnabled()) {
|
||||
// 每次玩家加入时热重载非法域名后缀(支持热更新)
|
||||
chatFilter.loadIllegalDomains();
|
||||
|
||||
List<String> urls = chatFilter.extractUrls(name);
|
||||
boolean isIllegalUrl = !urls.isEmpty();
|
||||
boolean isIllegalDomain = chatFilter.containsIllegalDomain(name);
|
||||
if (isIllegalUrl || isIllegalDomain) {
|
||||
e.setJoinMessage(null); // 抑制加入消息
|
||||
p.kickPlayer("§c§l禁止使用含URL或非法域名的名称\n§7请修改您的游戏名称后再加入");
|
||||
illegalNameKickedPlayers.add(name); // 记录以便抑制退出消息
|
||||
getLogger().warning("[安全] 玩家 " + name + " 因名称含非法URL/域名被踢出 (urls=" + isIllegalUrl + ", domain=" + isIllegalDomain + ")");
|
||||
return;
|
||||
}
|
||||
@@ -2607,7 +2626,7 @@ public class Main extends JavaPlugin
|
||||
chatFilter.markPlayerActive(p.getName());
|
||||
}
|
||||
|
||||
// ===== 新玩家验证码检查 =====
|
||||
// ===== 新玩家验证码检查(N+1机制) =====
|
||||
if (chatFilter != null && chatFilter.isEnabled()) {
|
||||
ChatFilterManager.VerificationResult vr = chatFilter.checkNewPlayerVerification(p);
|
||||
|
||||
@@ -2623,17 +2642,15 @@ public class Main extends JavaPlugin
|
||||
// 验证进行中:当前聊天框输入就是答案
|
||||
ChatFilterManager.VerificationResult checkResult = chatFilter.checkAnswer(p.getName(), msg);
|
||||
if (checkResult == ChatFilterManager.VerificationResult.VERIFIED) {
|
||||
String cachedMsg = chatFilter.pendingMessages.get(p.getName());
|
||||
if (cachedMsg != null) {
|
||||
Bukkit.broadcastMessage(p.getDisplayName() + ": " + cachedMsg);
|
||||
chatFilter.pendingMessages.remove(p.getName());
|
||||
}
|
||||
// ★ 答对了 → 释放所有缓存消息(N-1条) + 当前消息(第N条)
|
||||
chatFilter.broadcastCachedMessages(p.getName());
|
||||
Bukkit.broadcastMessage(p.getDisplayName() + ": " + msg);
|
||||
p.sendMessage("§a§l[验证码] §a验证通过!");
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
} else if (checkResult == ChatFilterManager.VerificationResult.FAILED) {
|
||||
// ★ 回答错误:丢弃当前消息(不缓存不发出),重新抽题
|
||||
chatFilter.pendingMessages.remove(p.getName()); // 清除之前的缓存
|
||||
// ★ 答错了 → 清除缓存(不泄露) + 重新出题
|
||||
chatFilter.clearPendingMessages(p.getName());
|
||||
chatFilter.generateMathVerification(p.getName());
|
||||
p.sendMessage("§c§l[验证码] §c回答错误,请重新回答");
|
||||
e.setCancelled(true);
|
||||
@@ -3186,8 +3203,8 @@ public class Main extends JavaPlugin
|
||||
// 移除验证码数据
|
||||
chatFilter.verificationData.remove(p.getName());
|
||||
// 清除缓存的消息(关闭GUI时丢弃)
|
||||
String cached = chatFilter.pendingMessages.remove(p.getName());
|
||||
if (cached != null) {
|
||||
List<String> cachedList = chatFilter.pendingMessages.remove(p.getName());
|
||||
if (cachedList != null) {
|
||||
// 消息已丢弃,下次发消息会重新触发验证码
|
||||
}
|
||||
// 不加入verifiedPlayers,玩家需要重新通过验证
|
||||
@@ -3212,12 +3229,15 @@ public class Main extends JavaPlugin
|
||||
String clickedMat = e.getCurrentItem().getType().name();
|
||||
if (chatFilter != null && chatFilter.isEnabled()) {
|
||||
ChatFilterManager.VerificationResult vr = chatFilter.checkGUIClick(p.getName(), clickedMat);
|
||||
String cachedMsg = chatFilter.pendingMessages.get(p.getName());
|
||||
List<String> cachedList = chatFilter.pendingMessages.get(p.getName());
|
||||
if (vr == ChatFilterManager.VerificationResult.VERIFIED) {
|
||||
p.closeInventory();
|
||||
p.sendMessage("§a§l[验证码] §a验证通过!");
|
||||
if (cachedMsg != null) {
|
||||
Bukkit.broadcastMessage(p.getDisplayName() + ": " + cachedMsg);
|
||||
if (cachedList != null) {
|
||||
// N+1: 广播缓存消息
|
||||
for (String cm : cachedList) {
|
||||
Bukkit.broadcastMessage(p.getDisplayName() + ": " + cm);
|
||||
}
|
||||
chatFilter.pendingMessages.remove(p.getName());
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user