diff --git a/locales/en-US.yml b/locales/en-US.yml index bdbe5d46f..e1be5c3ee 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -337,6 +337,7 @@ protection: description: | Configure invincible visitor settings. + visitors-protected: "&cVisitors protected" LEASH: "LEASH" LOCK: name: "Lock island" @@ -361,6 +362,7 @@ protection: description: | Enable/Disable PVP on island. + pvp-not-allowed: "&cPVP is not allowed" PVP_NETHER: name: "Nether PVP" description: | diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/InvincibleVisitorsListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/InvincibleVisitorsListener.java index f32f49fa5..131ee54f6 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/InvincibleVisitorsListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/InvincibleVisitorsListener.java @@ -78,10 +78,10 @@ public class InvincibleVisitorsListener extends AbstractFlagListener implements @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onVisitorGetDamage(EntityDamageEvent e) { World world = e.getEntity().getWorld(); - if (!getPlugin().getIWM().getIvSettings(world).contains(e.getCause().name()) + if (!getPlugin().getIWM().inWorld(e.getEntity().getLocation()) + || !getPlugin().getIWM().getIvSettings(world).contains(e.getCause().name()) || !(e.getEntity() instanceof Player) || e.getCause().equals(DamageCause.ENTITY_ATTACK) - || !getPlugin().getIWM().inWorld(e.getEntity().getLocation()) || getIslands().userIsOnIsland(world, User.getInstance(e.getEntity()))) { return; } 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 d333f351c..9bef62c5b 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/PVPListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/PVPListener.java @@ -3,26 +3,28 @@ package us.tastybento.bskyblock.listeners.flags; import java.util.HashMap; import java.util.UUID; +import org.bukkit.Bukkit; +import org.bukkit.World; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; +import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.AreaEffectCloudApplyEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.LingeringPotionSplashEvent; import org.bukkit.event.entity.PotionSplashEvent; import org.bukkit.event.player.PlayerFishEvent; -import org.bukkit.potion.PotionEffect; import us.tastybento.bskyblock.api.flags.Flag; import us.tastybento.bskyblock.api.user.User; import us.tastybento.bskyblock.lists.Flags; /** - * TODO: PVP is different to other flags - it's either allowed for everyone or not allowed for everyone. Currently owners can hit visitors. * Handles PVP * @author tastybento * @@ -38,23 +40,20 @@ public class PVPListener extends AbstractFlagListener { * @param e - event */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onEntityDamage(final EntityDamageByEntityEvent e) { - // Check PVP - if (e.getEntity() instanceof Player) { + public void onEntityDamage(EntityDamageByEntityEvent e) { + if (e.getEntity() instanceof Player && getPlugin().getIWM().inWorld(e.getEntity().getLocation())) { // Protect visitors - if (e.getCause().equals(DamageCause.ENTITY_ATTACK) - && getPlugin().getIWM().getIvSettings(e.getEntity().getWorld()).contains(DamageCause.ENTITY_ATTACK.name()) - && !getIslands().userIsOnIsland(e.getEntity().getWorld(), User.getInstance(e.getEntity()))) { + if (e.getCause().equals(DamageCause.ENTITY_ATTACK) && protectedVisitor((Player)e.getEntity())) { + if (e.getDamager() instanceof Player) { + User.getInstance(e.getDamager()).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + } else if (e.getDamager() instanceof Projectile && ((Projectile)e.getDamager()).getShooter() instanceof Player) { + User.getInstance((Player)((Projectile)e.getDamager()).getShooter()).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + } e.setCancelled(true); - return; + } else { + // PVP check + respond(e, e.getDamager(), getFlag(e.getEntity().getWorld())); } - Flag flag = Flags.PVP_OVERWORLD; - if (e.getEntity().getWorld().equals(getPlugin().getIWM().getNetherWorld(e.getEntity().getWorld()))) { - flag = Flags.PVP_NETHER; - } else if (e.getEntity().getWorld().equals(getPlugin().getIWM().getEndWorld(e.getEntity().getWorld()))) { - flag = Flags.PVP_END; - } - respond(e, e.getDamager(), flag); } } @@ -64,40 +63,40 @@ public class PVPListener extends AbstractFlagListener { * @param damager * @param flag */ - private void respond(Event e, Entity damager, Flag flag) { + private void respond(Cancellable e, Entity damager, Flag flag) { // Get the attacker if (damager instanceof Player) { - setUser(User.getInstance(damager)).checkIsland(e, damager.getLocation(), flag); + User user = User.getInstance(damager); + if (!setUser(user).checkIsland((Event)e, damager.getLocation(), flag)) { + user.sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + e.setCancelled(true); + } } else if (damager instanceof Projectile) { // Find out who fired the arrow Projectile p = (Projectile) damager; if (p.getShooter() instanceof Player) { - if (!setUser(User.getInstance((Player)p.getShooter())).checkIsland(e, damager.getLocation(), flag)) { + User user = User.getInstance((Player)p.getShooter()); + if (!setUser(user).checkIsland((Event)e, damager.getLocation(), flag)) { damager.setFireTicks(0); damager.remove(); + user.sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + e.setCancelled(true); } } } - } @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onFishing(PlayerFishEvent e) { - if (e.getCaught() instanceof Player) { + if (e.getCaught() instanceof Player && getPlugin().getIWM().inWorld(e.getCaught().getLocation())) { // Protect visitors - if (getPlugin().getIWM().getIvSettings(e.getPlayer().getWorld()).contains(DamageCause.ENTITY_ATTACK.name()) - && !getIslands().userIsOnIsland(e.getPlayer().getWorld(), User.getInstance(e.getCaught()))) { + if (protectedVisitor((Player)e.getCaught())) { + User.getInstance(e.getPlayer()).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); e.setCancelled(true); - return; - } - Flag flag = Flags.PVP_OVERWORLD; - if (e.getCaught().getWorld().equals(getPlugin().getIWM().getNetherWorld())) { - flag = Flags.PVP_NETHER; - } else if (e.getCaught().getWorld().equals(getPlugin().getIWM().getEndWorld())) { - flag = Flags.PVP_END; - } - if (checkIsland(e, e.getCaught().getLocation(), flag)) { + } else if (!checkIsland(e, e.getCaught().getLocation(), getFlag(e.getCaught().getWorld()))) { e.getHook().remove(); + User.getInstance(e.getPlayer()).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + e.setCancelled(true); } } } @@ -108,85 +107,56 @@ public class PVPListener extends AbstractFlagListener { */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) public void onSplashPotionSplash(final PotionSplashEvent e) { - // Deduce the world - Flag flag = Flags.PVP_OVERWORLD; - if (e.getPotion().getWorld().equals(getPlugin().getIWM().getNetherWorld())) { - flag = Flags.PVP_NETHER; - } else if (e.getPotion().getWorld().equals(getPlugin().getIWM().getEndWorld())) { - flag = Flags.PVP_END; + if (e.getEntity().getShooter() instanceof Player && getPlugin().getIWM().inWorld(e.getEntity().getLocation())) { + User user = User.getInstance((Player)e.getEntity().getShooter()); + // Run through affected entities and cancel the splash if any are a protected player + e.setCancelled(e.getAffectedEntities().stream().anyMatch(le -> blockPVP(user, le, e, getFlag(e.getEntity().getWorld())))); } - - // Try to get the thrower - Projectile projectile = e.getEntity(); - if (projectile.getShooter() instanceof Player) { - Player attacker = (Player)projectile.getShooter(); - // Run through all the affected entities - for (LivingEntity entity: e.getAffectedEntities()) { - // Self damage - if (attacker.equals(entity)) { - continue; - } - // PVP? - if (entity instanceof Player) { - // Protect visitors - if (getPlugin().getIWM().getIvSettings(entity.getWorld()).contains(DamageCause.ENTITY_ATTACK.name()) - && !getIslands().userIsOnIsland(entity.getWorld(), User.getInstance(entity))) { - e.setCancelled(true); - return; - } - if (!setUser(User.getInstance(attacker)).checkIsland(e, entity.getLocation(), flag)) { - for (PotionEffect effect : e.getPotion().getEffects()) { - entity.removePotionEffect(effect.getType()); - } - } - } + } + + private boolean blockPVP(User user, LivingEntity le, Event e, Flag flag) { + if (le instanceof Player) { + // Protect visitors + if (protectedVisitor(le)) { + user.sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + return true; + } + // Check if PVP is allowed or not + if (!checkIsland(e, le.getLocation(), flag)) { + user.sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + return true; } } + return false; + } + + private boolean protectedVisitor(LivingEntity entity) { + return getPlugin().getIWM().getIvSettings(entity.getWorld()).contains(DamageCause.ENTITY_ATTACK.name()) + && !getIslands().userIsOnIsland(entity.getWorld(), User.getInstance(entity)); } @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) public void onLingeringPotionSplash(final LingeringPotionSplashEvent e) { // Try to get the shooter - Projectile projectile = e.getEntity(); - if (projectile.getShooter() instanceof Player) { - UUID uuid = ((Player) projectile.getShooter()).getUniqueId(); - // Store it and remove it when the effect is gone - thrownPotions.put(e.getAreaEffectCloud().getEntityId(), uuid); - getPlugin().getServer().getScheduler().runTaskLater(getPlugin(), () -> thrownPotions.remove(e.getAreaEffectCloud().getEntityId()), e.getAreaEffectCloud().getDuration()); + if (e.getEntity().getShooter() instanceof Player && getPlugin().getIWM().inWorld(e.getEntity().getLocation())) { + // Store it and remove it when the effect is gone (Entity ID, UUID of throwing player) + thrownPotions.put(e.getAreaEffectCloud().getEntityId(), ((Player)e.getEntity().getShooter()).getUniqueId()); + Bukkit.getScheduler().runTaskLater(getPlugin(), () -> thrownPotions.remove(e.getAreaEffectCloud().getEntityId()), e.getAreaEffectCloud().getDuration()); } } - @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) - public void onLingeringPotionDamage(final EntityDamageByEntityEvent e) { - if (e.getEntity() == null || e.getEntity().getUniqueId() == null) { - return; - } - - if (e.getCause().equals(DamageCause.ENTITY_ATTACK) && thrownPotions.containsKey(e.getDamager().getEntityId())) { - // Deduce the world - Flag flag = Flags.PVP_OVERWORLD; - if (e.getEntity().getWorld().equals(getPlugin().getIWM().getNetherWorld())) { - flag = Flags.PVP_NETHER; - } else if (e.getEntity().getWorld().equals(getPlugin().getIWM().getEndWorld())) { - flag = Flags.PVP_END; - } - - UUID attacker = thrownPotions.get(e.getDamager().getEntityId()); - // Self damage - if (attacker.equals(e.getEntity().getUniqueId())) { - return; - } - Entity entity = e.getEntity(); - // PVP? - if (entity instanceof Player) { - // Protect visitors - if (getPlugin().getIWM().getIvSettings(entity.getWorld()).contains(DamageCause.ENTITY_ATTACK.name()) - && !getIslands().userIsOnIsland(entity.getWorld(), User.getInstance(entity))) { - e.setCancelled(true); - return; - } - checkIsland(e, entity.getLocation(), flag); - } + @EventHandler(priority = EventPriority.NORMAL) + public void onLingeringPotionDamage(AreaEffectCloudApplyEvent e) { + if (e.getEntity() != null && thrownPotions.containsKey(e.getEntity().getEntityId())) { + User user = User.getInstance(thrownPotions.get(e.getEntity().getEntityId())); + // Run through affected entities and delete them if they are safe + e.getAffectedEntities().removeIf(le -> !le.getUniqueId().equals(user.getUniqueId()) && blockPVP(user, le, e, getFlag(e.getEntity().getWorld()))); } } + + private Flag getFlag(World w) { + return w.getEnvironment().equals(World.Environment.NORMAL) ? Flags.PVP_OVERWORLD + : w.getEnvironment().equals(World.Environment.NETHER) ? Flags.PVP_NETHER : Flags.PVP_END; + } + } diff --git a/src/main/java/us/tastybento/bskyblock/lists/Flags.java b/src/main/java/us/tastybento/bskyblock/lists/Flags.java index 1d9ac150d..9962144de 100644 --- a/src/main/java/us/tastybento/bskyblock/lists/Flags.java +++ b/src/main/java/us/tastybento/bskyblock/lists/Flags.java @@ -36,6 +36,8 @@ import us.tastybento.bskyblock.listeners.flags.clicklisteners.WorldToggleClickLi import us.tastybento.bskyblock.managers.RanksManager; public class Flags { + // Disabled setting 'rank' + private static final int DISABLED = -1; // TODO: add DYEING sheeps // TODO: add ELYTRA @@ -134,11 +136,11 @@ public class Flags { */ // PVP public static final Flag PVP_OVERWORLD = new FlagBuilder().id("PVP_OVERWORLD").icon(Material.ARROW).type(Type.SETTING) - .listener(new PVPListener()).onClick(new IslandToggleClickListener("PVP_OVERWORLD")).build(); + .defaultRank(DISABLED).listener(new PVPListener()).onClick(new IslandToggleClickListener("PVP_OVERWORLD")).build(); public static final Flag PVP_NETHER = new FlagBuilder().id("PVP_NETHER").icon(Material.IRON_AXE).type(Type.SETTING) - .onClick(new IslandToggleClickListener("PVP_NETHER")).build(); + .defaultRank(DISABLED).onClick(new IslandToggleClickListener("PVP_NETHER")).build(); public static final Flag PVP_END = new FlagBuilder().id("PVP_END").icon(Material.END_CRYSTAL).type(Type.SETTING) - .onClick(new IslandToggleClickListener("PVP_END")).build(); + .defaultRank(DISABLED).onClick(new IslandToggleClickListener("PVP_END")).build(); // Others public static final Flag ANIMAL_SPAWN = new FlagBuilder().id("ANIMAL_SPAWN").icon(Material.APPLE).allowedByDefault(true).type(Type.SETTING).build(); public static final Flag MONSTER_SPAWN = new FlagBuilder().id("MONSTER_SPAWN").icon(Material.MOB_SPAWNER).allowedByDefault(true).type(Type.SETTING).build(); diff --git a/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java b/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java index b349f9c7d..666266070 100644 --- a/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java @@ -462,7 +462,7 @@ public class IslandWorldManager { * @return invisible visitor settings */ public List getIvSettings(World world) { - return worldSettings.get(world).getIvSettings(); + return worldSettings.get(Util.getWorld(world)).getIvSettings(); } } diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/PVPListenerTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/PVPListenerTest.java new file mode 100644 index 000000000..f0d56b2df --- /dev/null +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/PVPListenerTest.java @@ -0,0 +1,871 @@ +/** + * + */ +package us.tastybento.bskyblock.listeners.flags; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.AreaEffectCloud; +import org.bukkit.entity.Creeper; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Fish; +import org.bukkit.entity.LingeringPotion; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.ThrownPotion; +import org.bukkit.entity.Witch; +import org.bukkit.entity.Zombie; +import org.bukkit.event.entity.AreaEffectCloudApplyEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageModifier; +import org.bukkit.event.entity.LingeringPotionSplashEvent; +import org.bukkit.event.entity.PotionSplashEvent; +import org.bukkit.event.player.PlayerFishEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.projectiles.ProjectileSource; +import org.bukkit.scheduler.BukkitScheduler; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.collect.ImmutableMap; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.Settings; +import us.tastybento.bskyblock.api.flags.Flag; +import us.tastybento.bskyblock.api.panels.Panel; +import us.tastybento.bskyblock.api.panels.PanelItem; +import us.tastybento.bskyblock.api.user.User; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.managers.FlagsManager; +import us.tastybento.bskyblock.managers.IslandWorldManager; +import us.tastybento.bskyblock.managers.IslandsManager; +import us.tastybento.bskyblock.managers.LocalesManager; +import us.tastybento.bskyblock.util.Util; + +/** + * @author tastybento + * + */ +@SuppressWarnings("deprecation") +@RunWith(PowerMockRunner.class) +@PrepareForTest({BSkyBlock.class, Util.class, Bukkit.class }) +public class PVPListenerTest { + + private IslandWorldManager iwm; + private Panel panel; + private Flag flag; + private IslandsManager im; + private Settings s; + private Island island; + private Player player; + private Player player2; + private Location loc; + private Zombie zombie; + private Creeper creeper; + private World world; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + // Set up plugin + BSkyBlock plugin = mock(BSkyBlock.class); + Whitebox.setInternalState(BSkyBlock.class, "instance", plugin); + // Island World Manager + iwm = mock(IslandWorldManager.class); + when(iwm.inWorld(Mockito.any())).thenReturn(true); + when(iwm.getPermissionPrefix(Mockito.any())).thenReturn("bskyblock"); + // No visitor protection right now + when(iwm.getIvSettings(Mockito.any())).thenReturn(new ArrayList<>()); + when(plugin.getIWM()).thenReturn(iwm); + + panel = mock(Panel.class); + when(panel.getInventory()).thenReturn(mock(Inventory.class)); + + // Sometimes use Mockito.withSettings().verboseLogging() + player = mock(Player.class); + UUID uuid = UUID.randomUUID(); + when(player.getUniqueId()).thenReturn(uuid); + + world = mock(World.class); + when(world.getEnvironment()).thenReturn(World.Environment.NORMAL); + when(player.getWorld()).thenReturn(world); + + loc = mock(Location.class); + when(loc.getWorld()).thenReturn(world); + + when(player.getLocation()).thenReturn(loc); + User.getInstance(player); + + // Sometimes use Mockito.withSettings().verboseLogging() + player2 = mock(Player.class); + UUID uuid2 = UUID.randomUUID(); + when(player2.getUniqueId()).thenReturn(uuid2); + + when(player2.getWorld()).thenReturn(world); + when(player2.getLocation()).thenReturn(loc); + User.getInstance(player2); + + PowerMockito.mockStatic(Util.class); + when(Util.getWorld(Mockito.any())).thenReturn(mock(World.class)); + + FlagsManager fm = mock(FlagsManager.class); + flag = mock(Flag.class); + when(flag.isSetForWorld(Mockito.any())).thenReturn(false); + PanelItem item = mock(PanelItem.class); + when(item.getItem()).thenReturn(mock(ItemStack.class)); + when(flag.toPanelItem(Mockito.any(), Mockito.any())).thenReturn(item); + when(fm.getFlagByID(Mockito.anyString())).thenReturn(flag); + when(plugin.getFlagsManager()).thenReturn(fm); + + im = mock(IslandsManager.class); + // Default is that player in on their island + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(true); + island = mock(Island.class); + when(im.getIslandAt(Mockito.any())).thenReturn(Optional.of(island)); + // All flags are disallowed by default. + when(island.isAllowed(Mockito.any())).thenReturn(false); + when(plugin.getIslands()).thenReturn(im); + + // Settings + s = mock(Settings.class); + when(plugin.getSettings()).thenReturn(s); + + // Locales - this returns the string that was requested for translation + LocalesManager lm = mock(LocalesManager.class); + when(plugin.getLocalesManager()).thenReturn(lm); + when(lm.get(any(), any())).thenAnswer(new Answer() { + + @Override + public String answer(InvocationOnMock invocation) throws Throwable { + return invocation.getArgumentAt(1, String.class); + }}); + + // Create some entities + zombie = mock(Zombie.class); + when(zombie.getWorld()).thenReturn(world); + when(zombie.getUniqueId()).thenReturn(UUID.randomUUID()); + creeper = mock(Creeper.class); + when(creeper.getWorld()).thenReturn(world); + when(creeper.getUniqueId()).thenReturn(UUID.randomUUID()); + + // Scheduler + BukkitScheduler sch = mock(BukkitScheduler.class); + PowerMockito.mockStatic(Bukkit.class); + when(Bukkit.getScheduler()).thenReturn(sch); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onEntityDamage(org.bukkit.event.entity.EntityDamageByEntityEvent)}. + */ + @Test + public void testOnEntityDamageNotPlayer() { + Entity damager = mock(Zombie.class); + Entity damagee = mock(Creeper.class); + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(damager, damagee, 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)}. + */ + @Test + public void testOnEntityDamageOnPlayerByZombie() { + Entity damager = mock(Zombie.class); + Entity damagee = mock(Player.class); + World world = mock(World.class); + when(world.getEnvironment()).thenReturn(World.Environment.NORMAL); + when(damager.getWorld()).thenReturn(world); + when(damagee.getWorld()).thenReturn(world); + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(damager, damagee, 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()); + + // Different attack type + e = new EntityDamageByEntityEvent(damager, damagee, EntityDamageEvent.DamageCause.ENTITY_SWEEP_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()); + + // Wrong world + e = new EntityDamageByEntityEvent(damager, damagee, EntityDamageEvent.DamageCause.ENTITY_ATTACK, + new EnumMap(ImmutableMap.of(DamageModifier.BASE, 0D)), + new EnumMap>(ImmutableMap.of(DamageModifier.BASE, Functions.constant(-0.0)))); + when(iwm.inWorld(Mockito.any())).thenReturn(false); + 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 testOnEntityDamageOnPlayerByZombieVisitorProtected() { + Entity damager = mock(Zombie.class); + Entity damagee = mock(Player.class); + World world = mock(World.class); + when(world.getEnvironment()).thenReturn(World.Environment.NORMAL); + when(damager.getWorld()).thenReturn(world); + when(damagee.getWorld()).thenReturn(world); + + // Protect visitors + List visitorProtectionList = new ArrayList<>(); + visitorProtectionList.add("ENTITY_ATTACK"); + when(iwm.getIvSettings(world)).thenReturn(visitorProtectionList); + // This player is on their island, i.e., not a visitor + + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(damager, damagee, 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()); + // Wrong world + e = new EntityDamageByEntityEvent(damager, damagee, EntityDamageEvent.DamageCause.ENTITY_ATTACK, + new EnumMap(ImmutableMap.of(DamageModifier.BASE, 0D)), + new EnumMap>(ImmutableMap.of(DamageModifier.BASE, Functions.constant(-0.0)))); + when(iwm.inWorld(Mockito.any())).thenReturn(false); + 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 testOnEntityDamageOnVisitorByZombieVisitorProtected() { + Entity damager = mock(Zombie.class); + Entity damagee = mock(Player.class); + World world = mock(World.class); + when(world.getEnvironment()).thenReturn(World.Environment.NORMAL); + when(damager.getWorld()).thenReturn(world); + when(damagee.getWorld()).thenReturn(world); + + // Protect visitors + List visitorProtectionList = new ArrayList<>(); + visitorProtectionList.add("ENTITY_ATTACK"); + when(iwm.getIvSettings(world)).thenReturn(visitorProtectionList); + // This player is a visitor + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(damager, damagee, 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); + assertTrue(e.isCancelled()); + // Wrong world + e = new EntityDamageByEntityEvent(damager, damagee, EntityDamageEvent.DamageCause.ENTITY_ATTACK, + new EnumMap(ImmutableMap.of(DamageModifier.BASE, 0D)), + new EnumMap>(ImmutableMap.of(DamageModifier.BASE, Functions.constant(-0.0)))); + when(iwm.inWorld(Mockito.any())).thenReturn(false); + 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 testOnEntityDamageOnVisitorByZombieVisitorProtectedWrongDamage() { + Entity damager = mock(Zombie.class); + Entity damagee = mock(Player.class); + World world = mock(World.class); + when(world.getEnvironment()).thenReturn(World.Environment.NORMAL); + when(damager.getWorld()).thenReturn(world); + when(damagee.getWorld()).thenReturn(world); + + // Protect visitors + List visitorProtectionList = new ArrayList<>(); + visitorProtectionList.add("ENTITY_ATTACK"); + when(iwm.getIvSettings(world)).thenReturn(visitorProtectionList); + // This player is a visitor + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + // Damage is not entity attack + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(damager, damagee, EntityDamageEvent.DamageCause.THORNS, + new EnumMap(ImmutableMap.of(DamageModifier.BASE, 0D)), + new EnumMap>(ImmutableMap.of(DamageModifier.BASE, Functions.constant(-0.0)))); + new PVPListener().onEntityDamage(e); + assertFalse(e.isCancelled()); + // Wrong world + when(iwm.inWorld(Mockito.any())).thenReturn(false); + 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 testOnEntityDamageOnVisitorByZombieVisitorNotProtected() { + Entity damager = mock(Zombie.class); + Entity damagee = mock(Player.class); + World world = mock(World.class); + when(world.getEnvironment()).thenReturn(World.Environment.NORMAL); + when(damager.getWorld()).thenReturn(world); + when(damagee.getWorld()).thenReturn(world); + + // This player is a visitor + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(damager, damagee, 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()); + // Wrong world + e = new EntityDamageByEntityEvent(damager, damagee, EntityDamageEvent.DamageCause.ENTITY_ATTACK, + new EnumMap(ImmutableMap.of(DamageModifier.BASE, 0D)), + new EnumMap>(ImmutableMap.of(DamageModifier.BASE, Functions.constant(-0.0)))); + when(iwm.inWorld(Mockito.any())).thenReturn(false); + new PVPListener().onEntityDamage(e); + assertFalse(e.isCancelled()); + } + + // PVP TESTS + /* + * PVP Tests + * + * Variables: + * PVP on/off -> Direct hit / Projectile + * Visitor protection on/off -> protection type correct/incorrect + * + */ + + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onEntityDamage(org.bukkit.event.entity.EntityDamageByEntityEvent)}. + */ + @Test + public void testOnEntityDamagePVPNotAllowed() { + + // No visitor protection + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(player, player2, 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); + // PVP should be banned + assertTrue(e.isCancelled()); + Mockito.verify(player).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + + // Enable visitor protection + // This player is a visitor and any damage is not allowed + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + when(iwm.getIvSettings(Mockito.any())).thenReturn(Arrays.asList("ENTITY_ATTACK")); + new PVPListener().onEntityDamage(e); + // visitor should be protected + assertTrue(e.isCancelled()); + Mockito.verify(player).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onEntityDamage(org.bukkit.event.entity.EntityDamageByEntityEvent)}. + */ + @Test + public void testOnEntityDamageOnPVPAllowed() { + // PVP is allowed + when(island.isAllowed(Mockito.any())).thenReturn(true); + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(player, player2, 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); + // PVP should be allowed + assertFalse(e.isCancelled()); + Mockito.verify(player, Mockito.never()).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + + // Enable visitor protection + // This player is a visitor and any damage is not allowed + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + when(iwm.getIvSettings(Mockito.any())).thenReturn(Arrays.asList("ENTITY_ATTACK")); + new PVPListener().onEntityDamage(e); + // visitor should be protected + assertTrue(e.isCancelled()); + Mockito.verify(player).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onEntityDamage(org.bukkit.event.entity.EntityDamageByEntityEvent)}. + */ + @Test + public void testOnEntityDamageOnPVPNotAllowedProjectile() { + Projectile p = mock(Projectile.class); + when(p.getShooter()).thenReturn(player); + when(p.getLocation()).thenReturn(loc); + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(p, player2, 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); + // PVP should be banned + assertTrue(e.isCancelled()); + Mockito.verify(player).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + + // Visitor protection + // This player is a visitor and any damage is not allowed + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + when(iwm.getIvSettings(Mockito.any())).thenReturn(Arrays.asList("ENTITY_ATTACK")); + new PVPListener().onEntityDamage(e); + // visitor should be protected + assertTrue(e.isCancelled()); + // PVP trumps visitor protection + Mockito.verify(player).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onEntityDamage(org.bukkit.event.entity.EntityDamageByEntityEvent)}. + */ + @Test + public void testOnEntityDamagePVPAllowedProjectile() { + Projectile p = mock(Projectile.class); + when(p.getShooter()).thenReturn(player); + when(p.getLocation()).thenReturn(loc); + // PVP is allowed + when(island.isAllowed(Mockito.any())).thenReturn(true); + EntityDamageByEntityEvent e = new EntityDamageByEntityEvent(p, player2, 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); + // PVP should be allowed + assertFalse(e.isCancelled()); + Mockito.verify(player, Mockito.never()).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + + // Enable visitor protection + // This player is a visitor and any damage is not allowed + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + when(iwm.getIvSettings(Mockito.any())).thenReturn(Arrays.asList("ENTITY_ATTACK")); + new PVPListener().onEntityDamage(e); + // visitor should be protected + assertTrue(e.isCancelled()); + Mockito.verify(player).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + + } + + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onFishing(org.bukkit.event.player.PlayerFishEvent)}. + */ + @Test + public void testOnFishing() { + // Fish hook + Fish hook = mock(Fish.class); + // Catch a zombie - fine + Entity caught = mock(Zombie.class); + PlayerFishEvent pfe = new PlayerFishEvent(player, caught, hook, null); + new PVPListener().onFishing(pfe); + assertFalse(pfe.isCancelled()); + + // Catch a player + pfe = new PlayerFishEvent(player, player2, hook, null); + new PVPListener().onFishing(pfe); + + // PVP should be banned + assertTrue(pfe.isCancelled()); + Mockito.verify(player).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + // Hook should be removed + Mockito.verify(hook).remove(); + + // Wrong world + when(iwm.inWorld(Mockito.any())).thenReturn(false); + pfe = new PlayerFishEvent(player, player2, hook, null); + new PVPListener().onFishing(pfe); + assertFalse(pfe.isCancelled()); + + // Correct world + when(iwm.inWorld(Mockito.any())).thenReturn(true); + + // Allow PVP + when(island.isAllowed(Mockito.any())).thenReturn(true); + pfe = new PlayerFishEvent(player, player2, hook, null); + new PVPListener().onFishing(pfe); + assertFalse(pfe.isCancelled()); + + // Wrong world + when(iwm.inWorld(Mockito.any())).thenReturn(false); + pfe = new PlayerFishEvent(player, player2, hook, null); + new PVPListener().onFishing(pfe); + assertFalse(pfe.isCancelled()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onFishing(org.bukkit.event.player.PlayerFishEvent)}. + */ + @Test + public void testOnFishingProtectVisitors() { + // Fish hook + Fish hook = mock(Fish.class); + // Catch a player + PlayerFishEvent pfe = new PlayerFishEvent(player, player2, hook, null); + + // Allow PVP + when(island.isAllowed(Mockito.any())).thenReturn(true); + + // Protect visitors + // This player is a visitor and any damage is not allowed + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + when(iwm.getIvSettings(Mockito.any())).thenReturn(Arrays.asList("ENTITY_ATTACK")); + new PVPListener().onFishing(pfe); + // visitor should be protected + assertTrue(pfe.isCancelled()); + Mockito.verify(player).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onFishing(org.bukkit.event.player.PlayerFishEvent)}. + */ + @Test + public void testOnFishingNoPVPProtectVisitors() { + // Fish hook + Fish hook = mock(Fish.class); + // Catch a player + PlayerFishEvent pfe = new PlayerFishEvent(player, player2, hook, null); + + // Disallow PVP + when(island.isAllowed(Mockito.any())).thenReturn(false); + + // Protect visitors + // This player is a visitor and any damage is not allowed + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + when(iwm.getIvSettings(Mockito.any())).thenReturn(Arrays.asList("ENTITY_ATTACK")); + new PVPListener().onFishing(pfe); + // visitor should be protected + assertTrue(pfe.isCancelled()); + Mockito.verify(player).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onSplashPotionSplash(org.bukkit.event.entity.PotionSplashEvent)}. + */ + @Test + public void testOnSplashPotionSplashWitch() { + ThrownPotion tp = mock(ThrownPotion.class); + ProjectileSource witch = mock(Witch.class); + when(tp.getShooter()).thenReturn(witch); + PotionSplashEvent e = new PotionSplashEvent(tp, new HashMap<>()); + 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 testOnSplashPotionSplashNoPlayers() { + 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(zombie, 100D); + map.put(creeper, 10D); + PotionSplashEvent 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)}. + */ + @Test + public void testOnSplashPotionSplash() { + // 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(player2, 100D); + map.put(zombie, 100D); + map.put(creeper, 10D); + PotionSplashEvent e = new PotionSplashEvent(tp, map); + new PVPListener().onSplashPotionSplash(e); + assertTrue(e.isCancelled()); + Mockito.verify(player).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + + // 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)}. + */ + @Test + public void testOnSplashPotionSplashAllowPVP() { + // Disallow PVP + when(island.isAllowed(Mockito.any())).thenReturn(true); + + 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(player2, 100D); + map.put(zombie, 100D); + map.put(creeper, 10D); + PotionSplashEvent e = new PotionSplashEvent(tp, map); + new PVPListener().onSplashPotionSplash(e); + assertFalse(e.isCancelled()); + Mockito.verify(player, Mockito.never()).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + } + + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onSplashPotionSplash(org.bukkit.event.entity.PotionSplashEvent)}. + */ + @Test + public void testOnSplashPotionSplashAllowPVPProtectVisitors() { + // Allow PVP + when(island.isAllowed(Mockito.any())).thenReturn(true); + + 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(player2, 100D); + map.put(zombie, 100D); + map.put(creeper, 10D); + PotionSplashEvent e = new PotionSplashEvent(tp, map); + // Protect visitors + // This player is a visitor and any damage is not allowed + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + when(iwm.getIvSettings(Mockito.any())).thenReturn(Arrays.asList("ENTITY_ATTACK")); + new PVPListener().onSplashPotionSplash(e); + // visitor should be protected + assertTrue(e.isCancelled()); + Mockito.verify(player).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + + // 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#onLingeringPotionSplash(org.bukkit.event.entity.LingeringPotionSplashEvent)}. + */ + @Test + public void testOnLingeringPotionSplash() { + LingeringPotion tp = mock(LingeringPotion.class); + when(tp.getShooter()).thenReturn(player); + when(tp.getWorld()).thenReturn(world); + AreaEffectCloud cloud = mock(AreaEffectCloud.class); + LingeringPotionSplashEvent e = new LingeringPotionSplashEvent(tp, cloud); + new PVPListener().onLingeringPotionSplash(e); + // Verify + Mockito.verify(player, Mockito.times(4)).getUniqueId(); + Mockito.verify(cloud).getEntityId(); + Mockito.verify(tp, Mockito.times(2)).getShooter(); + PowerMockito.verifyStatic(Bukkit.class); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onLingeringPotionSplash(org.bukkit.event.entity.LingeringPotionSplashEvent)}. + */ + @Test + public void testOnLingeringPotionSplashNonHuman() { + LingeringPotion tp = mock(LingeringPotion.class); + when(tp.getShooter()).thenReturn(creeper); + when(tp.getWorld()).thenReturn(world); + AreaEffectCloud cloud = mock(AreaEffectCloud.class); + LingeringPotionSplashEvent e = new LingeringPotionSplashEvent(tp, cloud); + new PVPListener().onLingeringPotionSplash(e); + // Verify + Mockito.verify(cloud, Mockito.never()).getEntityId(); + Mockito.verify(tp).getShooter(); + PowerMockito.verifyStatic(Bukkit.class, Mockito.never()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onLingeringPotionDamage(org.bukkit.event.entity.AreaEffectCloudApplyEvent)}. + */ + @Test + public void testOnLingeringPotionDamageNoPVP() { + // Disallow PVP + when(island.isAllowed(Mockito.any())).thenReturn(false); + // Throw a potion + LingeringPotion tp = mock(LingeringPotion.class); + when(tp.getShooter()).thenReturn(player); + when(tp.getWorld()).thenReturn(world); + AreaEffectCloud cloud = mock(AreaEffectCloud.class); + when(cloud.getWorld()).thenReturn(world); + LingeringPotionSplashEvent e = new LingeringPotionSplashEvent(tp, cloud); + PVPListener listener = new PVPListener(); + listener.onLingeringPotionSplash(e); + List list = new ArrayList<>(); + list.add(player); // This player will still suffer + list.add(creeper); + list.add(player2); + list.add(zombie); + // See who it affects + AreaEffectCloudApplyEvent ae = new AreaEffectCloudApplyEvent(cloud, list); + listener.onLingeringPotionDamage(ae); + assertEquals(3, ae.getAffectedEntities().size()); + assertFalse(ae.getAffectedEntities().contains(player2)); + Mockito.verify(player).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + // Wrong world + when(iwm.inWorld(Mockito.any())).thenReturn(false); + listener.onLingeringPotionSplash(e); + // No change to results + assertEquals(3, ae.getAffectedEntities().size()); + assertFalse(ae.getAffectedEntities().contains(player2)); + Mockito.verify(player).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onLingeringPotionDamage(org.bukkit.event.entity.AreaEffectCloudApplyEvent)}. + */ + @Test + public void testOnLingeringPotionDamagePVP() { + // Allow PVP + when(island.isAllowed(Mockito.any())).thenReturn(true); + // Throw a potion + LingeringPotion tp = mock(LingeringPotion.class); + when(tp.getShooter()).thenReturn(player); + when(tp.getWorld()).thenReturn(world); + AreaEffectCloud cloud = mock(AreaEffectCloud.class); + when(cloud.getWorld()).thenReturn(world); + LingeringPotionSplashEvent e = new LingeringPotionSplashEvent(tp, cloud); + PVPListener listener = new PVPListener(); + listener.onLingeringPotionSplash(e); + List list = new ArrayList<>(); + list.add(player); // This player will still suffer + list.add(creeper); + list.add(player2); + list.add(zombie); + // See who it affects + AreaEffectCloudApplyEvent ae = new AreaEffectCloudApplyEvent(cloud, list); + listener.onLingeringPotionDamage(ae); + assertEquals(4, ae.getAffectedEntities().size()); + Mockito.verify(player, Mockito.never()).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + // Wrong world + when(iwm.inWorld(Mockito.any())).thenReturn(false); + listener.onLingeringPotionSplash(e); + assertEquals(4, ae.getAffectedEntities().size()); + Mockito.verify(player, Mockito.never()).sendMessage("protection.flags.PVP_OVERWORLD.pvp-not-allowed"); + } + + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onLingeringPotionDamage(org.bukkit.event.entity.AreaEffectCloudApplyEvent)}. + */ + @Test + public void testOnLingeringPotionDamageNoPVPVisitor() { + // Disallow PVP + when(island.isAllowed(Mockito.any())).thenReturn(false); + // Throw a potion + LingeringPotion tp = mock(LingeringPotion.class); + when(tp.getShooter()).thenReturn(player); + when(tp.getWorld()).thenReturn(world); + AreaEffectCloud cloud = mock(AreaEffectCloud.class); + when(cloud.getWorld()).thenReturn(world); + LingeringPotionSplashEvent e = new LingeringPotionSplashEvent(tp, cloud); + PVPListener listener = new PVPListener(); + listener.onLingeringPotionSplash(e); + List list = new ArrayList<>(); + list.add(player); // This player will still suffer + list.add(creeper); + list.add(player2); + list.add(zombie); + // Protect visitor + // This player is a visitor and any damage is not allowed + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + when(iwm.getIvSettings(Mockito.any())).thenReturn(Arrays.asList("ENTITY_ATTACK")); + + // See who it affects + AreaEffectCloudApplyEvent ae = new AreaEffectCloudApplyEvent(cloud, list); + listener.onLingeringPotionDamage(ae); + assertEquals(3, ae.getAffectedEntities().size()); + assertFalse(ae.getAffectedEntities().contains(player2)); + Mockito.verify(player).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + // Wrong world + when(iwm.inWorld(Mockito.any())).thenReturn(false); + listener.onLingeringPotionSplash(e); + assertEquals(3, ae.getAffectedEntities().size()); + assertFalse(ae.getAffectedEntities().contains(player2)); + Mockito.verify(player).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.PVPListener#onLingeringPotionDamage(org.bukkit.event.entity.AreaEffectCloudApplyEvent)}. + */ + @Test + public void testOnLingeringPotionDamagePVPVisitor() { + // Allow PVP + when(island.isAllowed(Mockito.any())).thenReturn(true); + // Throw a potion + LingeringPotion tp = mock(LingeringPotion.class); + when(tp.getShooter()).thenReturn(player); + when(tp.getWorld()).thenReturn(world); + AreaEffectCloud cloud = mock(AreaEffectCloud.class); + when(cloud.getWorld()).thenReturn(world); + LingeringPotionSplashEvent e = new LingeringPotionSplashEvent(tp, cloud); + PVPListener listener = new PVPListener(); + listener.onLingeringPotionSplash(e); + List list = new ArrayList<>(); + list.add(player); // This player will still suffer + list.add(creeper); + list.add(player2); + list.add(zombie); + // Protect visitor + // This player is a visitor and any damage is not allowed + when(im.userIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); + when(iwm.getIvSettings(Mockito.any())).thenReturn(Arrays.asList("ENTITY_ATTACK")); + + // See who it affects + AreaEffectCloudApplyEvent ae = new AreaEffectCloudApplyEvent(cloud, list); + listener.onLingeringPotionDamage(ae); + assertEquals(3, ae.getAffectedEntities().size()); + assertFalse(ae.getAffectedEntities().contains(player2)); + Mockito.verify(player).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + // Wrong world + when(iwm.inWorld(Mockito.any())).thenReturn(false); + listener.onLingeringPotionSplash(e); + assertEquals(3, ae.getAffectedEntities().size()); + assertFalse(ae.getAffectedEntities().contains(player2)); + Mockito.verify(player).sendMessage("protection.flags.INVINCIBLE_VISITORS.visitors-protected"); + } +}