diff --git a/src/main/java/world/bentobox/bentobox/listeners/PortalTeleportationListener.java b/src/main/java/world/bentobox/bentobox/listeners/PortalTeleportationListener.java index e8db9fd3f..21b0d64ff 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/PortalTeleportationListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/PortalTeleportationListener.java @@ -125,6 +125,10 @@ public class PortalTeleportationListener implements Listener { // We are done here return true; } + // Set player's velocity and fall distance to 0 + plugin.logDebug("Setting player's velocity to 0 before teleport"); + e.getPlayer().setVelocity(new Vector(0,0,0)); + e.getPlayer().setFallDistance(0); // Else other worlds teleport to the end // Set player's velocity to zero one tick after cancellation @@ -133,6 +137,7 @@ public class PortalTeleportationListener implements Listener { .entity(e.getPlayer()) .location(to) .thenRun(() -> { + plugin.logDebug("Setting player's velocity to 0 after teleport"); e.getPlayer().setVelocity(new Vector(0,0,0)); e.getPlayer().setFallDistance(0); }) 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 fcafe0c87..4c2e7533d 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 @@ -46,6 +46,14 @@ public class BreakBlocksListener extends FlagListener { if (e.getRemover() instanceof Player) { checkIsland(e, (Player)e.getRemover(), e.getEntity().getLocation(), Flags.BREAK_BLOCKS); } + // Check for projectiles + if (e.getRemover() instanceof Projectile) { + // Find out who fired it + Projectile p = (Projectile)e.getRemover(); + if (p.getShooter() instanceof Player) { + checkIsland(e, (Player)p.getShooter(), e.getEntity().getLocation(), Flags.BREAK_BLOCKS); + } + } } /** @@ -133,7 +141,7 @@ public class BreakBlocksListener extends FlagListener { } else if (e.getEntity() instanceof ArmorStand) { return !checkIsland(e, player, location, Flags.ARMOR_STAND); } - return false; + return false; } /** diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java index f4ce22854..703e11bcd 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java @@ -8,6 +8,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.EntityBlockFormEvent; +import org.bukkit.event.hanging.HangingPlaceEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; @@ -36,6 +37,15 @@ public class PlaceBlocksListener extends FlagListener { checkIsland(e, e.getPlayer(), e.getBlock().getLocation(), Flags.PLACE_BLOCKS); } + /** + * Check for paintings and other hanging placements + * @param e - event + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onHangingPlace(final HangingPlaceEvent e) { + checkIsland(e, e.getPlayer(), e.getBlock().getLocation(), Flags.PLACE_BLOCKS); + } + /** * Handles placing items into ItemFrames * @param e - event diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListenerTest.java index 42482f103..86341a26d 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListenerTest.java @@ -9,6 +9,7 @@ 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 static org.mockito.Mockito.never; import java.util.Arrays; import java.util.HashMap; @@ -26,6 +27,7 @@ import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Arrow; import org.bukkit.entity.Creeper; import org.bukkit.entity.EnderCrystal; import org.bukkit.entity.Entity; @@ -271,6 +273,53 @@ public class BreakBlocksListenerTest { assertFalse(e.isCancelled()); } + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.protection.BreakBlocksListener#onBreakHanging(org.bukkit.event.hanging.HangingBreakByEntityEvent)}. + */ + @Test + public void testOnBreakHangingNotPlayerProjectile() { + Hanging hanging = mock(Hanging.class); + when(hanging.getLocation()).thenReturn(location); + RemoveCause cause = RemoveCause.PHYSICS; + Arrow arrow = mock(Arrow.class); + when(arrow.getShooter()).thenReturn(mock(Skeleton.class)); + HangingBreakByEntityEvent e = new HangingBreakByEntityEvent(hanging, arrow, cause); + bbl.onBreakHanging(e); + assertFalse(e.isCancelled()); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.protection.BreakBlocksListener#onBreakHanging(org.bukkit.event.hanging.HangingBreakByEntityEvent)}. + */ + @Test + public void testOnBreakHangingPlayerProjectileNotAllowed() { + when(island.isAllowed(any(), any())).thenReturn(false); + Hanging hanging = mock(Hanging.class); + when(hanging.getLocation()).thenReturn(location); + RemoveCause cause = RemoveCause.PHYSICS; + Arrow arrow = mock(Arrow.class); + when(arrow.getShooter()).thenReturn(player); + HangingBreakByEntityEvent e = new HangingBreakByEntityEvent(hanging, arrow, cause); + bbl.onBreakHanging(e); + assertTrue(e.isCancelled()); + verify(notifier).notify(any(), eq("protection.protected")); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.protection.BreakBlocksListener#onBreakHanging(org.bukkit.event.hanging.HangingBreakByEntityEvent)}. + */ + @Test + public void testOnBreakHangingPlayerProjectileAllowed() { + Hanging hanging = mock(Hanging.class); + when(hanging.getLocation()).thenReturn(location); + RemoveCause cause = RemoveCause.PHYSICS; + Arrow arrow = mock(Arrow.class); + when(arrow.getShooter()).thenReturn(player); + HangingBreakByEntityEvent e = new HangingBreakByEntityEvent(hanging, arrow, cause); + bbl.onBreakHanging(e); + assertFalse(e.isCancelled()); + verify(notifier, never()).notify(any(), eq("protection.protected")); + } /** * Test method for {@link world.bentobox.bentobox.listeners.flags.protection.BreakBlocksListener#onPlayerInteract(org.bukkit.event.player.PlayerInteractEvent)}. */ diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListenerTest.java index d1b39503b..33d772a50 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListenerTest.java @@ -4,8 +4,11 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; 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.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.Arrays; @@ -27,11 +30,13 @@ import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.entity.Creeper; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Hanging; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; import org.bukkit.event.Event.Result; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.hanging.HangingPlaceEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; @@ -128,8 +133,8 @@ public class PlaceBlocksListenerTest { // Fake players Settings settings = mock(Settings.class); - Mockito.when(plugin.getSettings()).thenReturn(settings); - Mockito.when(settings.getFakePlayers()).thenReturn(new HashSet<>()); + when(plugin.getSettings()).thenReturn(settings); + when(settings.getFakePlayers()).thenReturn(new HashSet<>()); User.setPlugin(plugin); @@ -146,7 +151,7 @@ public class PlaceBlocksListenerTest { // World Settings WorldSettings ws = mock(WorldSettings.class); - when(iwm.getWorldSettings(Mockito.any())).thenReturn(ws); + when(iwm.getWorldSettings(any())).thenReturn(ws); Map worldFlags = new HashMap<>(); when(ws.getWorldFlags()).thenReturn(worldFlags); @@ -155,19 +160,19 @@ public class PlaceBlocksListenerTest { when(plugin.getIslands()).thenReturn(im); island = mock(Island.class); Optional optional = Optional.of(island); - when(im.getProtectedIslandAt(Mockito.any())).thenReturn(optional); + when(im.getProtectedIslandAt(any())).thenReturn(optional); // Default is that everything is allowed - when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(true); + when(island.isAllowed(any(), any())).thenReturn(true); // Notifier notifier = mock(Notifier.class); when(plugin.getNotifier()).thenReturn(notifier); PowerMockito.mockStatic(Util.class); - when(Util.getWorld(Mockito.any())).thenReturn(mock(World.class)); + when(Util.getWorld(any())).thenReturn(mock(World.class)); // Addon - when(iwm.getAddon(Mockito.any())).thenReturn(Optional.empty()); + when(iwm.getAddon(any())).thenReturn(Optional.empty()); // Player player = mock(Player.class); @@ -224,7 +229,36 @@ public class PlaceBlocksListenerTest { pbl.onBlockPlace(e); assertFalse(e.isCancelled()); } - + + /** + * Test method for {@link PlaceBlocksListener#onHangingPlace(org.bukkit.event.hanging.HangingPlaceEvent)}. + */ + @Test + public void testOnHangingPlaceAllowed() { + Hanging hanging = mock(Hanging.class); + Block block = mock(Block.class); + when(block.getLocation()).thenReturn(location); + HangingPlaceEvent e = new HangingPlaceEvent(hanging, player, block, BlockFace.EAST); + pbl.onHangingPlace(e); + assertFalse(e.isCancelled()); + verify(notifier, never()).notify(any(), eq("protection.protected")); + } + + /** + * Test method for {@link PlaceBlocksListener#onHangingPlace(org.bukkit.event.hanging.HangingPlaceEvent)}. + */ + @Test + public void testOnHangingPlaceNotAllowed() { + when(island.isAllowed(any(), any())).thenReturn(false); + Hanging hanging = mock(Hanging.class); + Block block = mock(Block.class); + when(block.getLocation()).thenReturn(location); + HangingPlaceEvent e = new HangingPlaceEvent(hanging, player, block, BlockFace.EAST); + pbl.onHangingPlace(e); + assertTrue(e.isCancelled()); + verify(notifier).notify(any(), eq("protection.protected")); + } + /** * Test method for {@link PlaceBlocksListener#onBlockPlace(org.bukkit.event.block.BlockPlaceEvent)}. */ @@ -246,7 +280,7 @@ public class PlaceBlocksListenerTest { */ @Test public void testOnBlockPlaceNotAllowed() { - when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(false); + when(island.isAllowed(any(), any())).thenReturn(false); Block placedBlock = mock(Block.class); when(placedBlock.getType()).thenReturn(Material.STONE); when(placedBlock.getLocation()).thenReturn(location); @@ -258,7 +292,7 @@ public class PlaceBlocksListenerTest { BlockPlaceEvent e = new BlockPlaceEvent(placedBlock, replacedBlockState, placedAgainst, itemInHand, player, true, hand); pbl.onBlockPlace(e); assertTrue(e.isCancelled()); - Mockito.verify(notifier).notify(Mockito.any(), Mockito.eq("protection.protected")); + verify(notifier).notify(any(), eq("protection.protected")); } /** @@ -267,7 +301,7 @@ public class PlaceBlocksListenerTest { */ @Test public void testOnBlockPlaceBook() { - when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(false); + when(island.isAllowed(any(), any())).thenReturn(false); Block placedBlock = mock(Block.class); when(placedBlock.getType()).thenReturn(Material.LECTERN); when(placedBlock.getLocation()).thenReturn(location); @@ -279,13 +313,13 @@ public class PlaceBlocksListenerTest { BlockPlaceEvent e = new BlockPlaceEvent(placedBlock, replacedBlockState, placedAgainst, itemInHand, player, true, hand); pbl.onBlockPlace(e); assertFalse(e.isCancelled()); - Mockito.verify(notifier, never()).notify(Mockito.any(), Mockito.eq("protection.protected")); + verify(notifier, never()).notify(any(), eq("protection.protected")); // With a WRITABLE BOOK now when(itemInHand.getType()).thenReturn(Material.WRITABLE_BOOK); pbl.onBlockPlace(e); assertFalse(e.isCancelled()); - Mockito.verify(notifier, never()).notify(Mockito.any(), Mockito.eq("protection.protected")); + verify(notifier, never()).notify(any(), eq("protection.protected")); } /** @@ -319,14 +353,14 @@ public class PlaceBlocksListenerTest { */ @Test public void testOnPlayerHitItemFrameNotAllowed() { - when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(false); + when(island.isAllowed(any(), any())).thenReturn(false); ItemFrame itemFrame = mock(ItemFrame.class); when(itemFrame.getType()).thenReturn(EntityType.ITEM_FRAME); when(itemFrame.getLocation()).thenReturn(location); PlayerInteractEntityEvent e = new PlayerInteractEntityEvent(player, itemFrame, EquipmentSlot.HAND); pbl.onPlayerHitItemFrame(e); assertTrue(e.isCancelled()); - Mockito.verify(notifier).notify(Mockito.any(), Mockito.eq("protection.protected")); + verify(notifier).notify(any(), eq("protection.protected")); } /** @@ -351,7 +385,7 @@ public class PlaceBlocksListenerTest { */ @Test public void testOnPlayerInteractNotAllowed() { - when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(false); + when(island.isAllowed(any(), any())).thenReturn(false); ItemStack item = mock(ItemStack.class); when(item.getType()).thenReturn(Material.ARMOR_STAND, Material.FIREWORK_ROCKET, Material.ITEM_FRAME, Material.END_CRYSTAL, Material.CHEST, Material.TRAPPED_CHEST, Material.DARK_OAK_BOAT); Block clickedBlock = mock(Block.class); @@ -362,6 +396,6 @@ public class PlaceBlocksListenerTest { pbl.onPlayerInteract(e); assertTrue("Failed on " + item.getType().toString(), e.useInteractedBlock().equals(Result.DENY)); } - Mockito.verify(notifier, Mockito.times(7)).notify(Mockito.any(), Mockito.eq("protection.protected")); + verify(notifier, times(7)).notify(any(), eq("protection.protected")); } }