From bbbbf54b3f1db19ca6b05060272ef720adb6c784 Mon Sep 17 00:00:00 2001 From: youpaishidifu Date: Mon, 29 Jun 2026 20:06:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=94=B9=E4=B8=BB=E5=BF=83?= =?UTF-8?q?=E8=B7=B3=E5=BB=B6=E6=97=B6=E6=9C=BA=E5=88=B6:=20PHP=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E8=BD=AE=E8=AF=A21=E5=88=86=E9=92=9F,Java=E5=9B=9E?= =?UTF-8?q?=E8=B0=83=E9=80=9A=E7=9F=A5=E5=8E=9F=E4=B8=BB=E4=BA=BA,?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=92=A4=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Sdf1_login/AreaProtection.java | 83 +++++++++++++++++++- src/main/java/Sdf1_login/WebManager.java | 43 +++++++++- 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/src/main/java/Sdf1_login/AreaProtection.java b/src/main/java/Sdf1_login/AreaProtection.java index 0487af0..6f06a42 100644 --- a/src/main/java/Sdf1_login/AreaProtection.java +++ b/src/main/java/Sdf1_login/AreaProtection.java @@ -5064,7 +5064,7 @@ public class AreaProtection implements Listener { "info", "setowner", "addvisitor", "removevisitor", "listvisitors", "transfer", "shop", "menu", "菜单", "sdf1debug", "testclear", "cli", - "取消删除", "canceldelete", + "取消删除", "canceldelete", "canceladminchange", "removemember", "addmember", "config", "配置", "public", "公共", "listpublic", "公共列表", "tpb", "传送公共", @@ -6612,6 +6612,87 @@ public class AreaProtection implements Listener { return true; } + // ===== 取消管理员改主 ===== + if (sub.equals("canceladminchange")) { + if (!(sender instanceof Player)) { + sender.sendMessage("§c仅玩家可用"); + return true; + } + Player p = (Player) sender; + if (args.length < 2) { + sender.sendMessage("§e用法: /protect canceladminchange <领地名>"); + return true; + } + String areaName = args[1]; + String resolved = resolveAreaName(areaName); + if (resolved != null) areaName = resolved; + + // 检查领地是否存在 + AreaConfig ac = getLand(areaName); + if (ac == null) { + sender.sendMessage("§c领地不存在: " + areaName); + return true; + } + + // 检查是否是原主人 + if (!p.getName().equalsIgnoreCase(ac.owner)) { + sender.sendMessage("§c只有原主人才能撤回改主"); + return true; + } + + // 查找最近的管理员改主记录 + try { + if (dbConnection == null) { + sender.sendMessage("§c数据库未连接"); + return true; + } + PreparedStatement ps = dbConnection.prepareStatement( + "SELECT id, change_data FROM web_admin_changes WHERE change_type = 'owner_change' AND target_name = ? AND status = 'completed' ORDER BY id DESC LIMIT 1"); + ps.setString(1, areaName); + ResultSet rs = ps.executeQuery(); + if (rs.next()) { + int changeId = rs.getInt("id"); + String changeDataStr = rs.getString("change_data"); + java.util.Map changeData = WebManager.parseJson(changeDataStr); + String newOwner = (String) changeData.get("new_owner"); + String oldOwner = (String) changeData.get("old_owner"); + + // 验证当前owner是否是newOwner(即已经被改主了) + if (!p.getName().equalsIgnoreCase(newOwner)) { + sender.sendMessage("§c当前所有者不是你,无法撤回"); + rs.close(); + ps.close(); + return true; + } + + // 回退owner + PreparedStatement updatePs = dbConnection.prepareStatement( + "UPDATE area_lands SET owner = ? WHERE name = ?"); + updatePs.setString(1, oldOwner); + updatePs.setString(2, areaName); + updatePs.executeUpdate(); + updatePs.close(); + + // 更新内存 + ac.owner = oldOwner; + + // 通知PHP回滚 + plugin.webManager.callbackOwnerChangeToPHP(changeId, false, "原主人撤回"); + + sender.sendMessage("§a§l[防护] §f已撤回领地 §e" + areaName + " §f的改主,恢复为 §a" + oldOwner); + plugin.getLogger().info("[防护] " + p.getName() + " 撤回了领地 " + areaName + " 的管理员改主"); + } else { + sender.sendMessage("§c没有可撤回的改主记录"); + } + rs.close(); + ps.close(); + } catch (Exception e) { + sender.sendMessage("§c撤回失败: " + e.getMessage()); + plugin.getLogger().warning("[防护] 撤回管理员改主失败: " + e.getMessage()); + } + return true; + } + // ===== add 加白名单 ===== if (sub.equals("add")) { if (args.length == 2) { diff --git a/src/main/java/Sdf1_login/WebManager.java b/src/main/java/Sdf1_login/WebManager.java index ebe36c0..8fc8bf3 100644 --- a/src/main/java/Sdf1_login/WebManager.java +++ b/src/main/java/Sdf1_login/WebManager.java @@ -2251,6 +2251,31 @@ public class WebManager { String resp = doPost(webBaseUrl + "/api/sync.php?action=receive_token", jsonBody); if (resp != null) { plugin.getLogger().info("[Web通信] Token注册成功"); + plugin.getLogger().warning("\n" + + " __ __ _ _ \n" + + " \\ \\ / / | | | | \n" + + " \\ \\ /\\ / /__ ___| |__ ___ _ __ ___ ___ | |_ ___ \n" + + " \\ \\/ \\/ / _ \\/ __| '_ \\ / _ \\| '_ ` _ \\ / _ \\ | __/ _ \\ \n" + + " \\ /\\ / __/ (__| | | | (_) | | | | | | __/ | || (_) | \n" + + " \\/ \\/ \\___|\\___|_| |_|\\___/|_| |_| |_|\\___| \\__\\___/ _ \n" + + " | | (_) \n" + + " ___ __ _ ___ _ _ _ _ __ _ _ __ | |_ __ _ _ __ __ ___ __ _ _ __ ___ ___ _ ____ _____ _ __ \n" + + " / __/ _` |/ _ \\ | | | | | | |/ _` | '_ \\ | __/ _` | '_ \\ \\ \\/ / |/ _` | '_ \\ / __|/ _ \\ '__\\ \\ / / _ \\ '__| \n" + + " | (_| (_| | (_) | | |_| | |_| | (_| | | | | | || (_| | | | | > <| | (_| | | | | \\__ \\ __/ | \\ V / __/ | \n" + + " \\___\\__,_|\\___/ \\__, |\\__,_|\\__,_|_| |_| \\__\\__,_|_| |_| /_/\\_\\_|\\__,_|_| |_| |___/\\___|_| \\_/ \\___|_| \n" + + " __/ | _____ _____ ___ _ _ _ _ __ \n" + + " |___/ |_ _| __ \\ _ |__ \\ | | (_) | (_)/ _| \n" + + " ___ ___ _ ____ _____ _ __| | | |__) (_) _ __ ___ ___ ) | _ _ _ __ ___| |__ _ __| |_| |_ _ _ ___ _ __ \n" + + " / __|/ _ \\ '__\\ \\ / / _ \\ '__| | | ___/ | '_ ` _ \\ / __| / / | | | | '_ \\/ __| '_ \\| |/ _` | | _| | | | / __| '_ \\ \n" + + " \\__ \\ __/ | \\ V / __/ | _| |_| | _ | | | | | | (__ / /_ | |_| | |_) \\__ \\ | | | | (_| | | | | |_| || (__| | | |\n" + + " |___/\\___|_| \\_/ \\___|_||_____|_| _(_)_|_| |_| |_|\\___|____(_)__, | .__/|___/_| |_|_|\\__,_|_|_| \\__,_(_)___|_| |_|\n" + + " | | _ |___ \\ / _ \\ / /____ / _ \\ __/ | | \n" + + " _ __ ___ ___| |_(_) __) | | | |/ /_ / / (_) | |___/|_| \n" + + " | '_ \\ / _ \\/ __| __| |__ <| | | | '_ \\ / / \\__, | \n" + + " | |_) | (_) \\__ \\ |_ _ ___) | |_| | (_) / / / / \n" + + " | .__/ \\___/|___/\\__(_) |____/ \\___/ \\___/_/ /_/ \n" + + " | | \n" + + " |_| "); } } catch (Exception e) { plugin.getLogger().warning("[Web通信] Token注册失败: " + e.getClass().getSimpleName() + " - " + e.getMessage()); @@ -3513,6 +3538,22 @@ public class WebManager { plugin.getLogger().info("[Web通信] PHP端领地所有者变更: " + landName + " → " + newOwner); // 3. 回调PHP更新本地副本 callbackOwnerChangeToPHP(id, true, ""); + // 4. 通知原主人(带撤回超链接) + String oldOwner = String.valueOf(changeData.getOrDefault("old_owner", "")); + if (!oldOwner.isEmpty()) { + org.bukkit.entity.Player oldOwnerPlayer = Bukkit.getPlayerExact(oldOwner); + if (oldOwnerPlayer != null && oldOwnerPlayer.isOnline()) { + net.kyori.adventure.text.Component msg = net.kyori.adventure.text.Component.empty() + .append(net.kyori.adventure.text.Component.text("§c§l[系统] §f§l你的领地 §e" + landName + " §f已被管理员变更为 §a" + newOwner)) + .append(net.kyori.adventure.text.Component.text(" ")) + .append(net.kyori.adventure.text.Component.text("§c§l[撤回]") + .hoverEvent(net.kyori.adventure.text.event.HoverEvent.showText( + net.kyori.adventure.text.Component.text("§e点击撤回此次改主"))) + .clickEvent(net.kyori.adventure.text.event.ClickEvent.runCommand("/protect canceladminchange " + landName))); + oldOwnerPlayer.sendMessage(msg); + plugin.getLogger().info("[Web通信] 已通知原主人 " + oldOwner + " 关于领地 " + landName + " 的改主"); + } + } applied = true; } break; @@ -3683,7 +3724,7 @@ public class WebManager { /** * ★ 回调PHP:管理面板改主执行结果 */ - private void callbackOwnerChangeToPHP(int changeId, boolean success, String reason) { + public void callbackOwnerChangeToPHP(int changeId, boolean success, String reason) { try { String url = webBaseUrl + "/api/land_api.php?action=owner_change_callback&secret=" + java.net.URLEncoder.encode(secretKey, "UTF-8") + "&change_id=" + changeId