From b2d5e0b84e7919eb79adfbb9d304f648a06530b8 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 14 Jul 2024 15:10:32 -0700 Subject: [PATCH] Add protection for Wind Charge explosions #2422 --- .../PhysicalInteractionListener.java | 40 ++++++++---- .../PhysicalInteractionListenerTest.java | 63 +++++++++++++++++++ 2 files changed, 91 insertions(+), 12 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PhysicalInteractionListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PhysicalInteractionListener.java index bef997cd8..76ea19691 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PhysicalInteractionListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PhysicalInteractionListener.java @@ -2,11 +2,14 @@ import org.bukkit.Material; import org.bukkit.Tag; +import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; +import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.entity.EntityInteractEvent; import org.bukkit.event.player.PlayerInteractEvent; @@ -55,24 +58,37 @@ public void onPlayerInteract(PlayerInteractEvent e) @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onProjectileHit(EntityInteractEvent e) { - if (!(e.getEntity() instanceof Projectile p)) + if (e.getEntity() instanceof Projectile p && p.getShooter() instanceof Player player) { + checkBlocks(e, player, e.getBlock()); + } + } + + private void checkBlocks(Event e, Player player, Block block) { + if (Tag.WOODEN_BUTTONS.isTagged(block.getType())) { + this.checkIsland(e, player, block.getLocation(), Flags.BUTTON); return; } - if (p.getShooter() instanceof Player player) - { - if (Tag.WOODEN_BUTTONS.isTagged(e.getBlock().getType())) - { - this.checkIsland(e, player, e.getBlock().getLocation(), Flags.BUTTON); - return; - } + if (Tag.PRESSURE_PLATES.isTagged(block.getType())) { + // Pressure plates + this.checkIsland(e, player, block.getLocation(), Flags.PRESSURE_PLATE); + } - if (Tag.PRESSURE_PLATES.isTagged(e.getBlock().getType())) - { - // Pressure plates - this.checkIsland(e, player, e.getBlock().getLocation(), Flags.PRESSURE_PLATE); + } + + /** + * Protects buttons and plates from being activated by projectiles that explode + * @param e - event + */ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onProjectileExplode(EntityExplodeEvent e) { + if (e.getEntity() instanceof Projectile p && p.getShooter() instanceof Player player) { + for (Block b : e.blockList()) { + this.checkBlocks(e, player, b); } } } + + } diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PhysicalInteractionListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PhysicalInteractionListenerTest.java index 0db36a177..60a3866cf 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PhysicalInteractionListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PhysicalInteractionListenerTest.java @@ -7,10 +7,13 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -25,6 +28,7 @@ import org.bukkit.entity.Zombie; import org.bukkit.event.Event.Result; import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.entity.EntityInteractEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; @@ -228,4 +232,63 @@ public void testOnProjectileHitProjectilePlayer() { assertTrue(p.name() +" failed", e.isCancelled()); }); } + + /** + * Test method for {@link PhysicalInteractionListener#onProjectileExplode(org.bukkit.event.entity.EntityExplodeEvent)}. + */ + @Test + public void testOnProjectileExplodeNotProjectile() { + Entity entity = mock(Entity.class); + List blocks = new ArrayList<>(); + EntityExplodeEvent e = new EntityExplodeEvent(entity, location, blocks, 0); + PhysicalInteractionListener i = new PhysicalInteractionListener(); + i.onProjectileExplode(e); + assertFalse(e.isCancelled()); + } + + /** + * Test method for {@link PhysicalInteractionListener#onProjectileExplode(org.bukkit.event.entity.EntityExplodeEvent)}. + */ + @Test + public void testOnProjectileExplodeProjectileNoPlayer() { + Projectile entity = mock(Projectile.class); + ProjectileSource source = mock(Creeper.class); + when(entity.getShooter()).thenReturn(source); + List blocks = new ArrayList<>(); + EntityExplodeEvent e = new EntityExplodeEvent(entity, location, blocks, 0); + PhysicalInteractionListener i = new PhysicalInteractionListener(); + i.onProjectileExplode(e); + assertFalse(e.isCancelled()); + } + + /** + * Test method for {@link PhysicalInteractionListener#onProjectileExplode(org.bukkit.event.entity.EntityExplodeEvent)}. + */ + @Test + public void testOnProjectileExplodeProjectilePlayer() { + Projectile entity = mock(Projectile.class); + when(entity.getShooter()).thenReturn(mockPlayer); + List blocks = new ArrayList<>(); + Block block1 = mock(Block.class); + Block block2 = mock(Block.class); + when(block1.getLocation()).thenReturn(location); + when(block2.getLocation()).thenReturn(location); + blocks.add(block1); + blocks.add(block2); + + EntityExplodeEvent e = new EntityExplodeEvent(entity, location, blocks, 0); + PhysicalInteractionListener i = new PhysicalInteractionListener(); + + // Test with wooden button + when(block1.getType()).thenReturn(Material.OAK_BUTTON); + when(Tag.WOODEN_BUTTONS.isTagged(Material.OAK_BUTTON)).thenReturn(true); + i.onProjectileExplode(e); + verify(notifier).notify(any(), eq("protection.protected")); + + // Test with pressure plate + when(block2.getType()).thenReturn(Material.STONE_PRESSURE_PLATE); + when(Tag.PRESSURE_PLATES.isTagged(Material.STONE_PRESSURE_PLATE)).thenReturn(true); + i.onProjectileExplode(e); + verify(notifier, times(3)).notify(any(), eq("protection.protected")); + } }