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