From 2733e3153572faa2f4f2af7f68fd11ecd075ddab Mon Sep 17 00:00:00 2001 From: tastybento Date: Tue, 9 Jul 2024 07:31:09 -0700 Subject: [PATCH 1/8] Remove nonNull annotation because it is wrong. --- .../world/bentobox/bentobox/managers/island/IslandCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java b/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java index f5edc3c8f..e6f91066d 100644 --- a/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java +++ b/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java @@ -38,7 +38,7 @@ public class IslandCache { * Map of all islands with island uniqueId as key */ @NonNull - private final Map<@NonNull String, @NonNull Island> islandsById; + private final Map<@NonNull String, Island> islandsById; /** * Every player who is associated with an island is in this map. Key is player * UUID, value is a set of islands From 2d9bbb9cc11562448a5292705e45cba2ed6c0892 Mon Sep 17 00:00:00 2001 From: tastybento Date: Tue, 9 Jul 2024 07:31:25 -0700 Subject: [PATCH 2/8] Support for new trial spawners protection --- .../listeners/flags/protection/BreakBlocksListener.java | 6 ++++++ .../flags/worldsettings/SpawnerSpawnEggsListener.java | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java index b40c99b05..2c13dc5b4 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java @@ -21,6 +21,8 @@ import org.bukkit.event.hanging.HangingBreakByEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.vehicle.VehicleDamageEvent; +import com.google.common.base.Enums; + import world.bentobox.bentobox.api.flags.FlagListener; import world.bentobox.bentobox.lists.Flags; @@ -101,6 +103,10 @@ public class BreakBlocksListener extends FlagListener { { return; } + if (Enums.getIfPresent(Material.class, "TRIAL_SPAWNER").isPresent() && m.equals(Material.TRIAL_SPAWNER)) { + this.checkIsland(e, p, l, Flags.BREAK_SPAWNERS); + return; + } switch (m) { case CAKE -> this.checkIsland(e, p, l, Flags.BREAK_BLOCKS); diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/SpawnerSpawnEggsListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/SpawnerSpawnEggsListener.java index 09c5d2e5c..34a7baac6 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/SpawnerSpawnEggsListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/SpawnerSpawnEggsListener.java @@ -1,6 +1,5 @@ package world.bentobox.bentobox.listeners.flags.worldsettings; -import org.bukkit.Material; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerInteractEvent; @@ -21,8 +20,8 @@ public class SpawnerSpawnEggsListener extends FlagListener { public void onSpawnerChange(final PlayerInteractEvent e) { User user = User.getInstance(e.getPlayer()); // Checking if the clicked block is a spawner and the item in hand is a mob egg - if (e.getClickedBlock() != null && e.getClickedBlock().getType().equals(Material.SPAWNER) - && e.getItem() != null && e.getItem().getType().toString().endsWith("_SPAWN_EGG") + if (e.getClickedBlock() != null && e.getClickedBlock().getType().name().endsWith("_SPAWNER") + && e.getItem() != null && e.getItem().getType().name().endsWith("_SPAWN_EGG") && getIWM().inWorld(e.getClickedBlock().getWorld()) && !(user.hasPermission(getIWM().getPermissionPrefix(e.getClickedBlock().getWorld()) + "mod.bypass." + Flags.SPAWNER_SPAWN_EGGS.getID() + ".everywhere") || user.hasPermission(getIWM().getPermissionPrefix(e.getClickedBlock().getWorld()) + "mod.bypassprotect")) From b2d5e0b84e7919eb79adfbb9d304f648a06530b8 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 14 Jul 2024 15:10:32 -0700 Subject: [PATCH 3/8] 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 @@ package world.bentobox.bentobox.listeners.flags.protection; 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 class PhysicalInteractionListener extends FlagListener @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.any; 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.Slime; 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 class PhysicalInteractionListenerTest extends AbstractCommonSetup { 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")); + } } From 3d00191b905954c8dd4c8456e4e120d9f7cce526 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 14 Jul 2024 15:23:25 -0700 Subject: [PATCH 4/8] Enhance to include gates, trapdoors, and doors --- .../PhysicalInteractionListener.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 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 76ea19691..3110c2a7e 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 @@ -1,5 +1,7 @@ package world.bentobox.bentobox.listeners.flags.protection; +import java.util.Map; + import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.block.Block; @@ -13,6 +15,7 @@ import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.entity.EntityInteractEvent; import org.bukkit.event.player.PlayerInteractEvent; +import world.bentobox.bentobox.api.flags.Flag; import world.bentobox.bentobox.api.flags.FlagListener; import world.bentobox.bentobox.lists.Flags; @@ -64,17 +67,12 @@ public class PhysicalInteractionListener extends FlagListener } } + private static final Map, Flag> TAG_TO_FLAG = Map.of(Tag.WOODEN_BUTTONS, Flags.BUTTON, + Tag.PRESSURE_PLATES, Flags.PRESSURE_PLATE, Tag.FENCE_GATES, Flags.GATE, Tag.DOORS, Flags.DOOR); + 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 (Tag.PRESSURE_PLATES.isTagged(block.getType())) { - // Pressure plates - this.checkIsland(e, player, block.getLocation(), Flags.PRESSURE_PLATE); - } - + TAG_TO_FLAG.entrySet().stream().filter(entry -> entry.getKey().isTagged(block.getType())).findFirst() + .ifPresent(entry -> this.checkIsland(e, player, block.getLocation(), entry.getValue())); } /** From 16592c595b2b83507bee615e06a25caeac9f788b Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 14 Jul 2024 16:02:00 -0700 Subject: [PATCH 5/8] Added CANDLES and BELL_RINGING flags and protections --- .../protection/BlockInteractionListener.java | 2 ++ .../flags/protection/CandleListener.java | 33 +++++++++++++++++++ .../PhysicalInteractionListener.java | 26 +++++++++++---- .../world/bentobox/bentobox/lists/Flags.java | 18 ++++++++++ src/main/resources/locales/en-US.yml | 8 +++++ 5 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 src/main/java/world/bentobox/bentobox/listeners/flags/protection/CandleListener.java diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java index aecaf82c0..496ae5238 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java @@ -100,9 +100,11 @@ public class BlockInteractionListener extends FlagListener switch (type) { case BEACON -> this.checkIsland(e, player, loc, Flags.BEACON); + case BELL -> this.checkIsland(e, player, loc, Flags.BELL_RINGING); case BREWING_STAND -> this.checkIsland(e, player, loc, Flags.BREWING); case BEEHIVE, BEE_NEST -> this.checkIsland(e, player, loc, Flags.HIVE); case BARREL -> this.checkIsland(e, player, loc, Flags.BARREL); + case CANDLE -> this.checkIsland(e, player, loc, Flags.CANDLES); case CHEST, CHEST_MINECART -> this.checkIsland(e, player, loc, Flags.CHEST); case TRAPPED_CHEST -> this.checkIsland(e, player, loc, Flags.TRAPPED_CHEST); case FLOWER_POT -> this.checkIsland(e, player, loc, Flags.FLOWER_POT); diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/CandleListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/CandleListener.java new file mode 100644 index 000000000..73fe13c3b --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/CandleListener.java @@ -0,0 +1,33 @@ +package world.bentobox.bentobox.listeners.flags.protection; + +import org.bukkit.Tag; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.player.PlayerInteractEvent; + +import world.bentobox.bentobox.api.flags.FlagListener; +import world.bentobox.bentobox.lists.Flags; + +/** + * Protects candles + * @author tastybento + * @since 2.4.2 + */ +public class CandleListener extends FlagListener { + + /** + * Prevent dying signs. + * @param e - event + */ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCandleInteract(final PlayerInteractEvent e) { + if (e.getClickedBlock() == null || e.getItem() == null) { + return; + } + + if (Tag.CANDLES.isTagged(e.getClickedBlock().getType()) + || Tag.CANDLE_CAKES.isTagged(e.getClickedBlock().getType())) { + this.checkIsland(e, e.getPlayer(), e.getClickedBlock().getLocation(), Flags.CANDLES); + } + } +} 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 3110c2a7e..11c3dbf57 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 @@ -67,16 +67,25 @@ public class PhysicalInteractionListener extends FlagListener } } - private static final Map, Flag> TAG_TO_FLAG = Map.of(Tag.WOODEN_BUTTONS, Flags.BUTTON, - Tag.PRESSURE_PLATES, Flags.PRESSURE_PLATE, Tag.FENCE_GATES, Flags.GATE, Tag.DOORS, Flags.DOOR); + private boolean checkBlocks(Event e, Player player, Block block) { + Map, Flag> TAG_TO_FLAG = Map.of(Tag.WOODEN_BUTTONS, Flags.BUTTON, Tag.PRESSURE_PLATES, + Flags.PRESSURE_PLATE, Tag.FENCE_GATES, Flags.GATE, Tag.DOORS, Flags.DOOR, Tag.CANDLE_CAKES, + Flags.CANDLES, Tag.CANDLES, Flags.CANDLES); + Map MAT_TO_FLAG = Map.of(Material.LEVER, Flags.LEVER, Material.TRIPWIRE, Flags.REDSTONE, + Material.TARGET, Flags.REDSTONE); + boolean result = TAG_TO_FLAG.entrySet().stream().filter(entry -> entry.getKey().isTagged(block.getType())) + .findFirst().map(entry -> this.checkIsland(e, player, block.getLocation(), entry.getValue())) + .orElse(true); - private void checkBlocks(Event e, Player player, Block block) { - TAG_TO_FLAG.entrySet().stream().filter(entry -> entry.getKey().isTagged(block.getType())).findFirst() - .ifPresent(entry -> this.checkIsland(e, player, block.getLocation(), entry.getValue())); + if (result && MAT_TO_FLAG.containsKey(block.getType())) { + result = this.checkIsland(e, player, block.getLocation(), MAT_TO_FLAG.get(block.getType())); + } + + return result; } /** - * Protects buttons and plates from being activated by projectiles that explode + * Protects buttons and plates, etc. from being activated by projectiles that explode * @param e - event */ @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) @@ -84,6 +93,11 @@ public class PhysicalInteractionListener extends FlagListener if (e.getEntity() instanceof Projectile p && p.getShooter() instanceof Player player) { for (Block b : e.blockList()) { this.checkBlocks(e, player, b); + /* + * TODO: + * Add protection for candles + * + */ } } } diff --git a/src/main/java/world/bentobox/bentobox/lists/Flags.java b/src/main/java/world/bentobox/bentobox/lists/Flags.java index d0f5c75b5..33f345d65 100644 --- a/src/main/java/world/bentobox/bentobox/lists/Flags.java +++ b/src/main/java/world/bentobox/bentobox/lists/Flags.java @@ -19,6 +19,7 @@ import world.bentobox.bentobox.listeners.flags.protection.BlockInteractionListen import world.bentobox.bentobox.listeners.flags.protection.BreakBlocksListener; import world.bentobox.bentobox.listeners.flags.protection.BreedingListener; import world.bentobox.bentobox.listeners.flags.protection.BucketListener; +import world.bentobox.bentobox.listeners.flags.protection.CandleListener; import world.bentobox.bentobox.listeners.flags.protection.DyeListener; import world.bentobox.bentobox.listeners.flags.protection.EggListener; import world.bentobox.bentobox.listeners.flags.protection.ElytraListener; @@ -687,6 +688,23 @@ public final class Flags { */ public static final Flag SIGN_EDITING = new Flag.Builder("SIGN_EDITING", Material.DARK_OAK_SIGN).mode(Flag.Mode.BASIC).type(Type.PROTECTION).build(); + /** + * Bell ringing protection + * Listeners are {@link BlockInteractionListener} and {@link PhysicalInteractionListener} + * @since 2.4.2 + */ + public static final Flag BELL_RINGING = new Flag.Builder("BELL_RINGING", Material.BELL).mode(Flag.Mode.EXPERT) + .type(Type.PROTECTION).build(); + + /** + * Candle protection + * Listener is {@link CandleListener} + * @since 2.4.2 + */ + public static final Flag CANDLES = new Flag.Builder("CANDLES", Material.CANDLE).mode(Flag.Mode.EXPERT) + .listener(new CandleListener()) + .type(Type.PROTECTION).build(); + /** * Provides a list of all the Flag instances contained in this class using reflection. * Deprecated Flags are ignored. diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 7989f41ed..47c5f27bc 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -912,6 +912,10 @@ protection: description: Toggle interaction name: Beacons hint: Beacon use disabled + BELL_RINGING: + description: Toggle interaction + name: Allow bell ringing + hint: Bell ringing disabled BED: description: Toggle interaction name: Beds @@ -960,6 +964,10 @@ protection: description: Toggle button use name: Buttons hint: Button use disabled + CANDLES: + description: Toggle candle interaction + name: Candles + hint: Candle interaction disabled CAKE: description: Toggle cake interaction name: Cakes From 1c5a52de4c71b7af5f2c3c0ddab10922bb419d55 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 14 Jul 2024 16:23:14 -0700 Subject: [PATCH 6/8] Added test class for candles --- .../flags/protection/CandleListener.java | 2 +- .../flags/protection/CandleListenerTest.java | 110 ++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/test/java/world/bentobox/bentobox/listeners/flags/protection/CandleListenerTest.java diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/CandleListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/CandleListener.java index 73fe13c3b..bd8f92c0b 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/CandleListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/CandleListener.java @@ -21,7 +21,7 @@ public class CandleListener extends FlagListener { */ @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onCandleInteract(final PlayerInteractEvent e) { - if (e.getClickedBlock() == null || e.getItem() == null) { + if (e.getClickedBlock() == null) { return; } diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/CandleListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/CandleListenerTest.java new file mode 100644 index 000000000..6d709b421 --- /dev/null +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/CandleListenerTest.java @@ -0,0 +1,110 @@ +package world.bentobox.bentobox.listeners.flags.protection; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Tag; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.event.Event.Result; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.listeners.flags.AbstractCommonSetup; +import world.bentobox.bentobox.lists.Flags; +import world.bentobox.bentobox.util.Util; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ BentoBox.class, Flags.class, Util.class, Bukkit.class }) +public class CandleListenerTest extends AbstractCommonSetup { + + private CandleListener l; + @Mock + private Block block; + + /** + */ + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + + // Island manager + // Default is that everything is allowed + when(island.isAllowed(any(), any())).thenReturn(true); + + when(block.getLocation()).thenReturn(location); + + // Tags + when(Tag.CANDLES.isTagged(any(Material.class))).thenReturn(true); + when(Tag.CANDLE_CAKES.isTagged(any(Material.class))).thenReturn(true); + + // Listener + l = new CandleListener(); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.protection.CandleListener#onCandleInteract(org.bukkit.event.player.PlayerInteractEvent)}. + */ + @Test + public void testOnCandleInteract() { + // Block + when(block.getType()).thenReturn(Material.CANDLE); + PlayerInteractEvent e = new PlayerInteractEvent(mockPlayer, Action.LEFT_CLICK_BLOCK, null, block, BlockFace.UP); + l.onCandleInteract(e); + assertEquals(Result.ALLOW, e.useInteractedBlock()); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.protection.CandleListener#onCandleInteract(org.bukkit.event.player.PlayerInteractEvent)}. + */ + @Test + public void testOnCandleCakeInteract() { + // Block + when(block.getType()).thenReturn(Material.CANDLE_CAKE); + PlayerInteractEvent e = new PlayerInteractEvent(mockPlayer, Action.LEFT_CLICK_BLOCK, null, block, BlockFace.UP); + l.onCandleInteract(e); + assertEquals(Result.ALLOW, e.useInteractedBlock()); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.protection.CandleListener#onCandleInteract(org.bukkit.event.player.PlayerInteractEvent)}. + */ + @Test + public void testOnCandleInteractFail() { + when(island.isAllowed(any(), any())).thenReturn(false); + // Block + when(block.getType()).thenReturn(Material.CANDLE); + PlayerInteractEvent e = new PlayerInteractEvent(mockPlayer, Action.LEFT_CLICK_BLOCK, null, block, BlockFace.UP); + l.onCandleInteract(e); + assertEquals(Result.DENY, e.useInteractedBlock()); + verify(notifier).notify(any(), eq("protection.protected")); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.protection.CandleListener#onCandleInteract(org.bukkit.event.player.PlayerInteractEvent)}. + */ + @Test + public void testOnCandleCakeInteractFail() { + when(island.isAllowed(any(), any())).thenReturn(false); + // Block + when(block.getType()).thenReturn(Material.CANDLE_CAKE); + PlayerInteractEvent e = new PlayerInteractEvent(mockPlayer, Action.LEFT_CLICK_BLOCK, null, block, BlockFace.UP); + l.onCandleInteract(e); + assertEquals(Result.DENY, e.useInteractedBlock()); + verify(notifier).notify(any(), eq("protection.protected")); + } + +} From b4ecb1dadd8028d0636974c9f605cd9af9892347 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 14 Jul 2024 20:21:33 -0700 Subject: [PATCH 7/8] Fix tests --- .../flags/protection/PhysicalInteractionListener.java | 1 - .../flags/protection/PhysicalInteractionListenerTest.java | 6 ++---- .../world/bentobox/bentobox/managers/FlagsManagerTest.java | 2 +- 3 files changed, 3 insertions(+), 6 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 11c3dbf57..b302fad75 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 @@ -76,7 +76,6 @@ public class PhysicalInteractionListener extends FlagListener boolean result = TAG_TO_FLAG.entrySet().stream().filter(entry -> entry.getKey().isTagged(block.getType())) .findFirst().map(entry -> this.checkIsland(e, player, block.getLocation(), entry.getValue())) .orElse(true); - if (result && MAT_TO_FLAG.containsKey(block.getType())) { result = this.checkIsland(e, player, block.getLocation(), MAT_TO_FLAG.get(block.getType())); } 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 60a3866cf..883d07019 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 @@ -282,13 +282,11 @@ public class PhysicalInteractionListenerTest extends AbstractCommonSetup { // 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")); + verify(notifier, times(2)).notify(any(), eq("protection.protected")); } } diff --git a/src/test/java/world/bentobox/bentobox/managers/FlagsManagerTest.java b/src/test/java/world/bentobox/bentobox/managers/FlagsManagerTest.java index 2cc674d87..c9f53635d 100644 --- a/src/test/java/world/bentobox/bentobox/managers/FlagsManagerTest.java +++ b/src/test/java/world/bentobox/bentobox/managers/FlagsManagerTest.java @@ -46,7 +46,7 @@ public class FlagsManagerTest { /** * Update this value if the number of registered listeners changes */ - private static final int NUMBER_OF_LISTENERS = 54; + private static final int NUMBER_OF_LISTENERS = 55; @Mock private BentoBox plugin; @Mock From 570fe7448e9a7ee2eeade71cf0ce991261a076a4 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 14 Jul 2024 21:44:43 -0700 Subject: [PATCH 8/8] WIP Try to add protection to decorative pots. --- .../flags/protection/BreakBlocksListener.java | 2 +- .../{TNTListener.java => ExplosionListener.java} | 2 +- .../protection/PhysicalInteractionListener.java | 12 +++++------- .../java/world/bentobox/bentobox/lists/Flags.java | 14 +++++++------- .../flags/protection/TNTListenerTest.java | 4 ++-- 5 files changed, 16 insertions(+), 18 deletions(-) rename src/main/java/world/bentobox/bentobox/listeners/flags/protection/{TNTListener.java => ExplosionListener.java} (99%) diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java index 2c13dc5b4..bf8ec1cab 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java @@ -188,7 +188,7 @@ public class BreakBlocksListener extends FlagListener { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onProjectileHitBreakBlock(ProjectileHitEvent e) { // We want to make sure this is an actual projectile (arrow or trident) - if (!(e.getEntity() instanceof AbstractArrow)) { + if (!(e.getEntity() instanceof Projectile)) { return; } diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/TNTListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/ExplosionListener.java similarity index 99% rename from src/main/java/world/bentobox/bentobox/listeners/flags/protection/TNTListener.java rename to src/main/java/world/bentobox/bentobox/listeners/flags/protection/ExplosionListener.java index f0878c8ce..d000eea7f 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/TNTListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/ExplosionListener.java @@ -27,7 +27,7 @@ import world.bentobox.bentobox.lists.Flags; * Protects islands from visitors blowing things up * @author tastybento */ -public class TNTListener extends FlagListener { +public class ExplosionListener extends FlagListener { /** * Contains {@link EntityType}s that generates an explosion. * @since 1.5.0 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 b302fad75..7b0a48104 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 @@ -72,12 +72,13 @@ public class PhysicalInteractionListener extends FlagListener Flags.PRESSURE_PLATE, Tag.FENCE_GATES, Flags.GATE, Tag.DOORS, Flags.DOOR, Tag.CANDLE_CAKES, Flags.CANDLES, Tag.CANDLES, Flags.CANDLES); Map MAT_TO_FLAG = Map.of(Material.LEVER, Flags.LEVER, Material.TRIPWIRE, Flags.REDSTONE, - Material.TARGET, Flags.REDSTONE); + Material.TARGET, Flags.REDSTONE, Material.DECORATED_POT, Flags.BREAK_BLOCKS); boolean result = TAG_TO_FLAG.entrySet().stream().filter(entry -> entry.getKey().isTagged(block.getType())) .findFirst().map(entry -> this.checkIsland(e, player, block.getLocation(), entry.getValue())) .orElse(true); if (result && MAT_TO_FLAG.containsKey(block.getType())) { result = this.checkIsland(e, player, block.getLocation(), MAT_TO_FLAG.get(block.getType())); + } return result; @@ -91,12 +92,9 @@ public class PhysicalInteractionListener extends FlagListener 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); - /* - * TODO: - * Add protection for candles - * - */ + if (!this.checkBlocks(e, player, b)) { + e.blockList().clear(); + } } } } diff --git a/src/main/java/world/bentobox/bentobox/lists/Flags.java b/src/main/java/world/bentobox/bentobox/lists/Flags.java index 33f345d65..15eb623d7 100644 --- a/src/main/java/world/bentobox/bentobox/lists/Flags.java +++ b/src/main/java/world/bentobox/bentobox/lists/Flags.java @@ -39,7 +39,7 @@ import world.bentobox.bentobox.listeners.flags.protection.PortalListener; import world.bentobox.bentobox.listeners.flags.protection.SculkSensorListener; import world.bentobox.bentobox.listeners.flags.protection.SculkShriekerListener; import world.bentobox.bentobox.listeners.flags.protection.ShearingListener; -import world.bentobox.bentobox.listeners.flags.protection.TNTListener; +import world.bentobox.bentobox.listeners.flags.protection.ExplosionListener; import world.bentobox.bentobox.listeners.flags.protection.TeleportationListener; import world.bentobox.bentobox.listeners.flags.protection.ThrowingListener; import world.bentobox.bentobox.listeners.flags.settings.DecayListener; @@ -267,9 +267,9 @@ public final class Flags { * Prevents players from priming TNT. * @since 1.5.0 * - * @see TNTListener + * @see ExplosionListener */ - public static final Flag TNT_PRIMING = new Flag.Builder("TNT_PRIMING", Material.TNT).listener(new TNTListener()).build(); + public static final Flag TNT_PRIMING = new Flag.Builder("TNT_PRIMING", Material.TNT).listener(new ExplosionListener()).build(); /** * Prevents players from extinguishing fires. @@ -462,7 +462,7 @@ public final class Flags { /** * If {@code false}, prevents TNT from breaking blocks and damaging nearby entities. * @since 1.5.0 - * @see TNTListener + * @see ExplosionListener */ public static final Flag TNT_DAMAGE = new Flag.Builder("TNT_DAMAGE", Material.TNT).type(Type.SETTING) .mode(Flag.Mode.ADVANCED).build(); @@ -470,7 +470,7 @@ public final class Flags { /** * If {@code false}, prevents Block Explode from breaking blocks and damaging nearby entities. * @since 1.19.1 - * @see TNTListener + * @see ExplosionListener */ public static final Flag BLOCK_EXPLODE_DAMAGE = new Flag.Builder("BLOCK_EXPLODE_DAMAGE", Material.TNT_MINECART).type(Type.SETTING) .mode(Flag.Mode.ADVANCED).build(); @@ -478,7 +478,7 @@ public final class Flags { /** * If {@code false}, prevents TNT from breaking blocks and damaging nearby entities outside of island boundaries. * @since 1.15.3 - * @see TNTListener + * @see ExplosionListener */ public static final Flag WORLD_TNT_DAMAGE = new Flag.Builder("WORLD_TNT_DAMAGE", Material.TNT) .type(Type.WORLD_SETTING) @@ -487,7 +487,7 @@ public final class Flags { /** * If {@code false}, prevents Block Explode from breaking blocks and damaging nearby entities outside of island boundaries. * @since 1.19.1 - * @see TNTListener + * @see ExplosionListener */ public static final Flag WORLD_BLOCK_EXPLODE_DAMAGE = new Flag.Builder("WORLD_BLOCK_EXPLODE_DAMAGE", Material.TNT_MINECART) .type(Type.WORLD_SETTING) diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/TNTListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/TNTListenerTest.java index 1aff866eb..846ddc34c 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/TNTListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/TNTListenerTest.java @@ -58,7 +58,7 @@ public class TNTListenerTest extends AbstractCommonSetup { private Entity entity; // Class under test - private TNTListener listener; + private ExplosionListener listener; @Override @Before @@ -85,7 +85,7 @@ public class TNTListenerTest extends AbstractCommonSetup { // Util when(Util.findFirstMatchingEnum(any(), anyString())).thenCallRealMethod(); - listener = new TNTListener(); + listener = new ExplosionListener(); listener.setPlugin(plugin); }