diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java index ba58b48e..fe02c2eb 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java @@ -215,6 +215,7 @@ public void loadConfiguration() { blockEnderDragonPortalCreation = getBoolean("mobs.block-enderdragon-portal-creation", false); blockFireballExplosions = getBoolean("mobs.block-fireball-explosions", false); blockFireballBlockDamage = getBoolean("mobs.block-fireball-block-damage", false); + blockWindChargeExplosions = getBoolean("mobs.block-windcharge-explosions", false); antiWolfDumbness = getBoolean("mobs.anti-wolf-dumbness", false); allowTamedSpawns = getBoolean("mobs.allow-tamed-spawns", true); disableEndermanGriefing = getBoolean("mobs.disable-enderman-griefing", false); diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/event/block/AbstractBlockEvent.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/event/block/AbstractBlockEvent.java index 8e119252..02fac016 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/event/block/AbstractBlockEvent.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/event/block/AbstractBlockEvent.java @@ -45,7 +45,7 @@ * This event is an internal event. We do not recommend handling or throwing * this event or its subclasses as the interface is highly subject to change. */ -abstract class AbstractBlockEvent extends DelegateEvent implements BulkEvent { +public abstract class AbstractBlockEvent extends DelegateEvent implements BulkEvent { private final World world; private List blocks; diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java index 9aafddb9..1a523158 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java @@ -25,6 +25,7 @@ import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.bukkit.cause.Cause; import com.sk89q.worldguard.bukkit.event.DelegateEvent; +import com.sk89q.worldguard.bukkit.event.block.AbstractBlockEvent; import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent; import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent; import com.sk89q.worldguard.bukkit.event.block.UseBlockEvent; @@ -46,10 +47,12 @@ import com.sk89q.worldguard.bukkit.util.Materials; import com.sk89q.worldguard.config.WorldConfiguration; import com.sk89q.worldguard.protection.flags.Flags; +import com.sk89q.worldguard.protection.flags.StateFlag; import io.papermc.lib.PaperLib; import io.papermc.paper.event.player.PlayerOpenSignEvent; import org.bukkit.Bukkit; import org.bukkit.Effect; +import org.bukkit.ExplosionResult; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; @@ -65,7 +68,6 @@ import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Waterlogged; import org.bukkit.block.data.type.Dispenser; -import org.bukkit.entity.AbstractWindCharge; import org.bukkit.entity.AreaEffectCloud; import org.bukkit.entity.Creeper; import org.bukkit.entity.Entity; @@ -358,14 +360,21 @@ public void onEntityChangeBlock(EntityChangeBlockEvent event) { @EventHandler(ignoreCancelled = true) public void onEntityExplode(EntityExplodeEvent event) { Entity entity = event.getEntity(); - if (entity instanceof AbstractWindCharge) { - UseBlockEvent useEvent = new UseBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR); - useEvent.getRelevantFlags().add(Flags.WIND_CHARGE_BURST); - useEvent.setSilent(true); - Events.fireBulkEventToCancel(event, useEvent); + AbstractBlockEvent wgEvent; + + if (event.getExplosionResult() == ExplosionResult.TRIGGER_BLOCK) { + wgEvent = new UseBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR); + } else if (event.getExplosionResult() == ExplosionResult.DESTROY || event.getExplosionResult() == ExplosionResult.DESTROY_WITH_DECAY) { + wgEvent = new BreakBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR); + } else { return; } - Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR)); + + wgEvent.getRelevantFlags().add(Entities.getExplosionFlag(event.getEntity())); + + wgEvent.setSilent(true); + Events.fireBulkEventToCancel(event, wgEvent); + if (entity instanceof Creeper) { Cause.untrackParentCause(entity); } @@ -584,7 +593,7 @@ public void onEntityInteract(EntityInteractEvent event) { @EventHandler(ignoreCancelled = true) public void onBlockFertilize(BlockFertilizeEvent event) { - if (event.getBlocks().isEmpty()) return; + if (event.getBlocks().isEmpty()) return; Cause cause = create(event.getPlayer(), event.getBlock()); Events.fireToCancel(event, new PlaceBlockEvent(event, cause, event.getBlock().getWorld(), event.getBlocks())); } @@ -750,7 +759,7 @@ public void onHangingBreak(HangingBreakEvent event) { if (event.isCancelled() && remover instanceof Player) { playDenyEffect((Player) remover, event.getEntity().getLocation()); } - } else if (event.getCause() == HangingBreakEvent.RemoveCause.EXPLOSION){ + } else if (event.getCause() == HangingBreakEvent.RemoveCause.EXPLOSION) { DestroyEntityEvent destroyEntityEvent = new DestroyEntityEvent(event, Cause.unknown(), event.getEntity()); destroyEntityEvent.getRelevantFlags().add(Flags.OTHER_EXPLOSION); if (event.getEntity() instanceof ItemFrame) { @@ -1112,7 +1121,7 @@ public void onLingeringApply(AreaEffectCloudApplyEvent event) { } @EventHandler(ignoreCancelled = true) - public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event){ + public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) { onPlayerInteractEntity(event); } diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardEntityListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardEntityListener.java index 7ea3bf47..111cffdd 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardEntityListener.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardEntityListener.java @@ -44,6 +44,7 @@ import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockState; +import org.bukkit.entity.AbstractWindCharge; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Creeper; import org.bukkit.entity.EnderCrystal; @@ -311,13 +312,17 @@ private void onEntityDamageByProjectile(EntityDamageByEntityEvent event) { return; } } - if (event.getDamager() instanceof Fireball) { - Fireball fireball = (Fireball) event.getDamager(); + if (event.getDamager() instanceof Fireball fireball) { if (fireball instanceof WitherSkull) { if (wcfg.blockWitherSkullExplosions) { event.setCancelled(true); return; } + } else if (fireball instanceof AbstractWindCharge) { + if (wcfg.blockWindChargeExplosions) { + event.setCancelled(true); + return; + } } else { if (wcfg.blockFireballExplosions) { event.setCancelled(true); @@ -325,8 +330,9 @@ private void onEntityDamageByProjectile(EntityDamageByEntityEvent event) { } } if (wcfg.useRegions) { + WorldGuardPlugin.inst().getLogger().info("Getting damager type " + event.getDamager().getType()); RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery(); - if (!query.testState(localPlayer.getLocation(), localPlayer, Flags.GHAST_FIREBALL) && wcfg.explosionFlagCancellation) { + if (!query.testState(localPlayer.getLocation(), localPlayer, Entities.getExplosionFlag(event.getDamager())) && wcfg.explosionFlagCancellation) { event.setCancelled(true); return; } @@ -483,6 +489,11 @@ public void onEntityExplode(EntityExplodeEvent event) { event.blockList().clear(); return; } + } else if (ent instanceof AbstractWindCharge) { + if (wcfg.blockWindChargeExplosions) { + event.setCancelled(true); + return; + } } else { if (wcfg.blockFireballExplosions) { event.setCancelled(true); @@ -493,16 +504,6 @@ public void onEntityExplode(EntityExplodeEvent event) { return; } } - // allow wither skull blocking since there is no dedicated flag atm - if (wcfg.useRegions) { - for (Block block : event.blockList()) { - if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(block.getLocation())).testState(null, Flags.GHAST_FIREBALL)) { - event.blockList().clear(); - if (wcfg.explosionFlagCancellation) event.setCancelled(true); - return; - } - } - } } else if (ent instanceof Wither) { if (wcfg.blockWitherExplosions) { event.setCancelled(true); @@ -512,34 +513,14 @@ public void onEntityExplode(EntityExplodeEvent event) { event.blockList().clear(); return; } - if (wcfg.useRegions) { - for (Block block : event.blockList()) { - if (!StateFlag.test(WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().queryState(BukkitAdapter.adapt(block.getLocation()), - (RegionAssociable) null, Flags.WITHER_DAMAGE))) { - event.blockList().clear(); - event.setCancelled(true); - return; - } - } - } } else { // unhandled entity if (wcfg.blockOtherExplosions) { event.setCancelled(true); return; } - if (wcfg.useRegions) { - for (Block block : event.blockList()) { - if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(block.getLocation())).testState(null, Flags.OTHER_EXPLOSION)) { - event.blockList().clear(); - if (wcfg.explosionFlagCancellation) event.setCancelled(true); - return; - } - } - } } - if (wcfg.signChestProtection) { for (Block block : event.blockList()) { if (wcfg.isChestProtected(BukkitAdapter.adapt(block.getLocation()))) { @@ -592,6 +573,11 @@ public void onExplosionPrime(ExplosionPrimeEvent event) { event.setCancelled(true); return; } + } else if (event instanceof AbstractWindCharge) { + if (wcfg.blockWindChargeExplosions) { + event.setCancelled(true); + return; + } } } diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Entities.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Entities.java index 8a89e7a7..205d0b64 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Entities.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Entities.java @@ -19,6 +19,9 @@ package com.sk89q.worldguard.bukkit.util; +import com.sk89q.worldguard.protection.flags.Flags; +import com.sk89q.worldguard.protection.flags.StateFlag; +import org.bukkit.entity.AbstractWindCharge; import org.bukkit.entity.Allay; import org.bukkit.entity.Ambient; import org.bukkit.entity.ArmorStand; @@ -28,6 +31,8 @@ import org.bukkit.entity.EnderDragon; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Fireball; +import org.bukkit.entity.Firework; import org.bukkit.entity.Flying; import org.bukkit.entity.Hanging; import org.bukkit.entity.LivingEntity; @@ -43,11 +48,13 @@ import org.bukkit.entity.TNTPrimed; import org.bukkit.entity.Tameable; import org.bukkit.entity.Vehicle; +import org.bukkit.entity.Wither; import org.bukkit.entity.minecart.ExplosiveMinecart; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.inventory.InventoryHolder; import org.bukkit.projectiles.ProjectileSource; +import javax.annotation.Nonnull; import javax.annotation.Nullable; public final class Entities { @@ -245,4 +252,19 @@ public static boolean isPluginSpawning(CreatureSpawnEvent.SpawnReason spawnReaso default -> false; }; } + + /** + * Get the explosion flag relevant for an entity type. + * @param entity the entity + * @return the relevant StateFlag or OTHER_EXPLOSION if none is matching + */ + public static @Nonnull StateFlag getExplosionFlag(Entity entity) { + return switch (entity) { + case AbstractWindCharge abstractWindCharge -> Flags.WIND_CHARGE_BURST; + case Firework firework -> Flags.FIREWORK_DAMAGE; + case Fireball fireball -> Flags.GHAST_FIREBALL; + case Wither wither -> Flags.WITHER_DAMAGE; + case null, default -> Flags.OTHER_EXPLOSION; + }; + } } diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java index ea0e2f04..28032158 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java @@ -22,6 +22,7 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.sk89q.worldguard.protection.flags.Flags; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.entity.EntityType; diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java b/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java index df3d5fc1..0f0c2460 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java @@ -101,6 +101,7 @@ public abstract class WorldConfiguration { public boolean blockEnderDragonPortalCreation; public boolean blockFireballExplosions; public boolean blockFireballBlockDamage; + public boolean blockWindChargeExplosions; public boolean blockOtherExplosions; public boolean blockEntityPaintingDestroy; public boolean blockEntityItemFrameDestroy;