From bbf23aad316e57240bd775bb1117926e0fd01457 Mon Sep 17 00:00:00 2001 From: youpaishidifu Date: Wed, 24 Jun 2026 18:32:25 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=A2=86=E5=9C=B0=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E5=A4=9A=E9=A1=B9=E4=BF=AE=E5=A4=8D=20-=20=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=91=98TAG=E9=AA=8C=E8=AF=81/=E5=92=8C=E5=B9=B3=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F/=E8=A2=AD=E5=87=BB=E6=A8=A1=E5=BC=8F=E5=91=BD?= =?UTF-8?q?=E5=90=8D/=E6=95=88=E6=9E=9C=E7=AE=A1=E7=90=86GUI/=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=88=90=E5=91=98=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Sdf1_login/AreaCLIManager.java | 12 +- src/main/java/Sdf1_login/AreaGUIManager.java | 127 +++++++++++++++- src/main/java/Sdf1_login/AreaProtection.java | 145 +++++++++++++++++-- src/main/java/Sdf1_login/Main.java | 12 ++ 4 files changed, 271 insertions(+), 25 deletions(-) diff --git a/src/main/java/Sdf1_login/AreaCLIManager.java b/src/main/java/Sdf1_login/AreaCLIManager.java index 1b43059..42331aa 100644 --- a/src/main/java/Sdf1_login/AreaCLIManager.java +++ b/src/main/java/Sdf1_login/AreaCLIManager.java @@ -538,7 +538,7 @@ public class AreaCLIManager { String permName = getPermNameByKey(permKey); boolean newState = !oldState; // ★ newState是deny值:true=禁止,false=允许 - p.sendMessage("§a已切换 §e" + permName + " §7→ " + (!newState ? "§a已允许" : "§c已禁止")); + p.sendMessage("§a已切换 §e" + permName + " §7→ " + (newState ? "§a已启用" : "§c已关闭")); } /** @@ -615,7 +615,7 @@ public class AreaCLIManager { perms.add(new PermItem("mount", "骑乘坐具", !land.denyMount)); perms.add(new PermItem("ender_pearl", "投掷末影珍珠", !land.denyEnderPearl)); perms.add(new PermItem("thrown_projectiles", "投掷物(三叉戟/雪球/风蛋)", !land.denyThrownProjectiles)); - perms.add(new PermItem("raid", "禁止袭击", !land.denyRaid)); + perms.add(new PermItem("raid", "启用袭击", !land.denyRaid)); perms.add(new PermItem("bow", "弓箭射击", !land.denyBow)); perms.add(new PermItem("potion", "药水效果", !land.denyPotion)); perms.add(new PermItem("fire", "点燃", !land.denyFire)); @@ -636,7 +636,7 @@ public class AreaCLIManager { perms.add(new PermItem("wool_shear", "剪切羊毛/生物", !land.denyWoolShear)); perms.add(new PermItem("animal_feed", "投喂动物", !land.denyAnimalFeeding)); perms.add(new PermItem("glowing", "玩家发光", !land.denyGlowing)); - perms.add(new PermItem("peace_mode", "禁止和平模式", !land.peaceMode)); + perms.add(new PermItem("peace_mode", "启用和平模式", land.peaceMode)); return perms; } @@ -649,7 +649,7 @@ public class AreaCLIManager { case "mount": return "骑乘坐具"; case "ender_pearl": return "投掷末影珍珠"; case "thrown_projectiles": return "投掷物"; - case "raid": return "禁止袭击"; + case "raid": return "启用袭击"; case "bow": return "弓箭射击"; case "potion": return "药水效果"; case "fire": return "点燃"; @@ -670,7 +670,7 @@ public class AreaCLIManager { case "wool_shear": return "剪切羊毛"; case "animal_feed": return "投喂动物"; case "glowing": return "玩家发光"; - case "peace_mode": return "禁止和平模式"; + case "peace_mode": return "启用和平模式"; default: return key; } } @@ -966,7 +966,7 @@ public class AreaCLIManager { {"wool_shear", "剪切羊毛/生物", "denyWoolShear"}, {"animal_feed", "投喂动物", "denyAnimalFeeding"}, {"glowing", "玩家发光", "denyGlowing"}, - {"peace_mode", "禁止和平模式", "peaceMode"} + {"peace_mode", "启用和平模式", "peaceMode"} }; for (String[] def : permDefs) { diff --git a/src/main/java/Sdf1_login/AreaGUIManager.java b/src/main/java/Sdf1_login/AreaGUIManager.java index 99a338c..52bc959 100644 --- a/src/main/java/Sdf1_login/AreaGUIManager.java +++ b/src/main/java/Sdf1_login/AreaGUIManager.java @@ -34,6 +34,9 @@ public class AreaGUIManager implements Listener { private static final String T_LAND_SETTINGS = "§6§l领地设置"; private static final String T_MEMBER_PERM_LIST = "§6§l成员权限列表"; private static final String T_PLAYER_PERM = "§6§l成员权限"; + private static final String T_EFFECTS_MGMT = "§b§l效果管理"; + private static final String T_EFFECTS_CLEAR = "§b§l单清效果"; + private static final String T_EFFECTS_GIVE = "§b§l增益效果"; // 每页显示数量 private static final int PAGE_SIZE = 45; @@ -49,6 +52,9 @@ public class AreaGUIManager implements Listener { // ★ 玩家当前编辑的per-player目标玩家 private final Map playerPermTarget = new HashMap<>(); + // ★ 效果管理待处理输入:UUID → [landName, inputType] + private final Map pendingEffectInput = new HashMap<>(); + public AreaGUIManager(Main plugin, AreaProtection areaProtect) { this.plugin = plugin; this.areaProtect = areaProtect; @@ -497,7 +503,7 @@ public class AreaGUIManager implements Listener { } /** - * 打开添加成员菜单 + * 打开添加成员菜单 - 显示在线玩家 + 自定义输入 */ public void openAddMember(Player p, String landName) { managingLand.put(p.getUniqueId(), landName); @@ -524,6 +530,11 @@ public class AreaGUIManager implements Listener { slot++; } + // 自定义输入成员(位置45) + inv.setItem(45, createItem(Material.PAPER, "§e§l自定义输入成员", + "§7点击后在聊天栏输入玩家名", + "§7将添加到该领地")); + // 返回按钮(位置48) inv.setItem(48, createItem(Material.ARROW, "§c§l返回成员列表", "")); @@ -903,6 +914,21 @@ public class AreaGUIManager implements Listener { return; } + // 效果管理 + if (title.startsWith("§b§l效果管理") || title.startsWith("§b§l单清效果") || title.startsWith("§b§l增益效果")) { + event.setCancelled(true); + String landName = managingLand.get(p.getUniqueId()); + if (landName == null) return; + + // 从标题提取subPage + int subPage = 1; + if (title.contains("单清效果")) subPage = 2; + else if (title.contains("增益效果")) subPage = 3; + + handleEffectsManagementClick(p, raw, subPage, landName); + return; + } + // 添加成员 if (title.startsWith(T_ADD_MEMBER)) { event.setCancelled(true); @@ -921,6 +947,11 @@ public class AreaGUIManager implements Listener { openAddMember(p, landName); } } + } else if (raw == 45) { + // 自定义输入成员:打开聊天栏等待玩家名 + p.closeInventory(); + p.sendMessage("§e§l[添加成员] §f请输入要添加的玩家名:"); + areaProtect.setPendingAddMemberInput(p.getUniqueId(), landName); } else if (raw == 48) { openMemberList(p, landName, 0); } @@ -1006,7 +1037,7 @@ public class AreaGUIManager implements Listener { // 和平模式(位置13) Material peaceMat = land.peaceMode ? Material.LIME_DYE : Material.GRAY_DYE; inv.setItem(13, createItem(peaceMat, "§e§l和平模式", - "§7当前状态: " + (land.peaceMode ? "§a已启用" : "§c已禁用"), + "§7当前状态: " + (land.peaceMode ? "§a已启用" : "§c已关闭"), "§7新生物进入领地后有保护期", "", "§e点击切换")); @@ -1162,7 +1193,7 @@ public class AreaGUIManager implements Listener { /** * 打开效果管理菜单 */ - private void openEffectsManagement(Player p, String landName, int subPage) { + public void openEffectsManagement(Player p, String landName, int subPage) { managingLand.put(p.getUniqueId(), landName); AreaProtection.AreaConfig land = areaProtect.getLand(landName); @@ -1234,6 +1265,32 @@ public class AreaGUIManager implements Listener { p.openInventory(inv); } + // ========== 子菜单3:增益效果列表 ========== + else if (subPage == 3) { + Inventory inv = Bukkit.createInventory(null, 54, "§b§l增益效果 - " + landName); + + if (land.giveEffects.isEmpty()) { + inv.setItem(22, createItem(Material.BARRIER, "§7§l暂无增益效果", + "§7使用快捷指令添加: /protect cli effectsaddadd <效果名> [等级] [秒数]", + "", + "§e示例: /protect cli effectsaddadd 力量 2 300")); + } else { + for (int i = 0; i < Math.min(land.giveEffects.size(), 36); i++) { + String[] eff = land.giveEffects.get(i); + String desc = eff[0] + (eff.length > 1 ? " Lv" + eff[1] : "") + (eff.length > 2 ? " " + eff[2] + "秒" : ""); + inv.setItem(i, createItem(Material.GOLDEN_CARROT, "§a" + desc, + "§7点击移除此增益效果", + "§e序号: " + (i + 1))); + } + } + + inv.setItem(48, createItem(Material.ARROW, "§c§l返回效果管理", "")); + inv.setItem(53, createItem(Material.BOOK, "§a§l添加效果", + "§7点击后在聊天栏输入效果名(如:缓慢、中毒)")); + + p.openInventory(inv); + } + // ========== 子菜单3:增益效果列表 ========== else if (subPage == 3) { Inventory inv = Bukkit.createInventory(null, 54, "§b§l增益效果 - " + landName); @@ -1260,4 +1317,68 @@ public class AreaGUIManager implements Listener { p.openInventory(inv); } } + + /** + * 处理效果管理GUI点击事件 + */ + private void handleEffectsManagementClick(Player p, int raw, int subPage, String landName) { + AreaProtection.AreaConfig land = areaProtect.getLand(landName); + if (land == null) return; + + // 子菜单1:开关管理 + if (subPage == 1) { + if (raw == 11) { + // 切换清除所有负面效果 + land.clearAllBadEffects = !land.clearAllBadEffects; + areaProtect.saveAreaToDb(land); + openEffectsManagement(p, landName, 1); + } else if (raw == 13) { + // 切换禁止所有效果 + land.denyAllEffects = !land.denyAllEffects; + areaProtect.saveAreaToDb(land); + openEffectsManagement(p, landName, 1); + } else if (raw == 15) { + // 打开单清效果列表 + openEffectsManagement(p, landName, 2); + } else if (raw == 17) { + // 打开增益效果列表 + openEffectsManagement(p, landName, 3); + } else if (raw == 48) { + // 返回管理领地 + openLandManage(p, landName); + } + } + // 子菜单2:单清效果列表 + else if (subPage == 2) { + if (raw < land.clearEffects.size()) { + // 移除单清效果 + land.clearEffects.remove(raw); + areaProtect.saveAreaToDb(land); + openEffectsManagement(p, landName, 2); + } else if (raw == 48) { + openEffectsManagement(p, landName, 1); + } else if (raw == 53) { + // 打开聊天栏输入效果名 + p.closeInventory(); + p.sendMessage("§e§l[添加清除效果] §f请输入效果名(如:缓慢、中毒、凋零):"); + areaProtect.setPendingClearEffectInput(p.getUniqueId(), landName, "clear"); + } + } + // 子菜单3:增益效果列表 + else if (subPage == 3) { + if (raw < land.giveEffects.size()) { + // 移除增益效果 + land.giveEffects.remove(raw); + areaProtect.saveAreaToDb(land); + openEffectsManagement(p, landName, 3); + } else if (raw == 48) { + openEffectsManagement(p, landName, 1); + } else if (raw == 53) { + // 打开聊天栏输入增益效果 + p.closeInventory(); + p.sendMessage("§e§l[添加增益效果] §f请输入: 效果名 [等级] [秒数] (例: 力量 2 300)"); + areaProtect.setPendingClearEffectInput(p.getUniqueId(), landName, "give"); + } + } + } } \ No newline at end of file diff --git a/src/main/java/Sdf1_login/AreaProtection.java b/src/main/java/Sdf1_login/AreaProtection.java index bd7cb7e..880e1d9 100644 --- a/src/main/java/Sdf1_login/AreaProtection.java +++ b/src/main/java/Sdf1_login/AreaProtection.java @@ -94,6 +94,10 @@ public class AreaProtection implements Listener { final Map wandCooldownMap = new ConcurrentHashMap<>(); // ★ 管理员配置输入等待:UUID → 配置key(GUI点击后等待玩家聊天输入) private final Map pendingConfigInput = new ConcurrentHashMap<>(); + // ★ 添加成员输入等待:UUID → 领地名 + private final Map pendingAddMemberInput = new ConcurrentHashMap<>(); + // ★ 效果管理待处理输入:UUID → [landName, inputType] + private final Map pendingEffectInput = new ConcurrentHashMap<>(); // ★ 全局配置默认值 private int globalCreatePricePerSqm = 10; // 每㎡创建价格 @@ -2446,26 +2450,20 @@ public class AreaProtection implements Listener { /** * 检查玩家是否为区域防护管理员 - * 支持TAG和OP两种模式(不共存,按配置文件中的顺序优先) - * 全局管理员不受访客权限限制 + * 与 Main.isAdmin() 使用相同的 ScoreboardTag 机制 */ public boolean isAreaAdmin(Player player) { ConfigManager cfg = plugin.getConfigMgr(); - if (cfg == null) return player.isOp(); + if (cfg == null) return false; - String mode = cfg.areaProtectAdminMode; - if ("op".equals(mode)) { - // OP模式:只有OP是管理员 - return player.isOp(); - } else { - // TAG模式(默认):有指定Tag的玩家是管理员 - String tag = cfg.areaProtectAdminTag; - if (tag == null || tag.isEmpty()) return player.isOp(); - String playerName = player.getName(); - // 检查玩家是否拥有该权限节点(作为Tag的替代方案) - // 如果没有权限系统,直接检查名字是否匹配 - return player.hasPermission("area.admin") - || player.isOp(); // OP始终是管理员(fallback) + String tag = cfg.areaProtectAdminTag; + if (tag == null || tag.isEmpty()) return false; + + // 使用ScoreboardTag验证(与Main.isAdmin()一致) + try { + return player.getScoreboardTags().contains(tag); + } catch (Exception e) { + return false; } } @@ -7040,6 +7038,121 @@ public class AreaProtection implements Listener { return true; } + /** + * 设置等待添加成员输入状态 + */ + public void setPendingAddMemberInput(java.util.UUID uuid, String landName) { + pendingAddMemberInput.put(uuid, landName); + } + + /** + * 检查并处理添加成员输入 + * @return true 如果是添加成员输入,已处理 + */ + public boolean handleAddMemberInput(Player p, String message) { + String landName = pendingAddMemberInput.remove(p.getUniqueId()); + if (landName == null) return false; + + String playerName = message.trim(); + // 验证玩家名格式 + if (!playerName.matches("^[a-zA-Z0-9_]{3,16}$")) { + p.sendMessage("§c§l[添加成员] §f无效的玩家名格式(3-16位字母数字下划线): " + playerName); + p.sendMessage("§7请重新输入有效玩家名,或输入 cancel 取消"); + return true; + } + + // 检查玩家是否已存在(本地) + Player target = Bukkit.getPlayerExact(playerName); + if (target == null) { + // 玩家不在线,但仍然可以添加(因为可能在数据库中有记录) + p.sendMessage("§e§l[添加成员] §f玩家 " + playerName + " 当前不在线,但仍可添加为成员"); + } + + // 检查是否已是成员 + Set members = getLandMembers(landName); + if (members.contains(playerName)) { + p.sendMessage("§c§l[添加成员] §f" + playerName + " 已经是该领地成员"); + return true; + } + + // 添加成员 + addLandMember(landName, playerName); + p.sendMessage("§a§l[添加成员] §f已成功添加 " + playerName + " 为领地成员"); + + // 刷新GUI + if (plugin.areaGUIManager != null) { + plugin.areaGUIManager.openAddMember(p, landName); + } + return true; + } + + /** + * 设置等待效果管理输入状态 + */ + public void setPendingClearEffectInput(java.util.UUID uuid, String landName, String inputType) { + pendingEffectInput.put(uuid, new String[]{landName, inputType}); + } + + /** + * 检查并处理效果管理输入 + * @return true 如果是效果管理输入,已处理 + */ + public boolean handleEffectInput(Player p, String message) { + String[] landAndType = pendingEffectInput.remove(p.getUniqueId()); + if (landAndType == null) return false; + + String landName = landAndType[0]; + String inputType = landAndType[1]; + AreaProtection.AreaConfig land = getLand(landName); + if (land == null) { + p.sendMessage("§c领地不存在"); + return true; + } + + if ("clear".equals(inputType)) { + // 添加单清效果 + String effName = message.trim(); + if (effName.isEmpty()) { + p.sendMessage("§c§l[添加清除效果] §f效果名不能为空"); + return true; + } + if (!land.clearEffects.contains(effName)) { + land.clearEffects.add(effName); + saveAreaToDb(land); + p.sendMessage("§a§l[添加清除效果] §f已添加: " + effName); + } else { + p.sendMessage("§e§l[添加清除效果] §f效果 " + effName + " 已在列表中"); + } + } else if ("give".equals(inputType)) { + // 添加增益效果: 格式 效果名 [等级] [秒数] + String[] parts = message.trim().split("\\s+"); + if (parts.length < 1) { + p.sendMessage("§c§l[添加增益效果] §f请输入: 效果名 [等级] [秒数]"); + return true; + } + String effName = parts[0].trim(); + int effLv = 1; + int effDur = 300; // 默认5分钟 + try { + if (parts.length >= 2) effLv = Integer.parseInt(parts[1]); + if (parts.length >= 3) effDur = Integer.parseInt(parts[2]); + } catch (NumberFormatException ignored) { + p.sendMessage("§c等级和秒数必须是数字"); + return true; + } + String[] effRecord = {effName, String.valueOf(effLv), String.valueOf(effDur)}; + land.giveEffects.add(effRecord); + saveAreaToDb(land); + p.sendMessage("§a§l[添加增益效果] §f已添加: " + effName + " Lv" + effLv + " " + effDur + "秒"); + } + + // 刷新GUI + if (plugin.areaGUIManager != null) { + plugin.areaGUIManager.openEffectsManagement(p, landName, 1); + } + return true; + } + private String getConfigNameByKey(String key) { switch (key) { case "create_price_per_sqm": return "创建价格(每㎡)"; diff --git a/src/main/java/Sdf1_login/Main.java b/src/main/java/Sdf1_login/Main.java index 21d0536..e15593e 100644 --- a/src/main/java/Sdf1_login/Main.java +++ b/src/main/java/Sdf1_login/Main.java @@ -2535,6 +2535,18 @@ public class Main extends JavaPlugin return; } + // ★ 添加成员输入拦截(GUI点击后聊天栏输入玩家名) + if (areaProtection != null && areaProtection.handleAddMemberInput(p, msg)) { + e.setCancelled(true); + return; + } + + // ★ 效果管理输入拦截(GUI点击后聊天栏输入效果名) + if (areaProtection != null && areaProtection.handleEffectInput(p, msg)) { + e.setCancelled(true); + return; + } + // ===== 菜单聊天输入 ===== if (getMenu().isEditing(p.getName())) { e.setCancelled(true);