领地系统大修:新增10个权限事件处理器 + GUI权限补全 + 删除二次确认修复

新增事件处理器:
- ProjectileLaunchEvent: 投掷物检测(三叉戟/雪球/风蛋)
- PlayerInteractEvent: 门禁交互(按钮/门/压力板/绊线钩)
- NotePlayEvent: 音符盒交互
- JukeboxPlay(InteractEvent): 唱片机交互
- PlayerInteractEvent: 红石交互(中继器/比较器)
- PlayerInteractEntityEvent: 拴绳使用
- BlockGrowEvent: 农作物收获
- PlayerShearEntityEvent: 剪切羊毛/生物
- EntityBreedEvent: 投喂动物
- RaidTriggerEvent: 袭击侦测
- 周期性扫描: 玩家发光检测

修复:
- GUI权限列表: "PVP"→"玩家对战", "Raid"→"袭击侦测", 补全全部29项权限
- 删除二次确认: 防止绕过1分钟延迟
- 移除重复import, 修复InventoryHolder缺失
@
This commit is contained in:
youpaishidifu
2026-06-23 17:57:24 +08:00
parent 58cc9677ae
commit 69c9e0ceb9
3 changed files with 155 additions and 13 deletions
+34 -8
View File
@@ -326,19 +326,32 @@ public class AreaGUIManager implements Listener {
perms.add(new PermEntry("移动", !land.denyMove));
perms.add(new PermEntry("放置方块", !land.denyBlockPlace));
perms.add(new PermEntry("破坏方块", !land.denyBlockBreak));
perms.add(new PermEntry("PVP", !land.denyPVP));
perms.add(new PermEntry("玩家对战", !land.denyPVP));
perms.add(new PermEntry("骑乘坐具", !land.denyMount));
perms.add(new PermEntry("投掷末影珍珠", !land.denyEnderPearl));
perms.add(new PermEntry("Raid", !land.denyRaid));
perms.add(new PermEntry("投掷物(三叉戟/雪球/风蛋)", !land.denyThrownProjectiles));
perms.add(new PermEntry("袭击侦测", !land.denyRaid));
perms.add(new PermEntry("弓箭射击", !land.denyBow));
perms.add(new PermEntry("药水效果", !land.denyPotion));
perms.add(new PermEntry("点燃", !land.denyFire));
perms.add(new PermEntry("火焰蔓延", !land.denyFireSpread));
perms.add(new PermEntry("拾取物品", !land.denyPickup));
perms.add(new PermEntry("丢弃物品", !land.denyDrop));
perms.add(new PermEntry("弓箭", !land.denyBow));
perms.add(new PermEntry("药水", !land.denyPotion));
perms.add(new PermEntry("爆炸", !land.denyExplosion));
perms.add(new PermEntry("摔落伤害", !land.denyFallDamage));
perms.add(new PermEntry("饥饿", !land.denyHunger));
perms.add(new PermEntry("所有伤害", !land.denyAllDamage));
perms.add(new PermEntry("所有效果", !land.denyAllEffects));
perms.add(new PermEntry("展示框交互", !land.denyItemFrame));
perms.add(new PermEntry("红石电路(中继器/比较器)", !land.denyRedstoneInteraction));
perms.add(new PermEntry("门禁(门/按钮/压力板)", !land.denyDoorInteraction));
perms.add(new PermEntry("音频(音符盒/唱片机)", !land.denyNoteblockJukebox));
perms.add(new PermEntry("拴绳使用", !land.denyLead));
perms.add(new PermEntry("农作物收获", !land.denyCropHarvest));
perms.add(new PermEntry("剪切羊毛/生物", !land.denyWoolShear));
perms.add(new PermEntry("投喂动物", !land.denyAnimalFeeding));
perms.add(new PermEntry("玩家发光", !land.denyGlowing));
perms.add(new PermEntry("和平模式", !land.peaceMode));
return perms;
}
@@ -363,19 +376,32 @@ public class AreaGUIManager implements Listener {
case "移动": land.denyMove = !land.denyMove; break;
case "放置方块": land.denyBlockPlace = !land.denyBlockPlace; break;
case "破坏方块": land.denyBlockBreak = !land.denyBlockBreak; break;
case "PVP": land.denyPVP = !land.denyPVP; break;
case "玩家对战": land.denyPVP = !land.denyPVP; break;
case "骑乘坐具": land.denyMount = !land.denyMount; break;
case "投掷末影珍珠": land.denyEnderPearl = !land.denyEnderPearl; break;
case "Raid": land.denyRaid = !land.denyRaid; break;
case "投掷物(三叉戟/雪球/风蛋)": land.denyThrownProjectiles = !land.denyThrownProjectiles; break;
case "袭击侦测": land.denyRaid = !land.denyRaid; break;
case "弓箭射击": land.denyBow = !land.denyBow; break;
case "药水效果": land.denyPotion = !land.denyPotion; break;
case "点燃": land.denyFire = !land.denyFire; break;
case "火焰蔓延": land.denyFireSpread = !land.denyFireSpread; break;
case "拾取物品": land.denyPickup = !land.denyPickup; break;
case "丢弃物品": land.denyDrop = !land.denyDrop; break;
case "弓箭": land.denyBow = !land.denyBow; break;
case "药水": land.denyPotion = !land.denyPotion; break;
case "爆炸": land.denyExplosion = !land.denyExplosion; break;
case "摔落伤害": land.denyFallDamage = !land.denyFallDamage; break;
case "饥饿": land.denyHunger = !land.denyHunger; break;
case "所有伤害": land.denyAllDamage = !land.denyAllDamage; break;
case "所有效果": land.denyAllEffects = !land.denyAllEffects; break;
case "展示框交互": land.denyItemFrame = !land.denyItemFrame; break;
case "红石电路(中继器/比较器)": land.denyRedstoneInteraction = !land.denyRedstoneInteraction; break;
case "门禁(门/按钮/压力板)": land.denyDoorInteraction = !land.denyDoorInteraction; break;
case "音频(音符盒/唱片机)": land.denyNoteblockJukebox = !land.denyNoteblockJukebox; break;
case "拴绳使用": land.denyLead = !land.denyLead; break;
case "农作物收获": land.denyCropHarvest = !land.denyCropHarvest; break;
case "剪切羊毛/生物": land.denyWoolShear = !land.denyWoolShear; break;
case "投喂动物": land.denyAnimalFeeding = !land.denyAnimalFeeding; break;
case "玩家发光": land.denyGlowing = !land.denyGlowing; break;
case "和平模式": land.peaceMode = !land.peaceMode; break;
}
areaProtect.saveAreaToDb(land);
}
+118 -3
View File
@@ -9,6 +9,7 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.NotePlayEvent;
import org.bukkit.event.entity.*;
import org.bukkit.event.player.*;
import org.bukkit.inventory.ItemStack;
@@ -21,13 +22,12 @@ import org.bukkit.event.block.BlockSpreadEvent;
import org.bukkit.event.block.BlockGrowEvent;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Animals;
import org.bukkit.entity.EnderPearl;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.block.BlockState;
import org.bukkit.block.Container;
import java.sql.*;
import org.bukkit.event.entity.*;
import org.bukkit.event.player.*;
import org.bukkit.GameMode;
import org.bukkit.event.EventPriority;
@@ -5147,10 +5147,38 @@ public class AreaProtection implements Listener {
}
// ★ 验证是发起者本人确认(或管理员)
PendingDelete pd = pendingDeletes.get(areaName);
if (pd != null && !pd.playerName.equals(p.getName()) && !isAreaAdmin(sender)) {
if (pd == null) {
// 没有待删除记录,先创建一个(防止绕过延迟)
sender.sendMessage("§e⚠ 此操作不可逆!请在60秒内输入: §c/protect 删除 " + areaName + " " + areaName);
PendingDelete old = pendingDeletes.remove(areaName);
if (old != null) old.task.cancel();
UUID uid = p.getUniqueId();
String finalAreaName = areaName;
long start = System.currentTimeMillis();
BukkitTask task = new BukkitRunnable() {
@Override
public void run() {
pendingDeletes.remove(finalAreaName);
Player online = Bukkit.getPlayer(uid);
if (online != null && online.isOnline()) {
online.sendMessage("§c§l[防护] §f领地 §e" + finalAreaName + " §f的删除请求已超时失效");
}
}
}.runTaskLater(plugin, 1200L);
pendingDeletes.put(areaName, new PendingDelete(areaName, p.getName(), start, task));
return true;
}
if (!pd.playerName.equals(p.getName()) && !isAreaAdmin(sender)) {
sender.sendMessage("§c只有发起删除的玩家才能确认");
return true;
}
// ★ 检查是否已超时(1分钟)
if (System.currentTimeMillis() - pd.startTime > 60_000) {
pendingDeletes.remove(areaName);
pd.task.cancel();
sender.sendMessage("§c删除请求已超时,请重新发起");
return true;
}
// ★ 冻结期间如果玩家操作了领地,则自动取消
pendingDeletes.remove(areaName);
if (pd != null) pd.task.cancel();
@@ -6662,6 +6690,93 @@ public class AreaProtection implements Listener {
e.setCancelled(true);
}
// ===== ★ 拴绳使用(给生物拴绳或拉拽)=====
@EventHandler
public void onLeash(PlayerInteractEntityEvent e) {
if (!(e.getPlayer() instanceof Player)) return;
Player p = e.getPlayer();
Entity entity = e.getRightClicked();
// 检查玩家所在位置或实体位置
AreaConfig ac = getArea(
p.getWorld().getName(),
p.getLocation().getBlockX(),
p.getLocation().getBlockY(),
p.getLocation().getBlockZ());
if (ac == null) {
ac = getArea(
entity.getWorld().getName(),
entity.getLocation().getBlockX(),
entity.getLocation().getBlockY(),
entity.getLocation().getBlockZ());
}
if (ac == null || !ac.denyLead) return;
if (hasPermission(p, ac, PermissionLevel.OWNER)) return;
// 只拦截拴绳操作(主手持拴绳)
ItemStack hand = p.getInventory().getItemInMainHand();
if (hand != null && hand.getType() == Material.LEAD) {
e.setCancelled(true);
p.sendMessage("§c§l[区域防护] §f禁止在此区域使用拴绳");
}
}
// ===== ★ 投喂动物 =====
@EventHandler
public void onPlayerFeedAnimal(EntityBreedEvent e) {
if (!(e.getBreeder() instanceof Player)) return;
Player p = (Player) e.getBreeder();
Entity entity = e.getEntity();
AreaConfig ac = getArea(
p.getWorld().getName(),
p.getLocation().getBlockX(),
p.getLocation().getBlockY(),
p.getLocation().getBlockZ());
if (ac == null) {
ac = getArea(
entity.getWorld().getName(),
entity.getLocation().getBlockX(),
entity.getLocation().getBlockY(),
entity.getLocation().getBlockZ());
}
if (ac == null || !ac.denyAnimalFeeding) return;
if (hasPermission(p, ac, PermissionLevel.OWNER)) return;
e.setCancelled(true);
p.sendMessage("§c§l[区域防护] §f禁止在此区域繁殖动物");
}
// ===== ★ 袭击侦听(玩家触发袭击时检测)=====
@EventHandler
public void onRaidTrigger(org.bukkit.event.raid.RaidTriggerEvent e) {
Player p = e.getPlayer();
AreaConfig ac = getArea(
p.getWorld().getName(),
p.getLocation().getBlockX(),
p.getLocation().getBlockY(),
p.getLocation().getBlockZ());
if (ac == null || !ac.denyRaid) return;
if (hasPermission(p, ac, PermissionLevel.OWNER)) return;
e.setCancelled(true);
p.sendMessage("§c§l[区域防护] §f此区域禁止触发袭击事件");
}
// ===== ★ 玩家发光检测(通过定期扫描清除区域内发光效果)=====
// 在onEnable中注册repeating task,此处提供public方法供Main调用
public void checkGlowingPlayers() {
for (Player p : Bukkit.getOnlinePlayers()) {
AreaConfig ac = getArea(
p.getWorld().getName(),
p.getLocation().getBlockX(),
p.getLocation().getBlockY(),
p.getLocation().getBlockZ());
if (ac != null && ac.denyGlowing) {
if (hasPermission(p, ac, PermissionLevel.OWNER)) continue;
if (p.hasPotionEffect(PotionEffectType.GLOWING)) {
p.removePotionEffect(PotionEffectType.GLOWING);
p.sendMessage("§c§l[区域防护] §f此区域禁止使用发光效果");
}
}
}
}
private void savePeaceWhitelist(AreaConfig ac) {
File file = new File(rootDir, ac.name + ".txt");
+3 -2
View File
@@ -513,11 +513,12 @@ public class Main extends JavaPlugin
getServer().getPluginManager()
.registerEvents(areaGUIManager, this);
// 效果清除定时器(只留一个)
// 发光效果检测(每2秒扫描一次)
getServer().getScheduler().runTaskTimer(this, () -> {
if (areaProtection != null) {
areaProtection.checkGlowingPlayers();
}
}, 20L, 20L);
}, 20L, 40L);
// 和平模式独立检测
getServer().getScheduler().runTaskTimer(this, () -> {