修复违规计数文案歧义、验证码重验回归、quest_data.db归位

1. 违规计数订正:实际计数一直是1→2→3(incrementViolation是+1),截图显示的
   1/3/6三角数是文案歧义——nextPunishHint返回的第N次违规预告与命中提示的第N次
   违规两行并列,被读成跳号。现改为预告只报处罚档位不报次数,命中提示改为
   「本次为第N次违规」,次数全局只出现一次。

2. 验证码回归修复:isMuted()禁言到期自动解禁时调用markReverify(),把已通过
   人机验证的玩家踢出verifiedPlayers,导致「验证码通过→被禁言→到期解禁→又要
   重验」的死循环。按用户裁定改为:到期自动解禁不再吊销验证状态,仅显式
   /chat unmute 与 /chat reset 才吊销。

3. quest_data.db 归位任务面板/:QuestStorage与PlayerStorage两处硬编码路径
   改为子目录并自动建目录,migrateRootDataFiles() 增加 db/-shm/-wal 三件套
   幂等迁移(启动最早期执行)。
This commit is contained in:
youpaishidifu
2026-10-08 17:44:15 +08:00
parent 19e03c5fb4
commit 0ab7c7052c
4 changed files with 25 additions and 8 deletions
@@ -1123,8 +1123,10 @@ public class ChatFilterManager {
muteIssuers.remove(name);
muteStarts.remove(name);
clearMuteDb(name);
// ★ 禁言到期自动解禁 → 立即要求重新人机验证(解禁≠解除人机验证)
markReverify(name);
// ★ 2026-10-08 用户裁定:玩家已通过人机验证后,禁言到期自动解禁
// **不再**吊销验证状态。此前这里调 markReverify 导致
// 「验证码通过 → 被禁言 → 到期解禁 → 又要重验」的死循环。
// 仅显式 /chat unmute 与 /chat reset 才吊销(见 unmutePlayer/resetPlayer)。
return false;
}
return true;
@@ -1411,7 +1413,8 @@ public class ChatFilterManager {
public void resetPlayer(String name) {
boolean wasMuted = mutedPlayers.remove(name) != null;
violationCount.remove(name);
// ★ 清禁言=解禁 → 必须重新人机验证;从未被禁言的只清计数,不打扰
// ★ 显式 /chat reset = 人为强制重置 → 吊销人机验证(合理)。
// 注意与 isMuted() 的「到期自动解禁」区分:后者不吊销(见 98-a)。
if (wasMuted) {
markReverify(name);
}
@@ -1434,7 +1437,11 @@ public class ChatFilterManager {
if ("mute".equals(type)) {
cn += " " + fmtDuration(dur);
}
return "第 " + nextKey + " 次违规: " + cn;
// ★ 2026-10-08:不再返回「第 N 次违规」前缀。
// 原文案「第3次违规: 禁言5分」紧跟在「(第 2 次违规)」之后,
// 两行并列会被读成计数 2→6 跳号(实际计数是 1→2→3,未跳)。
// 次数只在「(第 N 次违规)」一处出现,避免重复计数视觉。
return cn;
}
public boolean isPlayerWhitelisted(
+7 -2
View File
@@ -1008,6 +1008,10 @@ public class Main extends JavaPlugin
{"pvp.db-shm", "pvp"},
{"pvp.db-wal", "pvp"},
{"maxsell_config.txt", "shop"},
// #99 quest_data.db 归入「任务面板」(任务进度数据)
{"quest_data.db", "任务面板"},
{"quest_data.db-shm", "任务面板"},
{"quest_data.db-wal", "任务面板"},
};
for (String[] m : moves) {
File src = new File(root, m[0]);
@@ -5723,10 +5727,11 @@ public class Main extends JavaPlugin
getLogger().info("[Sdf1_chat] " + p.getName() + " 命中敏感词("
+ ms.get(0) + "),累计违规 " + sc + " 次,消息已拦截");
p.sendMessage("§c§l[聊天过滤] §7消息包含违规词 §f" + ms.get(0)
+ " §7已被拦截 §8(第 " + sc + " 次违规)");
+ " §7已被拦截,§8本次为第 " + sc + " 次违规");
String punishHint = chatFilter.nextPunishHint(sc);
if (punishHint != null) {
p.sendMessage("§8下次违规将触发: §e" + punishHint);
// ★ 只报处罚档位,不报「第N次」——与上一行的次数并列易被读成跳号
p.sendMessage("§8再次违规将处罚: §e" + punishHint);
}
String swReason = "说出敏感词("
+ ms.get(0) + ")";
+4 -1
View File
@@ -12,8 +12,11 @@ public class PlayerStorage {
Logger logger) {
this.logger = logger;
File dbFile = new File(
dataFolder,
new File(dataFolder,
"任务面板"),
"quest_data.db");
dbFile.getParentFile()
.mkdirs();
try {
Class.forName(
"org.sqlite.JDBC");
+3 -1
View File
@@ -23,7 +23,9 @@ public class QuestStorage {
try {
Class.forName("org.sqlite.JDBC");
File dbFile = new File(
dataFolder, "quest_data.db");
new File(dataFolder, "任务面板"),
"quest_data.db");
dbFile.getParentFile().mkdirs();
path = dbFile.getPath();
} catch (Exception e) {
e.printStackTrace();