修复6项区域防护问题:

1. 移除独立成员权限面板,合并到成员列表左键编辑
2. 新增攻击生物权限(denyMobAttack):字段/DB迁移/事件处理/GUI/CLI
3. CLI效果编辑:增益效果添加等级/时长编辑按钮+聊天输入
4. 投喂动物修复:isAnimalFood检测动物食物+动态命名(禁止投喂/允许投喂)
5. 领地传送修复:GUI传送优先传送点→安全位置搜索(中心+40次随机)
6. 拾取节流:5~10秒随机间隔+5条随机提示轮换
This commit is contained in:
2026-06-26 16:31:39 +08:00
parent 3402a56d1c
commit 11e1d27013
3 changed files with 240 additions and 39 deletions
+51 -5
View File
@@ -530,6 +530,7 @@ public class AreaCLIManager {
case "crop_harvest": oldState = land.denyCropHarvest; land.denyCropHarvest = !land.denyCropHarvest; break;
case "wool_shear": oldState = land.denyWoolShear; land.denyWoolShear = !land.denyWoolShear; break;
case "animal_feed": oldState = land.denyAnimalFeeding; land.denyAnimalFeeding = !land.denyAnimalFeeding; break;
case "mob_attack": oldState = land.denyMobAttack; land.denyMobAttack = !land.denyMobAttack; break;
case "glowing": oldState = land.denyGlowing; land.denyGlowing = !land.denyGlowing; break;
case "peace_mode": oldState = land.peaceMode; land.peaceMode = !land.peaceMode; break;
}
@@ -584,6 +585,7 @@ public class AreaCLIManager {
case "crop_harvest": return "denyCropHarvest";
case "wool_shear": return "denyWoolShear";
case "animal_feed": return "denyAnimalFeeding";
case "mob_attack": return "denyMobAttack";
case "glowing": return "denyGlowing";
case "peace_mode": return "peaceMode";
default: return shortKey;
@@ -637,7 +639,8 @@ public class AreaCLIManager {
perms.add(new PermItem("lead", "拴绳使用", !land.denyLead));
perms.add(new PermItem("crop_harvest", land.denyCropHarvest ? "禁用农作物收获" : "启用农作物收获", !land.denyCropHarvest));
perms.add(new PermItem("wool_shear", "剪切羊毛/生物", !land.denyWoolShear));
perms.add(new PermItem("animal_feed", "投喂动物", !land.denyAnimalFeeding));
perms.add(new PermItem("animal_feed", land.denyAnimalFeeding ? "禁止投喂" : "允许投喂动物", !land.denyAnimalFeeding));
perms.add(new PermItem("mob_attack", land.denyMobAttack ? "禁止攻击生物" : "允许攻击生物", !land.denyMobAttack));
perms.add(new PermItem("glowing", "玩家发光", !land.denyGlowing));
perms.add(new PermItem("peace_mode", "和平模式", land.peaceMode));
return perms;
@@ -673,6 +676,7 @@ public class AreaCLIManager {
case "crop_harvest": return "农作物收获";
case "wool_shear": return "剪切羊毛";
case "animal_feed": return "投喂动物";
case "mob_attack": return "攻击生物";
case "glowing": return "玩家发光";
case "peace_mode": return "和平模式";
default: return key;
@@ -986,6 +990,7 @@ public class AreaCLIManager {
{"crop_harvest", "农作物收获", "denyCropHarvest"},
{"wool_shear", "剪切羊毛/生物", "denyWoolShear"},
{"animal_feed", "投喂动物", "denyAnimalFeeding"},
{"mob_attack", "攻击生物", "denyMobAttack"},
{"glowing", "玩家发光", "denyGlowing"},
{"peace_mode", "和平模式", "peaceMode"}
};
@@ -1008,6 +1013,14 @@ public class AreaCLIManager {
if (field.equals("denyCropHarvest")) {
name = landDefault ? "禁用农作物收获" : "启用农作物收获";
}
// ★ denyAnimalFeeding显示名称
if (field.equals("denyAnimalFeeding")) {
name = landDefault ? "禁止投喂" : "允许投喂动物";
}
// ★ denyMobAttack显示名称
if (field.equals("denyMobAttack")) {
name = landDefault ? "禁止攻击生物" : "允许攻击生物";
}
// 如果有per-player覆盖,使用覆盖值;否则使用领地默认
if (playerPerms.containsKey(field)) {
@@ -1155,11 +1168,21 @@ public class AreaCLIManager {
for (int i = 0; i < land.giveEffects.size(); i++) {
String[] eff = land.giveEffects.get(i);
String desc = eff[0] + (eff.length > 1 ? " Lv" + eff[1] : "") + (eff.length > 2 ? " §f" + eff[2] + "秒" : "");
String level = eff.length > 1 ? eff[1] : "1";
String duration = eff.length > 2 ? eff[2] : "300";
p.sendMessage(Component.empty()
.append(Component.text("§a- " + desc))
.append(Component.text(" §c[x]"))
.hoverEvent(HoverEvent.showText(Component.text("§e点击移除增益效果 '" + desc + "'")))
.clickEvent(ClickEvent.runCommand("/protect cli effectsaddremove " + landName + " " + (i + 1))));
.append(Component.text("§a- " + desc + " "))
.append(Component.text("§b[等级:" + level + "]")
.hoverEvent(HoverEvent.showText(Component.text("§e点击编辑等级")))
.clickEvent(ClickEvent.runCommand("/protect cli effectsaddedit " + landName + " " + (i + 1) + " level")))
.append(Component.text(" "))
.append(Component.text("§d[时长:" + duration + "s]")
.hoverEvent(HoverEvent.showText(Component.text("§e点击编辑时长(秒)")))
.clickEvent(ClickEvent.runCommand("/protect cli effectsaddedit " + landName + " " + (i + 1) + " duration")))
.append(Component.text(" "))
.append(Component.text("§c[x]")
.hoverEvent(HoverEvent.showText(Component.text("§c点击移除增益效果 '" + desc + "'")))
.clickEvent(ClickEvent.runCommand("/protect cli effectsaddremove " + landName + " " + (i + 1)))));
}
}
@@ -1305,6 +1328,29 @@ public class AreaCLIManager {
areaProtect.saveAreaToDb(land);
}
/**
* ★ 开始编辑增益效果的等级或时长(等待玩家输入)
*/
public void startEditGiveEffect(Player p, String landName, String indexStr, String editField) {
AreaProtection.AreaConfig land = areaProtect.getLand(landName);
if (land == null) { p.sendMessage(Component.text("§c领地不存在")); return; }
int idx;
try { idx = Integer.parseInt(indexStr); } catch (Exception e) { p.sendMessage(Component.text("§c序号无效")); return; }
if (idx < 1 || idx > land.giveEffects.size()) { p.sendMessage(Component.text("§c序号超出范围")); return; }
if (!editField.equals("level") && !editField.equals("duration")) {
p.sendMessage(Component.text("§c编辑类型必须是 level 或 duration"));
return;
}
// 记录待输入状态到 AreaProtection 的 pendingEffectInput
String inputType = "editGive_" + editField + "_" + idx;
areaProtect.setPendingEffectInput(p.getUniqueId(), landName, inputType, 3);
String fieldLabel = editField.equals("level") ? "等级" : "时长(秒)";
String[] eff = land.giveEffects.get(idx - 1);
String current = editField.equals("level") ? (eff.length > 1 ? eff[1] : "1") : (eff.length > 2 ? eff[2] : "300");
p.sendMessage(Component.text("§e请输入新的" + fieldLabel + "(当前: " + current + "),输入取消"));
p.sendMessage(Component.text("§7§l───────────────────────────────"));
}
/**
* 切换「禁止所有效果」开关
*/
+79 -28
View File
@@ -3,6 +3,7 @@ package Sdf1_login;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -438,6 +439,7 @@ public class AreaGUIManager implements Listener {
{"所有效果", "denyAllEffects"}, {"禁止展示框", "denyItemFrame"}, {"红石电路", "denyRedstoneInteraction"},
{"禁止门禁", "denyDoorInteraction"}, {"音频", "denyNoteblockJukebox"}, {"拴绳使用", "denyLead"},
{"农作物收获", "denyCropHarvest"}, {"剪切羊毛", "denyWoolShear"}, {"投喂动物", "denyAnimalFeeding"},
{"攻击生物", "denyMobAttack"},
{"玩家发光", "denyGlowing"}, {"和平模式", "peaceMode"}
};
@@ -461,6 +463,12 @@ public class AreaGUIManager implements Listener {
if (field.equals("denyCropHarvest")) {
name = landDefault ? "禁用农作物收获" : "启用农作物收获";
}
if (field.equals("denyAnimalFeeding")) {
name = landDefault ? "禁止投喂" : "允许投喂动物";
}
if (field.equals("denyMobAttack")) {
name = landDefault ? "禁止攻击生物" : "允许攻击生物";
}
// enabled = true 表示"允许操作"(即deny=false)
boolean allowed = !effective;
@@ -610,7 +618,8 @@ public class AreaGUIManager implements Listener {
perms.add(new PermEntry("拴绳使用", !land.denyLead));
perms.add(new PermEntry(land.denyCropHarvest ? "禁用农作物收获" : "启用农作物收获", !land.denyCropHarvest));
perms.add(new PermEntry("剪切羊毛/生物", !land.denyWoolShear));
perms.add(new PermEntry("投喂动物", !land.denyAnimalFeeding));
perms.add(new PermEntry(land.denyAnimalFeeding ? "禁止投喂" : "允许投喂动物", !land.denyAnimalFeeding));
perms.add(new PermEntry(land.denyMobAttack ? "禁止攻击生物" : "允许攻击生物", !land.denyMobAttack));
perms.add(new PermEntry("玩家发光", !land.denyGlowing));
perms.add(new PermEntry("和平模式", land.peaceMode));
return perms;
@@ -666,7 +675,8 @@ public class AreaGUIManager implements Listener {
case "禁用农作物收获": land.denyCropHarvest = !land.denyCropHarvest; break;
case "启用农作物收获": land.denyCropHarvest = !land.denyCropHarvest; break;
case "剪切羊毛/生物": land.denyWoolShear = !land.denyWoolShear; break;
case "投喂动物": land.denyAnimalFeeding = !land.denyAnimalFeeding; break;
case "禁止投喂": case "允许投喂动物": land.denyAnimalFeeding = !land.denyAnimalFeeding; break;
case "禁止攻击生物": case "允许攻击生物": land.denyMobAttack = !land.denyMobAttack; break;
case "玩家发光": land.denyGlowing = !land.denyGlowing; break;
case "和平模式": land.peaceMode = !land.peaceMode; break;
}
@@ -689,6 +699,36 @@ public class AreaGUIManager implements Listener {
return item;
}
/**
* 安全传送位置搜索:优先中心点,然后随机40次寻找头顶≥2空气+脚下非实体方块+在领地范围内
*/
private Location findSafeLocation(World w, int cx, int cz, int yMin, int yMax) {
// 先检查中心点
for (int y = Math.min(yMax, w.getMaxHeight()); y >= Math.max(yMin, w.getMinHeight()); y--) {
org.bukkit.block.Block foot = w.getBlockAt(cx, y, cz);
if (!foot.getType().isSolid()) continue;
if (w.getBlockAt(cx, y + 1, cz).getType().isSolid()) continue;
if (w.getBlockAt(cx, y + 2, cz).getType().isSolid()) continue;
return new Location(w, cx + 0.5, y + 1, cz + 0.5);
}
// 随机40次
java.util.Random rng = new java.util.Random();
int x1 = Math.min(cx - 5, cx + 5), x2 = Math.max(cx - 5, cx + 5);
int z1 = Math.min(cz - 5, cz + 5), z2 = Math.max(cz - 5, cz + 5);
for (int i = 0; i < 40; i++) {
int rx = x1 + rng.nextInt(Math.max(1, x2 - x1 + 1));
int rz = z1 + rng.nextInt(Math.max(1, z2 - z1 + 1));
for (int y = Math.min(yMax, w.getMaxHeight()); y >= Math.max(yMin, w.getMinHeight()); y--) {
org.bukkit.block.Block foot = w.getBlockAt(rx, y, rz);
if (!foot.getType().isSolid()) continue;
if (w.getBlockAt(rx, y + 1, rz).getType().isSolid()) continue;
if (w.getBlockAt(rx, y + 2, rz).getType().isSolid()) continue;
return new Location(w, rx + 0.5, y + 1, rz + 0.5);
}
}
return null; // 找不到安全位置
}
/**
* 处理菜单点击事件
*/
@@ -759,16 +799,22 @@ public class AreaGUIManager implements Listener {
p.closeInventory();
p.performCommand("protect 删除 " + land.name);
} else if (event.isShiftClick() && event.isLeftClick()) {
// 传送
// 传送 - 优先传送点,否则安全搜索中心
p.closeInventory();
Location tpLoc = new Location(
Bukkit.getWorld(land.world),
(land.x1 + land.x2) / 2.0,
land.yMin,
(land.z1 + land.z2) / 2.0
);
p.teleport(tpLoc);
// ★ GUI模式不发送聊天消息
if (land.warpWorld != null && !land.warpWorld.isEmpty()) {
World ww = Bukkit.getWorld(land.warpWorld);
if (ww != null) {
p.teleport(new Location(ww, land.warpX, land.warpY, land.warpZ, land.warpYaw, land.warpPitch));
}
} else {
int cx = (Math.min(land.x1, land.x2) + Math.max(land.x1, land.x2)) / 2;
int cz = (Math.min(land.z1, land.z2) + Math.max(land.z1, land.z2)) / 2;
World ww = Bukkit.getWorld(land.world);
if (ww != null) {
Location safeLoc = findSafeLocation(ww, cx, cz, land.yMin, land.yMax);
if (safeLoc != null) p.teleport(safeLoc);
}
}
}
} else if (raw == 45 && page > 0) {
openLandList(p, page - 1);
@@ -790,26 +836,31 @@ public class AreaGUIManager implements Listener {
openMemberList(p, landName, 0);
} else if (raw == 13) {
openVisitorPerm(p, landName, 0);
} else if (raw == 14) {
// ★ 成员权限(独立)
openMemberPermList(p, landName);
} else if (raw == 15) {
openLandSettings(p, landName);
} else if (raw == 16) {
openEffectsManagement(p, landName, 1);
} else if (raw == 31) {
// 传送
// 传送 - 优先传送点,否则安全搜索中心
p.closeInventory();
AreaProtection.AreaConfig land = areaProtect.getLand(landName);
if (land != null) {
Location tpLoc = new Location(
Bukkit.getWorld(land.world),
(land.x1 + land.x2) / 2.0,
land.yMin,
(land.z1 + land.z2) / 2.0
);
p.teleport(tpLoc);
// ★ GUI模式不发送聊天消息
if (land.warpWorld != null && !land.warpWorld.isEmpty()) {
// 有传送点 → 直接传送
World ww = Bukkit.getWorld(land.warpWorld);
if (ww != null) {
p.teleport(new Location(ww, land.warpX, land.warpY, land.warpZ, land.warpYaw, land.warpPitch));
}
} else {
// 无传送点 → 中心点安全搜索
int cx = (Math.min(land.x1, land.x2) + Math.max(land.x1, land.x2)) / 2;
int cz = (Math.min(land.z1, land.z2) + Math.max(land.z1, land.z2)) / 2;
World ww = Bukkit.getWorld(land.world);
if (ww != null) {
Location safeLoc = findSafeLocation(ww, cx, cz, land.yMin, land.yMax);
if (safeLoc != null) p.teleport(safeLoc);
}
}
}
} else if (raw == 48) {
openLandList(p, 0);
@@ -832,8 +883,8 @@ public class AreaGUIManager implements Listener {
if (raw >= 0 && raw < (end - start)) {
String member = memberList.get(start + raw);
if (event.isLeftClick()) {
// 左键:编辑权限(打开访客权限页面)
openVisitorPerm(p, landName, 0);
// 左键:编辑该成员的独立权限
openPlayerPerm(p, landName, member);
} else if (event.isRightClick()) {
// 右键:移除成员
areaProtect.removeLandMember(landName, member);
@@ -923,7 +974,7 @@ public class AreaGUIManager implements Listener {
if (raw == 22) {
ItemStack item = event.getView().getTopInventory().getItem(raw);
if (item != null && item.getType() == Material.GOLD_BLOCK) {
openMemberPermList(p, landName);
openMemberList(p, landName, 0);
return;
}
}
@@ -959,7 +1010,7 @@ public class AreaGUIManager implements Listener {
// 清除所有自定义权限
areaProtect.setPlayerPermJson(landId, targetPlayer, "");
// ★ GUI模式不发送聊天消息
openMemberPermList(p, landName);
openMemberList(p, landName, 0);
} else if (raw == 47) {
// ★ 管理员按钮:切换管理员状态
org.bukkit.entity.Player targetBukkit = Bukkit.getPlayerExact(targetPlayer);
@@ -996,7 +1047,7 @@ public class AreaGUIManager implements Listener {
openPlayerPerm(p, landName, targetPlayer);
} else if (raw == 49) {
// 返回成员列表
openMemberPermList(p, landName);
openMemberList(p, landName, 0);
}
return;
}
+110 -6
View File
@@ -151,6 +151,15 @@ public class AreaProtection implements Listener {
// 待清理的效果列表(与延时任务配合)
private final Map<UUID, List<PotionEffectType>> pendingClearEffects
= new ConcurrentHashMap<>();
// ★ 拾取消息节流(5~10秒随机间隔)
private final Map<UUID, Long> lastPickupMsgTime = new ConcurrentHashMap<>();
private static final String[] PICKUP_MSGS = {
"§c§l[区域防护] §f禁止拾取物品",
"§c§l[区域防护] §f此区域不允许拾取",
"§c§l[区域防护] §f拾取功能已禁用",
"§c§l[区域防护] §f你无法在此区域拾取物品",
"§c§l[区域防护] §f请离开领地后再拾取"
};
@@ -980,6 +989,7 @@ public class AreaProtection implements Listener {
try { ac.denyWoolShear = rs.getInt("deny_wool_shear") == 1; } catch (Exception ignored) {}
try { ac.denyAnimalFeeding = rs.getInt("deny_animal_feeding") == 1; } catch (Exception ignored) {}
try { ac.denyContainer = rs.getInt("deny_container") == 1; } catch (Exception ignored) {}
try { ac.denyMobAttack = rs.getInt("deny_mob_attack") == 1; } catch (Exception ignored) {}
try { ac.warpX = rs.getDouble("warp_x"); } catch (Exception ignored) {}
try { ac.warpY = rs.getDouble("warp_y"); } catch (Exception ignored) {}
try { ac.warpZ = rs.getDouble("warp_z"); } catch (Exception ignored) {}
@@ -1173,6 +1183,8 @@ public class AreaProtection implements Listener {
try { stmt.executeUpdate("ALTER TABLE area_lands ADD COLUMN warp_world TEXT DEFAULT ''"); } catch (Exception ignored) {}
// ★ 容器管理权限列(旧表缺失会导致INSERT OR REPLACE失败)
try { stmt.executeUpdate("ALTER TABLE area_lands ADD COLUMN deny_container INTEGER DEFAULT 0"); } catch (Exception ignored) {}
// ★ 玩家攻击生物权限列
try { stmt.executeUpdate("ALTER TABLE area_lands ADD COLUMN deny_mob_attack INTEGER DEFAULT 0"); } catch (Exception ignored) {}
// ★ 全局配置默认值
try {
@@ -2378,6 +2390,7 @@ public class AreaProtection implements Listener {
case "denyCropHarvest": return ac.denyCropHarvest;
case "denyWoolShear": return ac.denyWoolShear;
case "denyAnimalFeeding": return ac.denyAnimalFeeding;
case "denyMobAttack": return ac.denyMobAttack;
case "peaceMode": return ac.peaceMode;
default: return false;
}
@@ -4143,7 +4156,7 @@ public class AreaProtection implements Listener {
}
}
// ★ 拾取限制:denyPickup=true时禁止拾取地上物品
// ★ 拾取限制:denyPickup=true时禁止拾取地上物品(节流5~10秒随机提示)
@EventHandler
public void onPlayerPickup(PlayerPickupItemEvent e) {
Player p = e.getPlayer();
@@ -4154,7 +4167,14 @@ public class AreaProtection implements Listener {
p.getLocation().getBlockZ());
if (ac != null && getEffectiveDeny(p, ac, "denyPickup")) {
e.setCancelled(true);
p.sendMessage("§c§l[区域防护] §f禁止拾取物品");
// 节流:5~10秒随机间隔
long now = System.currentTimeMillis();
Long last = lastPickupMsgTime.get(p.getUniqueId());
long cooldown = 5000 + new java.util.Random().nextLong(5000); // 5~10秒
if (last == null || now - last > cooldown) {
lastPickupMsgTime.put(p.getUniqueId(), now);
p.sendMessage(PICKUP_MSGS[new java.util.Random().nextInt(PICKUP_MSGS.length)]);
}
}
}
@@ -4613,6 +4633,17 @@ public class AreaProtection implements Listener {
|| mat == Material.BEACON || mat.name().contains("LECTERN");
}
// ★ 检查是否为动物食物(包括玩家食物+动物专用食物)
private boolean isAnimalFood(Material mat) {
if (mat.isEdible()) return true; // 玩家食物(面包、胡萝卜等)
// 动物专用食物(玩家不可食用)
return mat == Material.WHEAT || mat == Material.BEETROOT_SEEDS
|| mat == Material.MELON_SEEDS || mat == Material.PUMPKIN_SEEDS
|| mat == Material.COCOA_BEANS || mat == Material.BONE_MEAL
|| mat == Material.NAME_TAG || mat == Material.SADDLE
|| mat.name().contains("SEEDS"); // 各种种子
}
// ★ 采集羊毛检测
@EventHandler
public void onShearEntity(PlayerShearEntityEvent e) {
@@ -4654,9 +4685,9 @@ public class AreaProtection implements Listener {
loc.getBlockZ());
if (ac == null) return;
if (!getEffectiveDeny(p, ac, "denyAnimalFeeding")) return;
// 检查玩家手持的物品是否是食物
// 检查玩家手持的物品是否是食物(isEdible()只检测玩家食物,需额外检测动物食物)
ItemStack hand = p.getInventory().getItemInMainHand();
if (hand != null && hand.getType().isEdible()) {
if (hand != null && hand.getType() != Material.AIR && isAnimalFood(hand.getType())) {
e.setCancelled(true);
p.sendMessage("§c§l[区域防护] §f禁止在此区域投喂动物");
}
@@ -5211,6 +5242,14 @@ public class AreaProtection implements Listener {
// 刷新:回到增益效果列表(subPage 3)
plugin.areaCLIManager.showEffectsManagement(p, args[2], 3);
break;
case "effectsaddedit":
// ★ 编辑增益效果等级或时长: 序号 level|duration
if (args.length < 5) {
p.sendMessage("§c用法: /protect cli effectsaddedit <领地名> <序号> <level|duration>");
break;
}
plugin.areaCLIManager.startEditGiveEffect(p, args[2], args[3], args[4]);
break;
case "create":
// 跳转到创建命令
// 直接转发
@@ -6820,8 +6859,8 @@ public class AreaProtection implements Listener {
+ "confiscate_msg, enable_announce, announce_template, txt_content, created_at, "
+ "deny_thrown_projectiles, deny_glowing, deny_redstone_interaction, deny_door_interaction, "
+ "deny_noteblock_jukebox, deny_lead, deny_crop_harvest, deny_wool_shear, deny_animal_feeding, "
+ "warp_x, warp_y, warp_z, warp_yaw, warp_pitch, warp_world, deny_container) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ "warp_x, warp_y, warp_z, warp_yaw, warp_pitch, warp_world, deny_container, deny_mob_attack) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
stmt.setString(1, ac.name);
stmt.setString(2, ac.owner != null ? ac.owner : "");
@@ -6887,6 +6926,7 @@ public class AreaProtection implements Listener {
stmt.setFloat(60, ac.warpPitch);
stmt.setString(61, ac.warpWorld != null ? ac.warpWorld : "");
stmt.setInt(62, ac.denyContainer ? 1 : 0);
stmt.setInt(63, ac.denyMobAttack ? 1 : 0);
stmt.executeUpdate();
stmt.close();
} catch (SQLException e) {
@@ -7254,6 +7294,13 @@ public class AreaProtection implements Listener {
pendingEffectInput.put(uuid, new String[]{landName, inputType, String.valueOf(subPage)});
}
/**
* ★ 通用设置效果输入状态
*/
public void setPendingEffectInput(java.util.UUID uuid, String landName, String inputType, int subPage) {
pendingEffectInput.put(uuid, new String[]{landName, inputType, String.valueOf(subPage)});
}
/**
* 检查并处理效果管理输入
* @return true 如果是效果管理输入,已处理
@@ -7346,6 +7393,46 @@ public class AreaProtection implements Listener {
land.giveEffects.add(effRecord);
saveAreaToDb(land);
p.sendMessage("§a§l[添加增益效果] §f已添加: §a" + effName + " §fLv" + effLv + " " + effDur + "秒");
} else if (inputType.startsWith("editGive_")) {
// ★ 编辑增益效果等级/时长: editGive_level_3 或 editGive_duration_3
String[] parts = inputType.split("_");
if (parts.length < 3) return true;
String editField = parts[1]; // level 或 duration
int idx;
try { idx = Integer.parseInt(parts[2]); } catch (Exception e) { return true; }
if (idx < 1 || idx > land.giveEffects.size()) {
p.sendMessage("§c序号超出范围");
return true;
}
if (message.trim().equalsIgnoreCase("取消")) {
p.sendMessage("§7已取消编辑");
if (plugin.areaCLIManager != null) plugin.areaCLIManager.showEffectsManagement(p, landName, 3);
return true;
}
String[] eff = land.giveEffects.get(idx - 1);
if ("level".equals(editField)) {
int newLevel;
try { newLevel = Integer.parseInt(message.trim()); } catch (Exception e) {
p.sendMessage("§c请输入有效数字");
return true;
}
if (newLevel < 1 || newLevel > 255) { p.sendMessage("§c等级范围1~255"); return true; }
if (eff.length < 2) { String[] tmp = new String[3]; System.arraycopy(eff, 0, tmp, 0, eff.length); eff = tmp; land.giveEffects.set(idx - 1, eff); }
eff[1] = String.valueOf(newLevel);
p.sendMessage("§a§l[编辑增益] §f已将 §e" + eff[0] + " §f等级修改为 " + newLevel);
} else {
int newDur;
try { newDur = Integer.parseInt(message.trim()); } catch (Exception e) {
p.sendMessage("§c请输入有效数字");
return true;
}
if (newDur < 1 || newDur > 86400) { p.sendMessage("§c时长范围1~86400秒"); return true; }
if (eff.length < 3) { String[] tmp = new String[3]; System.arraycopy(eff, 0, tmp, 0, Math.min(eff.length, 3)); eff = tmp; land.giveEffects.set(idx - 1, eff); }
eff[2] = String.valueOf(newDur);
p.sendMessage("§a§l[编辑增益] §f已将 §e" + eff[0] + " §f时长修改为 " + newDur + "秒");
}
saveAreaToDb(land);
if (plugin.areaCLIManager != null) plugin.areaCLIManager.showEffectsManagement(p, landName, 3);
}
// 刷新GUI,回到原来的subPage
@@ -7831,6 +7918,21 @@ public class AreaProtection implements Listener {
return;
}
// ===== 攻击生物逻辑 =====
if (!(e.getDamager() instanceof Player)) return;
if (e.getEntity() instanceof Player) return; // PVP走下面的逻辑
Player mobAttacker = (Player) e.getDamager();
AreaConfig acMob = getArea(
mobAttacker.getWorld().getName(),
mobAttacker.getLocation().getBlockX(),
mobAttacker.getLocation().getBlockY(),
mobAttacker.getLocation().getBlockZ());
if (acMob != null && getEffectiveDeny(mobAttacker, acMob, "denyMobAttack")) {
e.setCancelled(true);
mobAttacker.sendMessage("§c§l[区域防护] §f此区域禁止攻击生物");
return;
}
// ===== PVP 逻辑 =====
if (!(e.getDamager() instanceof Player)) return;
if (!(e.getEntity() instanceof Player)) return;
@@ -8325,6 +8427,8 @@ public class AreaProtection implements Listener {
public boolean denyWoolShear = false;
// ★ 投喂动物
public boolean denyAnimalFeeding = false;
// ★ 玩家攻击生物
public boolean denyMobAttack = false;
public boolean enableAnnounce = false;
public String announceTemplate = "";
public String txtContent = "";