fix: 领地系统多项修复 - 管理员TAG验证/和平模式/袭击模式命名/效果管理GUI/添加成员功能
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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<UUID, String> playerPermTarget = new HashMap<>();
|
||||
|
||||
// ★ 效果管理待处理输入:UUID → [landName, inputType]
|
||||
private final Map<UUID, String[]> 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,6 +94,10 @@ public class AreaProtection implements Listener {
|
||||
final Map<java.util.UUID, Long> wandCooldownMap = new ConcurrentHashMap<>();
|
||||
// ★ 管理员配置输入等待:UUID → 配置key(GUI点击后等待玩家聊天输入)
|
||||
private final Map<java.util.UUID, String> pendingConfigInput = new ConcurrentHashMap<>();
|
||||
// ★ 添加成员输入等待:UUID → 领地名
|
||||
private final Map<java.util.UUID, String> pendingAddMemberInput = new ConcurrentHashMap<>();
|
||||
// ★ 效果管理待处理输入:UUID → [landName, inputType]
|
||||
private final Map<java.util.UUID, String[]> 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)
|
||||
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<String> 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 "创建价格(每㎡)";
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user