From aa8b7ce47aeaf2258dde3d4fcd41a7a989dee8aa Mon Sep 17 00:00:00 2001 From: youpaishidifu Date: Fri, 10 Jul 2026 19:55:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AE=9E=E4=BD=93=E7=A0=B4?= =?UTF-8?q?=E5=9D=8F=E9=98=B2=E6=8A=A4=EF=BC=9A=E6=96=B0=E5=A2=9E=E8=BD=BD?= =?UTF-8?q?=E5=85=B7=E4=B8=8E=E6=82=AC=E6=8C=82=E7=89=A9=E6=9D=83=E5=A8=81?= =?UTF-8?q?=E7=A0=B4=E5=9D=8F=E4=BA=8B=E4=BB=B6=E6=8B=A6=E6=88=AA=EF=BC=88?= =?UTF-8?q?VehicleDestroyEvent/HangingBreakEvent=EF=BC=89=EF=BC=8C?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=20L1=E7=A0=B4=E5=9D=8F=E6=80=BB=E5=BC=80?= =?UTF-8?q?=E5=85=B3=E2=86=92L2=E5=AE=9E=E4=BD=93=E4=BA=A4=E4=BA=92=20?= =?UTF-8?q?=E5=B1=82=E7=BA=A7=EF=BC=8C=E5=8C=BA=E5=9F=9F=E5=8F=96=E6=B3=95?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E4=B8=BA=E5=AE=9E=E4=BD=93=E5=9D=90=E6=A0=87?= =?UTF-8?q?=E4=BC=98=E5=85=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Sdf1_login/AreaProtection.java | 65 ++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/main/java/Sdf1_login/AreaProtection.java b/src/main/java/Sdf1_login/AreaProtection.java index ff2b641..55d45f3 100644 --- a/src/main/java/Sdf1_login/AreaProtection.java +++ b/src/main/java/Sdf1_login/AreaProtection.java @@ -9768,6 +9768,71 @@ public class AreaProtection implements Listener { return; } } + + // ===== ★ 载具破坏拦截(船/矿车等):VehicleDestroyEvent 是破坏的权威事件 ===== + // 仅靠 EntityDamageByEntityEvent 取消伤害,在部分版本/路径下不足以阻止载具被移除并掉落, + // 此处直接拦截破坏事件本身,确保 L1破坏总开关 / L2实体交互 对载具稳定生效。 + @EventHandler(priority = EventPriority.HIGHEST) + public void onVehicleDestroy(org.bukkit.event.vehicle.VehicleDestroyEvent e) { + org.bukkit.entity.Vehicle v = e.getVehicle(); + Entity attacker = e.getAttacker(); + if (!(attacker instanceof Player)) return; // 仅拦截玩家主动破坏,环境破坏(如撞击)不在此处理 + Player p = (Player) attacker; + // ★ 取区域方式与放置一致:优先载具坐标,玩家坐标兜底 + AreaConfig ac = getArea( + v.getWorld().getName(), + v.getLocation().getBlockX(), + v.getLocation().getBlockY(), + v.getLocation().getBlockZ()); + if (ac == null) { + ac = getArea( + p.getWorld().getName(), + p.getLocation().getBlockX(), + p.getLocation().getBlockY(), + p.getLocation().getBlockZ()); + } + if (ac == null) return; + // 层级:L1 破坏总开关 → L2 实体交互 + if (getEffectiveDeny(p, ac, "denyBlockBreak")) { + e.setCancelled(true); + p.sendMessage("§c§l[区域防护] §f禁止破坏载具"); + return; + } + if (getEffectiveDeny(p, ac, "denyEntityInteract")) { + e.setCancelled(true); + p.sendMessage("§c§l[区域防护] §f禁止破坏载具"); + } + } + + // ===== ★ 悬挂物破坏拦截(展示框/画等):HangingBreakEvent 是破坏的权威事件 ===== + @EventHandler(priority = EventPriority.HIGHEST) + public void onHangingBreak(org.bukkit.event.hanging.HangingBreakEvent e) { + org.bukkit.entity.Hanging hanging = e.getEntity(); + AreaConfig ac = findFrameArea(hanging); + if (ac == null) return; + // ★ HangingBreakEvent 本身无 getRemover(),玩家/实体破坏走子类 HangingBreakByEntityEvent + Entity remover = null; + if (e instanceof org.bukkit.event.hanging.HangingBreakByEntityEvent) { + remover = ((org.bukkit.event.hanging.HangingBreakByEntityEvent) e).getRemover(); + } + if (!(remover instanceof Player)) return; // 玩家主动破坏;箭矢命中由 onProjectileHit 处理 + Player p = (Player) remover; + // 层级:L1 破坏总开关 → L2 实体交互 → L3 展示框 + if (getEffectiveDeny(p, ac, "denyBlockBreak")) { + e.setCancelled(true); + p.sendMessage("§c§l[区域防护] §f禁止破坏实体"); + return; + } + if (getEffectiveDeny(p, ac, "denyEntityInteract")) { + e.setCancelled(true); + p.sendMessage("§c§l[区域防护] §f禁止破坏实体"); + return; + } + if (!getEffectiveDeny(p, ac, "denyItemFrame")) return; + e.setCancelled(true); + p.sendMessage("§c§l[区域防护] §f禁止破坏展示框"); + } + private AreaConfig findFrameArea(Entity frame) { Location loc = frame.getLocation(); int bx = loc.getBlockX();