Protect paintings from projectiles and being placed.

Fixes https://github.com/BentoBoxWorld/BentoBox/issues/1273
This commit is contained in:
tastybento 2020-04-09 16:02:51 -07:00
parent b6b9b11f53
commit d327ea4a89
5 changed files with 124 additions and 18 deletions

View File

@ -125,6 +125,10 @@ public class PortalTeleportationListener implements Listener {
// We are done here // We are done here
return true; 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 // Else other worlds teleport to the end
// Set player's velocity to zero one tick after cancellation // Set player's velocity to zero one tick after cancellation
@ -133,6 +137,7 @@ public class PortalTeleportationListener implements Listener {
.entity(e.getPlayer()) .entity(e.getPlayer())
.location(to) .location(to)
.thenRun(() -> { .thenRun(() -> {
plugin.logDebug("Setting player's velocity to 0 after teleport");
e.getPlayer().setVelocity(new Vector(0,0,0)); e.getPlayer().setVelocity(new Vector(0,0,0));
e.getPlayer().setFallDistance(0); e.getPlayer().setFallDistance(0);
}) })

View File

@ -46,6 +46,14 @@ public class BreakBlocksListener extends FlagListener {
if (e.getRemover() instanceof Player) { if (e.getRemover() instanceof Player) {
checkIsland(e, (Player)e.getRemover(), e.getEntity().getLocation(), Flags.BREAK_BLOCKS); 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) { } else if (e.getEntity() instanceof ArmorStand) {
return !checkIsland(e, player, location, Flags.ARMOR_STAND); return !checkIsland(e, player, location, Flags.ARMOR_STAND);
} }
return false; return false;
} }
/** /**

View File

@ -8,6 +8,7 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.EntityBlockFormEvent; import org.bukkit.event.block.EntityBlockFormEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent; 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); 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 * Handles placing items into ItemFrames
* @param e - event * @param e - event

View File

@ -9,6 +9,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.mockito.Mockito.never;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -26,6 +27,7 @@ import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.entity.ArmorStand; import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Creeper; import org.bukkit.entity.Creeper;
import org.bukkit.entity.EnderCrystal; import org.bukkit.entity.EnderCrystal;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -271,6 +273,53 @@ public class BreakBlocksListenerTest {
assertFalse(e.isCancelled()); 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)}. * Test method for {@link world.bentobox.bentobox.listeners.flags.protection.BreakBlocksListener#onPlayerInteract(org.bukkit.event.player.PlayerInteractEvent)}.
*/ */

View File

@ -4,8 +4,11 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; 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 static org.mockito.Mockito.when;
import java.util.Arrays; import java.util.Arrays;
@ -27,11 +30,13 @@ import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.entity.Creeper; import org.bukkit.entity.Creeper;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Hanging;
import org.bukkit.entity.ItemFrame; import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result; import org.bukkit.event.Event.Result;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
@ -128,8 +133,8 @@ public class PlaceBlocksListenerTest {
// Fake players // Fake players
Settings settings = mock(Settings.class); Settings settings = mock(Settings.class);
Mockito.when(plugin.getSettings()).thenReturn(settings); when(plugin.getSettings()).thenReturn(settings);
Mockito.when(settings.getFakePlayers()).thenReturn(new HashSet<>()); when(settings.getFakePlayers()).thenReturn(new HashSet<>());
User.setPlugin(plugin); User.setPlugin(plugin);
@ -146,7 +151,7 @@ public class PlaceBlocksListenerTest {
// World Settings // World Settings
WorldSettings ws = mock(WorldSettings.class); WorldSettings ws = mock(WorldSettings.class);
when(iwm.getWorldSettings(Mockito.any())).thenReturn(ws); when(iwm.getWorldSettings(any())).thenReturn(ws);
Map<String, Boolean> worldFlags = new HashMap<>(); Map<String, Boolean> worldFlags = new HashMap<>();
when(ws.getWorldFlags()).thenReturn(worldFlags); when(ws.getWorldFlags()).thenReturn(worldFlags);
@ -155,19 +160,19 @@ public class PlaceBlocksListenerTest {
when(plugin.getIslands()).thenReturn(im); when(plugin.getIslands()).thenReturn(im);
island = mock(Island.class); island = mock(Island.class);
Optional<Island> optional = Optional.of(island); Optional<Island> optional = Optional.of(island);
when(im.getProtectedIslandAt(Mockito.any())).thenReturn(optional); when(im.getProtectedIslandAt(any())).thenReturn(optional);
// Default is that everything is allowed // Default is that everything is allowed
when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(true); when(island.isAllowed(any(), any())).thenReturn(true);
// Notifier // Notifier
notifier = mock(Notifier.class); notifier = mock(Notifier.class);
when(plugin.getNotifier()).thenReturn(notifier); when(plugin.getNotifier()).thenReturn(notifier);
PowerMockito.mockStatic(Util.class); PowerMockito.mockStatic(Util.class);
when(Util.getWorld(Mockito.any())).thenReturn(mock(World.class)); when(Util.getWorld(any())).thenReturn(mock(World.class));
// Addon // Addon
when(iwm.getAddon(Mockito.any())).thenReturn(Optional.empty()); when(iwm.getAddon(any())).thenReturn(Optional.empty());
// Player // Player
player = mock(Player.class); player = mock(Player.class);
@ -224,7 +229,36 @@ public class PlaceBlocksListenerTest {
pbl.onBlockPlace(e); pbl.onBlockPlace(e);
assertFalse(e.isCancelled()); 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)}. * Test method for {@link PlaceBlocksListener#onBlockPlace(org.bukkit.event.block.BlockPlaceEvent)}.
*/ */
@ -246,7 +280,7 @@ public class PlaceBlocksListenerTest {
*/ */
@Test @Test
public void testOnBlockPlaceNotAllowed() { public void testOnBlockPlaceNotAllowed() {
when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(false); when(island.isAllowed(any(), any())).thenReturn(false);
Block placedBlock = mock(Block.class); Block placedBlock = mock(Block.class);
when(placedBlock.getType()).thenReturn(Material.STONE); when(placedBlock.getType()).thenReturn(Material.STONE);
when(placedBlock.getLocation()).thenReturn(location); when(placedBlock.getLocation()).thenReturn(location);
@ -258,7 +292,7 @@ public class PlaceBlocksListenerTest {
BlockPlaceEvent e = new BlockPlaceEvent(placedBlock, replacedBlockState, placedAgainst, itemInHand, player, true, hand); BlockPlaceEvent e = new BlockPlaceEvent(placedBlock, replacedBlockState, placedAgainst, itemInHand, player, true, hand);
pbl.onBlockPlace(e); pbl.onBlockPlace(e);
assertTrue(e.isCancelled()); 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 @Test
public void testOnBlockPlaceBook() { public void testOnBlockPlaceBook() {
when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(false); when(island.isAllowed(any(), any())).thenReturn(false);
Block placedBlock = mock(Block.class); Block placedBlock = mock(Block.class);
when(placedBlock.getType()).thenReturn(Material.LECTERN); when(placedBlock.getType()).thenReturn(Material.LECTERN);
when(placedBlock.getLocation()).thenReturn(location); when(placedBlock.getLocation()).thenReturn(location);
@ -279,13 +313,13 @@ public class PlaceBlocksListenerTest {
BlockPlaceEvent e = new BlockPlaceEvent(placedBlock, replacedBlockState, placedAgainst, itemInHand, player, true, hand); BlockPlaceEvent e = new BlockPlaceEvent(placedBlock, replacedBlockState, placedAgainst, itemInHand, player, true, hand);
pbl.onBlockPlace(e); pbl.onBlockPlace(e);
assertFalse(e.isCancelled()); 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 // With a WRITABLE BOOK now
when(itemInHand.getType()).thenReturn(Material.WRITABLE_BOOK); when(itemInHand.getType()).thenReturn(Material.WRITABLE_BOOK);
pbl.onBlockPlace(e); pbl.onBlockPlace(e);
assertFalse(e.isCancelled()); 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 @Test
public void testOnPlayerHitItemFrameNotAllowed() { public void testOnPlayerHitItemFrameNotAllowed() {
when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(false); when(island.isAllowed(any(), any())).thenReturn(false);
ItemFrame itemFrame = mock(ItemFrame.class); ItemFrame itemFrame = mock(ItemFrame.class);
when(itemFrame.getType()).thenReturn(EntityType.ITEM_FRAME); when(itemFrame.getType()).thenReturn(EntityType.ITEM_FRAME);
when(itemFrame.getLocation()).thenReturn(location); when(itemFrame.getLocation()).thenReturn(location);
PlayerInteractEntityEvent e = new PlayerInteractEntityEvent(player, itemFrame, EquipmentSlot.HAND); PlayerInteractEntityEvent e = new PlayerInteractEntityEvent(player, itemFrame, EquipmentSlot.HAND);
pbl.onPlayerHitItemFrame(e); pbl.onPlayerHitItemFrame(e);
assertTrue(e.isCancelled()); 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 @Test
public void testOnPlayerInteractNotAllowed() { public void testOnPlayerInteractNotAllowed() {
when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(false); when(island.isAllowed(any(), any())).thenReturn(false);
ItemStack item = mock(ItemStack.class); 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); 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); Block clickedBlock = mock(Block.class);
@ -362,6 +396,6 @@ public class PlaceBlocksListenerTest {
pbl.onPlayerInteract(e); pbl.onPlayerInteract(e);
assertTrue("Failed on " + item.getType().toString(), e.useInteractedBlock().equals(Result.DENY)); 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"));
} }
} }