diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/PVPListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/PVPListener.java index c1dd7d8f8..c12b93ed7 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/PVPListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/PVPListener.java @@ -43,6 +43,10 @@ public class PVPListener extends AbstractFlagListener { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onEntityDamage(EntityDamageByEntityEvent e) { if (e.getEntity() instanceof Player && getPlugin().getIWM().inWorld(e.getEntity().getLocation())) { + // Allow self damage + if (e.getEntity().equals(e.getDamager())) { + return; + } // Protect visitors if (e.getCause().equals(DamageCause.ENTITY_ATTACK) && protectedVisitor((Player)e.getEntity())) { if (e.getDamager() instanceof Player) { @@ -53,7 +57,7 @@ public class PVPListener extends AbstractFlagListener { e.setCancelled(true); } else { // PVP check - respond(e, e.getDamager(), getFlag(e.getEntity().getWorld())); + respond(e, e.getDamager(), e.getEntity(), getFlag(e.getEntity().getWorld())); } } } @@ -64,7 +68,7 @@ public class PVPListener extends AbstractFlagListener { * @param damager - entity doing the damaging * @param flag - flag */ - private void respond(Cancellable e, Entity damager, Flag flag) { + private void respond(Cancellable e, Entity damager, Entity hurtEntity, Flag flag) { // Get the attacker if (damager instanceof Player) { User user = User.getInstance(damager); @@ -76,6 +80,10 @@ public class PVPListener extends AbstractFlagListener { // Find out who fired the arrow Projectile p = (Projectile) damager; if (p.getShooter() instanceof Player) { + // Allow self damage + if (p.getShooter().equals(hurtEntity)) { + return; + } User user = User.getInstance((Player)p.getShooter()); if (!setUser(user).checkIsland((Event)e, damager.getLocation(), flag)) { damager.setFireTicks(0); @@ -90,6 +98,10 @@ public class PVPListener extends AbstractFlagListener { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onFishing(PlayerFishEvent e) { if (e.getCaught() instanceof Player && getPlugin().getIWM().inWorld(e.getCaught().getLocation())) { + // Allow self-inflicted damage + if (e.getCaught().equals(e.getPlayer())) { + return; + } // Protect visitors if (protectedVisitor((Player)e.getCaught())) { User.getInstance(e.getPlayer()).sendMessage(Flags.INVINCIBLE_VISITORS.getHintReference()); @@ -115,7 +127,19 @@ public class PVPListener extends AbstractFlagListener { } } + /** + * Check if PVP should be blocked or not + * @param user - user who is initiating the action + * @param le - Living entity involed + * @param e - event driving + * @param flag - flag to check + * @return true if PVP should be blocked otherwise false + */ private boolean blockPVP(User user, LivingEntity le, Event e, Flag flag) { + // Check for self-inflicted damage + if (user.getPlayer().equals(le)) { + return false; + } if (le instanceof Player) { // Protect visitors if (protectedVisitor(le)) { diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/PVPListenerTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/PVPListenerTest.java index 6fda58ded..0ed703999 100644 --- a/src/test/java/us/tastybento/bskyblock/listeners/flags/PVPListenerTest.java +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/PVPListenerTest.java @@ -208,6 +208,19 @@ public class PVPListenerTest { new PVPListener().onEntityDamage(e); assertFalse(e.isCancelled()); } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onEntityDamage(org.bukkit.event.entity.EntityDamageByEntityEvent)}. + */ + @Test + public void testOnEntityDamageSelfDamage() { + Entity damager = mock(Player.class); + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(damager, damager, EntityDamageEvent.DamageCause.ENTITY_ATTACK, + new EnumMap(ImmutableMap.of(DamageModifier.BASE, 0D)), + new EnumMap>(ImmutableMap.of(DamageModifier.BASE, Functions.constant(-0.0)))); + new PVPListener().onEntityDamage(e); + assertFalse(e.isCancelled()); + } /** * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onEntityDamage(org.bukkit.event.entity.EntityDamageByEntityEvent)}. @@ -456,6 +469,22 @@ public class PVPListenerTest { Mockito.verify(player).sendMessage(Flags.PVP_OVERWORLD.getHintReference()); } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onEntityDamage(org.bukkit.event.entity.EntityDamageByEntityEvent)}. + */ + @Test + public void testOnEntityDamageSelfDamageProjectile() { + Projectile p = mock(Projectile.class); + when(p.getShooter()).thenReturn(player); + when(p.getLocation()).thenReturn(loc); + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(p, player, EntityDamageEvent.DamageCause.ENTITY_ATTACK, + new EnumMap(ImmutableMap.of(DamageModifier.BASE, 0D)), + new EnumMap>(ImmutableMap.of(DamageModifier.BASE, Functions.constant(-0.0)))); + new PVPListener().onEntityDamage(e); + // Self damage okay + assertFalse(e.isCancelled()); + } /** * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onEntityDamage(org.bukkit.event.entity.EntityDamageByEntityEvent)}. @@ -555,6 +584,19 @@ public class PVPListenerTest { Mockito.verify(player).sendMessage(Flags.INVINCIBLE_VISITORS.getHintReference()); } + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onFishing(org.bukkit.event.player.PlayerFishEvent)}. + */ + @Test + public void testOnFishingSelfDamage() { + // Fish hook + Fish hook = mock(Fish.class); + // Catch a player + PlayerFishEvent pfe = new PlayerFishEvent(player, player, hook, null); + assertFalse(pfe.isCancelled()); + Mockito.verify(player, Mockito.never()).sendMessage(Mockito.anyString()); + } + /** * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onFishing(org.bukkit.event.player.PlayerFishEvent)}. */ @@ -635,6 +677,33 @@ public class PVPListenerTest { new PVPListener().onSplashPotionSplash(e); assertFalse(e.isCancelled()); } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onSplashPotionSplash(org.bukkit.event.entity.PotionSplashEvent)}. + */ + @Test + public void testOnSplashPotionSplashSelfInflicted() { + // Disallow PVP + when(island.isAllowed(Mockito.any())).thenReturn(false); + + ThrownPotion tp = mock(ThrownPotion.class); + when(tp.getShooter()).thenReturn(player); + when(tp.getWorld()).thenReturn(world); + // Create a damage map + Map map = new HashMap<>(); + map.put(player, 100D); + map.put(zombie, 100D); + map.put(creeper, 10D); + PotionSplashEvent e = new PotionSplashEvent(tp, map); + new PVPListener().onSplashPotionSplash(e); + assertFalse(e.isCancelled()); + + // Wrong world + when(iwm.inWorld(Mockito.any())).thenReturn(false); + e = new PotionSplashEvent(tp, map); + new PVPListener().onSplashPotionSplash(e); + assertFalse(e.isCancelled()); + } /** * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onSplashPotionSplash(org.bukkit.event.entity.PotionSplashEvent)}.