fix: 点燃权限全面重构——统一使用getEffectiveDeny做豁免+去重方法

1. 所有点燃拦截统一使用getEffectiveDeny()进行OWNER/ADMIN自动豁免
2. 移除了重复的方法定义(onIgnite/onPlayerInteractFire/BlockIgniteEvent各两个)
3. onPlayerInteractFire: 拦截打火石/火焰弹/岩浆桶/火床
4. onPlaceCampfire: 单独拦截火床/灵魂火床放置
5. onIgniteBlock: 拦截玩家放置火把等非直接用物品点燃
6. onFireSpreadNonPlayer: 拦截非玩家触发的火蔓延(如TNT红石)
7. onEntityChangeBlock: 拦截末影龙/末影螨改变方块为火/岩浆
This commit is contained in:
2026-07-03 00:58:30 +08:00
parent 3ece4c8369
commit 40cafa4b74
+110 -76
View File
@@ -4559,7 +4559,6 @@ public class AreaProtection implements Listener {
@EventHandler
public void onEntityChangeBlock(org.bukkit.event.entity.EntityChangeBlockEvent e) {
// 拦截末影龙/末影螨改变方块(如把水变成源)
if (e.getBlock().getType() == Material.FIRE || e.getBlock().getType() == Material.LAVA) {
AreaConfig ac = getArea(e.getBlock().getWorld().getName(),
e.getBlock().getX(), e.getBlock().getY(), e.getBlock().getZ());
@@ -4567,6 +4566,41 @@ public class AreaProtection implements Listener {
}
}
// ===== BlockIgniteEvent: 处理火把放置、打火石打地面等非玩家直接使用物品的场景 =====
@EventHandler
public void onIgniteBlock(BlockIgniteEvent e) {
Player p = e.getPlayer();
Block tgtBlock = e.getBlock();
// 非玩家触发(如火蔓延、TNT引爆)-> 不拦截,由BlockBurnEvent处理
if (p == null) return;
AreaConfig srcArea = getArea(p.getWorld().getName(),
p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ());
AreaConfig tgtArea = getArea(tgtBlock.getWorld().getName(),
tgtBlock.getX(), tgtBlock.getY(), tgtBlock.getZ());
// 使用统一豁免
boolean srcDenied = getEffectiveDeny(p, srcArea, "denyFire");
boolean tgtDenied = getEffectiveDeny(p, tgtArea, "denyFire");
if (srcDenied || tgtDenied) {
e.setCancelled(true);
p.sendMessage("§c§l[区域防护] §f此区域禁止点燃物品");
}
}
// ===== 火蔓延防漏网(非玩家触发) =====
@EventHandler
public void onFireSpreadNonPlayer(BlockIgniteEvent e) {
if (e.getPlayer() != null) return;
Block tgtBlock = e.getBlock();
AreaConfig ac = getArea(tgtBlock.getWorld().getName(),
tgtBlock.getX(), tgtBlock.getY(), tgtBlock.getZ());
if (ac != null && ac.denyFireSpread) {
e.setCancelled(true);
}
}
@EventHandler
public void onInventoryOpen(InventoryOpenEvent e) {
if (!(e.getPlayer() instanceof Player)) return;
@@ -9527,81 +9561,6 @@ public class AreaProtection implements Listener {
}
}
// ===== 区域内禁止点燃方块 =====
@EventHandler
public void onIgnite(BlockIgniteEvent e) {
Player p = e.getPlayer();
Block tgtBlock = e.getBlock();
AreaConfig srcArea = null;
AreaConfig tgtArea = null;
// 检查源领地(玩家所在位置)
if (p != null) {
srcArea = getArea(
p.getWorld().getName(),
p.getLocation().getBlockX(),
p.getLocation().getBlockY(),
p.getLocation().getBlockZ());
}
// 检查目标领地(被点燃方块位置)
tgtArea = getArea(
tgtBlock.getWorld().getName(),
tgtBlock.getX(), tgtBlock.getY(), tgtBlock.getZ());
// OWNER/ADMIN 豁免
if (p != null && srcArea != null && hasPermission(p, srcArea, PermissionLevel.OWNER)) return;
if (p != null && tgtArea != null && hasPermission(p, tgtArea, PermissionLevel.OWNER)) return;
// 任何一方denyFire=true就阻止
if ((srcArea != null && srcArea.denyFire) || (tgtArea != null && tgtArea.denyFire)) {
e.setCancelled(true);
if (p != null) {
p.sendMessage("§c§l[区域防护] §f此区域禁止点燃物品");
}
}
}
// ===== 玩家使用打火石/点燃物品时直接拦截 =====
@EventHandler
public void onPlayerInteractFire(PlayerInteractEvent e) {
Player p = e.getPlayer();
Action action = e.getAction();
Material mat = e.getItem() == null ? null : e.getItem().getType();
// 只拦截 RIGHT_CLICK_BLOCK/AIR 使用打火石/火床/TNT/岩浆桶
if (action != Action.RIGHT_CLICK_BLOCK && action != Action.RIGHT_CLICK_AIR) return;
if (mat != Material.FLINT_AND_STEEL && mat != Material.FIRE_CHARGE
&& mat != Material.CAMPFIRE && mat != Material.SOUL_CAMPFIRE
&& mat != Material.LAVA_BUCKET) {
return;
}
// 检查目标方块或玩家所处领地
Block clickedBlock = e.getClickedBlock();
AreaConfig ac1 = null;
AreaConfig ac2 = null;
// 玩家位置
ac1 = getArea(p.getWorld().getName(),
p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ());
// 点击的方块
if (clickedBlock != null) {
ac2 = getArea(clickedBlock.getWorld().getName(),
clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ());
}
// OWNER/ADMIN 豁免
if (hasPermission(p, ac1, PermissionLevel.OWNER)) return;
if (hasPermission(p, ac2, PermissionLevel.OWNER)) return;
if ((ac1 != null && ac1.denyFire) || (ac2 != null && ac2.denyFire)) {
e.setCancelled(true);
p.sendMessage("§c§l[区域防护] §f此区域禁止点燃物品");
}
}
// ===== 火焰弹/烈焰球拦截 =====
@EventHandler
@@ -9658,6 +9617,81 @@ public class AreaProtection implements Listener {
}
}
// ===== PlayerInteractEvent: 打火石/火焰弹右键使用拦截(带豁免) =====
// 注:火床放置拦截在onBlockPlace事件中处理
@EventHandler
public void onPlayerInteractFire(PlayerInteractEvent e) {
Player p = e.getPlayer();
Action action = e.getAction();
if (action != Action.RIGHT_CLICK_BLOCK && action != Action.RIGHT_CLICK_AIR) return;
Material mat = e.getItem() == null ? null : e.getItem().getType();
if (mat != Material.FLINT_AND_STEEL && mat != Material.FIRE_CHARGE
&& mat != Material.CAMPFIRE && mat != Material.SOUL_CAMPFIRE
&& mat != Material.LAVA_BUCKET) {
return;
}
AreaConfig srcArea = getArea(p.getWorld().getName(),
p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ());
Block clickedBlock = e.getClickedBlock();
AreaConfig tgtArea = null;
if (clickedBlock != null) {
tgtArea = getArea(clickedBlock.getWorld().getName(),
clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ());
}
// 使用统一的豁免逻辑(OWNER/ADMIN自动通过,visitor按领地默认权限)
boolean srcDenied = getEffectiveDeny(p, srcArea, "denyFire");
boolean tgtDenied = getEffectiveDeny(p, tgtArea, "denyFire");
if (srcDenied || tgtDenied) {
e.setCancelled(true);
p.sendMessage("§c§l[区域防护] §f此区域禁止点燃物品");
}
}
// ===== 火床放置拦截 =====
@EventHandler
public void onPlaceCampfire(BlockPlaceEvent e) {
Material placed = e.getItemInHand().getType();
if (placed != Material.CAMPFIRE && placed != Material.SOUL_CAMPFIRE) return;
Player p = e.getPlayer();
AreaConfig ac = getArea(p.getWorld().getName(),
p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ());
// OWNER/ADMIN 豁免
if (hasPermission(p, ac, PermissionLevel.OWNER)) return;
// visitor: 用领地默认权限
if (ac != null && ac.denyFire) {
e.setCancelled(true);
p.sendMessage("§c§l[区域防护] §f此区域禁止放置火床");
}
}
// ===== BlockIgniteEvent: 处理火把放置、打火石打地面等非玩家直接使用物品的场景 =====
@EventHandler
public void onIgnite(BlockIgniteEvent e) {
Player p = e.getPlayer();
Block tgtBlock = e.getBlock();
// 非玩家触发(如火蔓延、TNT引爆)-> 不拦截,由BlockBurnEvent处理
if (p == null) return;
AreaConfig srcArea = getArea(p.getWorld().getName(),
p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ());
AreaConfig tgtArea = getArea(tgtBlock.getWorld().getName(),
tgtBlock.getX(), tgtBlock.getY(), tgtBlock.getZ());
// 使用统一豁免
boolean srcDenied = getEffectiveDeny(p, srcArea, "denyFire");
boolean tgtDenied = getEffectiveDeny(p, tgtArea, "denyFire");
if (srcDenied || tgtDenied) {
e.setCancelled(true);
p.sendMessage("§c§l[区域防护] §f此区域禁止点燃物品");
}
}
// ===== ★ 拴绳使用(给生物拴绳或拉拽)=====
@EventHandler
public void onLeash(PlayerInteractEntityEvent e) {