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
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);
})

View File

@ -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;
}
/**

View File

@ -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

View File

@ -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)}.
*/

View File

@ -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<String, Boolean> 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<Island> 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"));
}
}