R23-2: 封禁同步彻底修复 - syncBans独立hash+控制台ban监听+插件ban即时同步PHP

This commit is contained in:
2026-07-12 23:45:59 +08:00
parent 529b83666c
commit c0ab91edba
2 changed files with 65 additions and 13 deletions
+35 -5
View File
@@ -1043,6 +1043,12 @@ public class Main extends JavaPlugin
// ★ 公屏广播封禁警告
broadcastBanWarning(target, type, reason, expireMs, sender.getName());
// ★ 立即异步同步封禁到PHP(避免等待15-25秒定时同步)
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
WebManager wm = webManager;
if (wm != null) wm.forceSyncBansAndAdmins();
});
// ★ 清除标记(延迟1秒,确保事件已触发)
String tgt = target.toLowerCase();
Bukkit.getScheduler().runTaskLater(this, () -> selfInitiatedBans.remove(tgt), 20L);
@@ -2870,15 +2876,33 @@ public class Main extends JavaPlugin
public void onPlayerCommandPreprocess(org.bukkit.event.player.PlayerCommandPreprocessEvent e) {
if (e.isCancelled()) return;
String msg = e.getMessage().trim();
String lower = msg.toLowerCase();
if (msg.isEmpty() || msg.charAt(0) != '/') return;
handleBanCommand(msg.substring(1));
}
boolean isNameBan = lower.equals("/ban") || lower.startsWith("/ban ");
boolean isIpBan = lower.equals("/ban-ip") || lower.startsWith("/ban-ip ")
|| lower.equals("/banip") || lower.startsWith("/banip ");
// ★ 拦截控制台 ban、ban-ip 命令(包括 minecraft:ban 形式)
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onServerCommand(org.bukkit.event.server.ServerCommandEvent e) {
if (e.isCancelled()) return;
handleBanCommand(e.getCommand().trim());
}
private void handleBanCommand(String rawCommand) {
if (rawCommand.isEmpty()) return;
String lower = rawCommand.toLowerCase();
// 兼容 minecraft:ban / minecraft:ban-ip 形式
if (lower.startsWith("minecraft:")) {
rawCommand = rawCommand.substring(10);
lower = lower.substring(10);
}
boolean isNameBan = lower.equals("ban") || lower.startsWith("ban ");
boolean isIpBan = lower.equals("ban-ip") || lower.startsWith("ban-ip ")
|| lower.equals("banip") || lower.startsWith("banip ");
if (!isNameBan && !isIpBan) return;
// 解析 /ban <player> [reason...] 或 /ban-ip <player|ip> [reason...]
String[] parts = msg.split("\\s+");
String[] parts = rawCommand.split("\\s+");
if (parts.length < 2) return;
String target = parts[1];
@@ -2913,6 +2937,12 @@ public class Main extends JavaPlugin
long expireMs = expireDate != null ? expireDate.getTime() : null;
broadcastBanWarning(ip, org.bukkit.BanList.Type.IP, reason, expireMs, source);
}
// 立即同步封禁到PHP( Vanilla ban 不走 applyBan,所以这里手动触发)
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
WebManager wm = webManager;
if (wm != null) wm.forceSyncBansAndAdmins();
});
} catch (Exception ex) {
getLogger().warning("[封禁广播] 拦截ban命令异常: " + ex.getMessage());
}
+30 -8
View File
@@ -107,6 +107,8 @@ public class WebManager {
private String lastServiceProviderHash = "";
private String lastBondBalanceHash = "";
private String lastLandDataHash = "";
private String lastBansHash = "";
private String lastAdminsHash = "";
private String lastPushCredentialsHash = "";
private String lastUserRegistrationHash = "";
@@ -3272,6 +3274,11 @@ public class WebManager {
.append(p.getOrDefault("permissions", "")).append("|");
}
String currentHash = lands.size() + ":" + hashBuilder.toString();
// ★ 封禁名单和管理员列表独立于领地hash变化,必须每次都同步
syncBans();
syncAdmins();
if (currentHash.equals(lastLandDataHash)) {
// ★ hash未变化,静默跳过(但首次运行或强制刷新时会同步)
return;
@@ -3343,12 +3350,6 @@ public class WebManager {
// 4. 同步成员权限数据(area_land_permissions → web_area_permissions)
syncPermissions(areaProtect);
// 5. 同步封禁名单到PHP
syncBans();
// 5. ★ 同步插件管理员列表到PHP
syncAdmins();
plugin.getLogger().fine("[Web通信] 领地数据同步完成");
} catch (Exception e) {
plugin.getLogger().warning("[Web通信] 领地同步异常: " + e.getMessage());
@@ -3470,6 +3471,13 @@ public class WebManager {
}
}
String currentHash = adminNames.stream().sorted().collect(Collectors.joining("|"));
if (currentHash.equals(lastAdminsHash)) {
plugin.getLogger().fine("[防护-sync] 管理员列表无变化,跳过");
return;
}
lastAdminsHash = currentHash;
// 构建JSON数组
StringBuilder sb = new StringBuilder("[");
boolean first = true;
@@ -3485,12 +3493,17 @@ public class WebManager {
params.put("secret", secretKey);
params.put("admins", sb.toString());
String resp = httpGet("api/sync.php", params);
plugin.getLogger().fine("[防护-sync] 管理员列表同步: " + adminNames.size() + "人 → " + resp);
plugin.getLogger().info("[防护-sync] 管理员列表同步: " + adminNames.size() + "人 → " + resp);
} catch (Exception e) {
plugin.getLogger().warning("[防护-sync] 管理员列表同步异常: " + e.getMessage());
}
}
public void forceSyncBansAndAdmins() {
syncBans();
syncAdmins();
}
/**
* ★ 同步封禁名单到PHP(供用户管理页面显示封禁状态)
*/
@@ -3502,6 +3515,7 @@ public class WebManager {
StringBuilder sb = new StringBuilder("[");
boolean first = true;
StringBuilder hashBuilder = new StringBuilder();
// 名字封禁
@SuppressWarnings("unchecked")
@@ -3517,6 +3531,7 @@ public class WebManager {
.append("\",\"reason\":\"").append(escapeJson(reason))
.append("\",\"source\":\"").append(escapeJson(source))
.append("\",\"expire\":").append(expireDate).append("}");
hashBuilder.append("n:").append(target).append(":").append(reason).append(":").append(expireDate).append("|");
}
// IP封禁
@@ -3533,16 +3548,23 @@ public class WebManager {
.append("\",\"reason\":\"").append(escapeJson(reason))
.append("\",\"source\":\"").append(escapeJson(source))
.append("\",\"expire\":").append(expireDate).append("}");
hashBuilder.append("i:").append(target).append(":").append(reason).append(":").append(expireDate).append("|");
}
sb.append("]");
String currentHash = hashBuilder.toString();
if (currentHash.equals(lastBansHash)) {
plugin.getLogger().fine("[防护-sync] 封禁名单无变化,跳过");
return;
}
lastBansHash = currentHash;
Map<String, String> params = new LinkedHashMap<>();
params.put("action", "sync_bans");
params.put("secret", secretKey);
params.put("bans", sb.toString());
String resp = httpGet("api/sync.php", params);
plugin.getLogger().fine("[防护-sync] 封禁名单同步: " + resp);
plugin.getLogger().info("[防护-sync] 封禁名单同步: " + (nameEntries.size() + ipEntries.size()) + "条 → " + resp);
} catch (Exception e) {
plugin.getLogger().warning("[防护-sync] 封禁名单同步异常: " + e.getMessage());
}