From 060549b5eceec91160f7e8598e01d4c0588289e5 Mon Sep 17 00:00:00 2001 From: tastybento Date: Fri, 11 May 2018 21:05:19 -0700 Subject: [PATCH] Switched to List from LinkedList for tab complete. Added FlyingMobs test. --- .../us/tastybento/bskyblock/BSkyBlock.java | 3 + .../bskyblock/api/commands/BSBCommand.java | 3 +- .../commands/admin/AdminGetRankCommand.java | 3 +- .../commands/admin/AdminSetRankCommand.java | 3 +- .../commands/admin/AdminTeleportCommand.java | 5 +- .../commands/island/IslandBanCommand.java | 5 +- .../commands/island/IslandUnbanCommand.java | 5 +- .../island/teams/IslandTeamInviteCommand.java | 5 +- .../teams/IslandTeamSetownerCommand.java | 5 +- .../listeners/protection/FlyingMobEvents.java | 71 ++-- src/test/java/bskyblock/TestBSkyBlock.java | 5 +- .../listeners/ObsidianToLavaTest.java | 5 - .../protection/FlyingMobEventsTest.java | 394 ++++++++++++++++++ 13 files changed, 447 insertions(+), 65 deletions(-) create mode 100644 src/test/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEventsTest.java diff --git a/src/main/java/us/tastybento/bskyblock/BSkyBlock.java b/src/main/java/us/tastybento/bskyblock/BSkyBlock.java index e4ad86588..aa28422a5 100755 --- a/src/main/java/us/tastybento/bskyblock/BSkyBlock.java +++ b/src/main/java/us/tastybento/bskyblock/BSkyBlock.java @@ -13,6 +13,7 @@ import us.tastybento.bskyblock.listeners.JoinLeaveListener; import us.tastybento.bskyblock.listeners.NetherPortals; import us.tastybento.bskyblock.listeners.ObsidianToLava; import us.tastybento.bskyblock.listeners.PanelListenerManager; +import us.tastybento.bskyblock.listeners.protection.FlyingMobEvents; import us.tastybento.bskyblock.managers.AddonsManager; import us.tastybento.bskyblock.managers.CommandsManager; import us.tastybento.bskyblock.managers.FlagsManager; @@ -149,6 +150,8 @@ public class BSkyBlock extends JavaPlugin { manager.registerEvents(new NetherPortals(this), this); // Obsidian to lava helper manager.registerEvents(new ObsidianToLava(this), this); + // Flying mobs protection + manager.registerEvents(new FlyingMobEvents(this), this); } @Override diff --git a/src/main/java/us/tastybento/bskyblock/api/commands/BSBCommand.java b/src/main/java/us/tastybento/bskyblock/api/commands/BSBCommand.java index e5b9c31c5..8a92019d0 100644 --- a/src/main/java/us/tastybento/bskyblock/api/commands/BSBCommand.java +++ b/src/main/java/us/tastybento/bskyblock/api/commands/BSBCommand.java @@ -1,6 +1,5 @@ package us.tastybento.bskyblock.api.commands; -import java.util.LinkedList; import java.util.List; import java.util.Optional; @@ -35,7 +34,7 @@ public interface BSBCommand { * @param args * @return List of strings that could be used to complete this command. */ - default Optional> tabComplete(User user, String alias, LinkedList args) { + default Optional> tabComplete(User user, String alias, List args) { return Optional.empty(); } diff --git a/src/main/java/us/tastybento/bskyblock/commands/admin/AdminGetRankCommand.java b/src/main/java/us/tastybento/bskyblock/commands/admin/AdminGetRankCommand.java index 850ccba6d..d4dbb9722 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/admin/AdminGetRankCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/admin/AdminGetRankCommand.java @@ -3,7 +3,6 @@ */ package us.tastybento.bskyblock.commands.admin; -import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -69,7 +68,7 @@ public class AdminGetRankCommand extends CompositeCommand { } @Override - public Optional> tabComplete(final User user, final String alias, final LinkedList args) { + public Optional> tabComplete(User user, String alias, List args) { return Optional.of(Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList())); } } diff --git a/src/main/java/us/tastybento/bskyblock/commands/admin/AdminSetRankCommand.java b/src/main/java/us/tastybento/bskyblock/commands/admin/AdminSetRankCommand.java index c6ab28eea..5a6454c18 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/admin/AdminSetRankCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/admin/AdminSetRankCommand.java @@ -3,7 +3,6 @@ */ package us.tastybento.bskyblock.commands.admin; -import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -75,7 +74,7 @@ public class AdminSetRankCommand extends CompositeCommand { } @Override - public Optional> tabComplete(final User user, final String alias, final LinkedList args) { + public Optional> tabComplete(User user, String alias, List args) { return Optional.of(getPlugin().getRanksManager().getRanks().keySet().stream().map(user::getTranslation).collect(Collectors.toList())); } } diff --git a/src/main/java/us/tastybento/bskyblock/commands/admin/AdminTeleportCommand.java b/src/main/java/us/tastybento/bskyblock/commands/admin/AdminTeleportCommand.java index 3e8b3f4d0..e8473c3cc 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/admin/AdminTeleportCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/admin/AdminTeleportCommand.java @@ -1,7 +1,6 @@ package us.tastybento.bskyblock.commands.admin; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -63,9 +62,9 @@ public class AdminTeleportCommand extends CompositeCommand { } @Override - public Optional> tabComplete(final User user, final String alias, final LinkedList args) { + public Optional> tabComplete(User user, String alias, List args) { List options = new ArrayList<>(); - String lastArg = (!args.isEmpty() ? args.getLast() : ""); + String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; if (args.isEmpty()) { // Don't show every player on the server. Require at least the first letter return Optional.empty(); diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/IslandBanCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/IslandBanCommand.java index 091f1fc90..8dfd6b245 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/IslandBanCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/IslandBanCommand.java @@ -1,6 +1,5 @@ package us.tastybento.bskyblock.commands.island; -import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -93,7 +92,7 @@ public class IslandBanCommand extends CompositeCommand { } @Override - public Optional> tabComplete(final User user, final String alias, final LinkedList args) { + public Optional> tabComplete(User user, String alias, List args) { if (args.isEmpty()) { // Don't show every player on the server. Require at least the first letter return Optional.empty(); @@ -104,7 +103,7 @@ public class IslandBanCommand extends CompositeCommand { .filter(p -> !island.isBanned(p.getUniqueId())) .filter(p -> user.getPlayer().canSee(p)) .map(Player::getName).collect(Collectors.toList()); - String lastArg = (!args.isEmpty() ? args.getLast() : ""); + String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; return Optional.of(Util.tabLimit(options, lastArg)); } } diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/IslandUnbanCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/IslandUnbanCommand.java index f3103920b..f7d2c13c5 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/IslandUnbanCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/IslandUnbanCommand.java @@ -1,6 +1,5 @@ package us.tastybento.bskyblock.commands.island; -import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -74,10 +73,10 @@ public class IslandUnbanCommand extends CompositeCommand { } @Override - public Optional> tabComplete(final User user, final String alias, final LinkedList args) { + public Optional> tabComplete(User user, String alias, List args) { Island island = getIslands().getIsland(user.getUniqueId()); List options = island.getBanned().stream().map(getPlayers()::getName).collect(Collectors.toList()); - String lastArg = (!args.isEmpty() ? args.getLast() : ""); + String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; return Optional.of(Util.tabLimit(options, lastArg)); } } diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamInviteCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamInviteCommand.java index 47ebd26a5..f7fb9f1fb 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamInviteCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamInviteCommand.java @@ -1,7 +1,6 @@ package us.tastybento.bskyblock.commands.island.teams; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.Set; @@ -126,9 +125,9 @@ public class IslandTeamInviteCommand extends AbstractIslandTeamCommand { } @Override - public Optional> tabComplete(final User user, final String alias, final LinkedList args) { + public Optional> tabComplete(User user, String alias, List args) { List options = new ArrayList<>(); - String lastArg = (!args.isEmpty() ? args.getLast() : ""); + String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; if (args.isEmpty()) { // Don't show every player on the server. Require at least the first letter return Optional.empty(); diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamSetownerCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamSetownerCommand.java index 96ea8a3ce..fa30d2597 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamSetownerCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamSetownerCommand.java @@ -1,7 +1,6 @@ package us.tastybento.bskyblock.commands.island.teams; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -77,9 +76,9 @@ public class IslandTeamSetownerCommand extends AbstractIslandTeamCommand { @Override - public Optional> tabComplete(final User user, final String alias, final LinkedList args) { + public Optional> tabComplete(User user, String alias, List args) { List options = new ArrayList<>(); - String lastArg = (!args.isEmpty() ? args.getLast() : ""); + String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; for (UUID member : getPlugin().getIslands().getMembers(user.getUniqueId())) { options.add(getPlugin().getServer().getOfflinePlayer(member).getName()); } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEvents.java b/src/main/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEvents.java index e438165b3..9dc5018f0 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEvents.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEvents.java @@ -4,6 +4,7 @@ import java.util.Iterator; import java.util.Map.Entry; import java.util.WeakHashMap; +import org.bukkit.Bukkit; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; @@ -29,7 +30,7 @@ import us.tastybento.bskyblock.util.Util; * */ public class FlyingMobEvents implements Listener { - private final BSkyBlock plugin; + private BSkyBlock plugin; private WeakHashMap mobSpawnInfo; /** @@ -39,7 +40,7 @@ public class FlyingMobEvents implements Listener { this.plugin = plugin; mobSpawnInfo = new WeakHashMap<>(); - plugin.getServer().getScheduler().runTaskTimer(plugin, () -> { + Bukkit.getScheduler().runTaskTimer(plugin, () -> { Iterator> it = mobSpawnInfo.entrySet().iterator(); while (it.hasNext()) { Entry entry = it.next(); @@ -70,67 +71,65 @@ public class FlyingMobEvents implements Listener { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onMobSpawn(CreatureSpawnEvent e) { // Only cover withers in the island world - if (!Util.inWorld(e.getEntity())) { - return; - } - if (!e.getEntityType().equals(EntityType.WITHER) && !e.getEntityType().equals(EntityType.BLAZE) && !e.getEntityType().equals(EntityType.GHAST)) { + if (!Util.inWorld(e.getEntity()) || !(e.getEntityType().equals(EntityType.WITHER) + || e.getEntityType().equals(EntityType.BLAZE) + || e.getEntityType().equals(EntityType.GHAST))) { return; } // Store where this mob originated plugin.getIslands().getIslandAt(e.getLocation()).ifPresent(island->mobSpawnInfo.put(e.getEntity(),island)); } + /** + * Protects entities exploding. However, I am not sure if this will ever be called as pre-explosions should prevent it. + * @param e + * @return true if cancelled + */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onMobExplosion(EntityExplodeEvent e) { + public boolean onMobExplosion(EntityExplodeEvent e) { // Only cover in the island world if (e.getEntity() == null || !Util.inWorld(e.getEntity())) { - return; + return false; } - if (mobSpawnInfo.containsKey(e.getEntity())) { - // We know about this mob - if (!mobSpawnInfo.get(e.getEntity()).inIslandSpace(e.getLocation())) { - // Cancel the explosion and block damage - e.blockList().clear(); - e.setCancelled(true); - } + if (mobSpawnInfo.containsKey(e.getEntity()) && !mobSpawnInfo.get(e.getEntity()).inIslandSpace(e.getLocation())) { + // Cancel the explosion and block damage + e.blockList().clear(); + e.setCancelled(true); + return true; } + return false; } /** * Deal with pre-explosions */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onWitherExplode(ExplosionPrimeEvent e) { + public boolean onWitherExplode(ExplosionPrimeEvent e) { // Only cover withers in the island world if (!Util.inWorld(e.getEntity()) || e.getEntity() == null) { - return; + return false; } // The wither or wither skulls can both blow up - if (e.getEntityType() == EntityType.WITHER) { - // Check the location - if (mobSpawnInfo.containsKey(e.getEntity())) { - // We know about this wither - if (!mobSpawnInfo.get(e.getEntity()).inIslandSpace(e.getEntity().getLocation())) { - // Cancel the explosion - e.setCancelled(true); - } - } - } - if (e.getEntityType() == EntityType.WITHER_SKULL) { + if (e.getEntityType() == EntityType.WITHER + && mobSpawnInfo.containsKey(e.getEntity()) + && !mobSpawnInfo.get(e.getEntity()).inIslandSpace(e.getEntity().getLocation())) { + // Cancel the explosion + e.setCancelled(true); + return true; + } else if (e.getEntityType() == EntityType.WITHER_SKULL) { // Get shooter Projectile projectile = (Projectile)e.getEntity(); if (projectile.getShooter() instanceof Wither) { Wither wither = (Wither)projectile.getShooter(); // Check the location - if (mobSpawnInfo.containsKey(wither)) { - // We know about this wither - if (!mobSpawnInfo.get(wither).inIslandSpace(e.getEntity().getLocation())) { - // Cancel the explosion - e.setCancelled(true); - } + if (mobSpawnInfo.containsKey(wither) && !mobSpawnInfo.get(wither).inIslandSpace(e.getEntity().getLocation())) { + // Cancel the explosion + e.setCancelled(true); + return true; } } } + return false; } /** @@ -157,7 +156,7 @@ public class FlyingMobEvents implements Listener { * Clean up the hashmap. It's probably not needed, but just in case. */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onMobDeath(EntityDeathEvent e) { - mobSpawnInfo.remove(e.getEntity()); + public Island onMobDeath(EntityDeathEvent e) { + return mobSpawnInfo.remove(e.getEntity()); } } \ No newline at end of file diff --git a/src/test/java/bskyblock/TestBSkyBlock.java b/src/test/java/bskyblock/TestBSkyBlock.java index d51756b6a..0374bb1f8 100644 --- a/src/test/java/bskyblock/TestBSkyBlock.java +++ b/src/test/java/bskyblock/TestBSkyBlock.java @@ -15,7 +15,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; import java.util.Optional; @@ -342,9 +341,9 @@ public class TestBSkyBlock { } @Override - public Optional> tabComplete(final User user, final String alias, final LinkedList args) { + public Optional> tabComplete(User user, String alias, List args) { List options = new ArrayList<>(); - String lastArg = (!args.isEmpty() ? args.getLast() : ""); + String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; options.addAll(Arrays.asList("Florian", "Ben", "Bill", "Ted")); return Optional.of(Util.tabLimit(options, lastArg)); } diff --git a/src/test/java/us/tastybento/bskyblock/listeners/ObsidianToLavaTest.java b/src/test/java/us/tastybento/bskyblock/listeners/ObsidianToLavaTest.java index 3299ea78c..478c26bcd 100644 --- a/src/test/java/us/tastybento/bskyblock/listeners/ObsidianToLavaTest.java +++ b/src/test/java/us/tastybento/bskyblock/listeners/ObsidianToLavaTest.java @@ -24,7 +24,6 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.PluginManager; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; @@ -42,10 +41,6 @@ import us.tastybento.bskyblock.managers.LocalesManager; @PrepareForTest({PlayerEvent.class, PlayerInteractEvent.class}) public class ObsidianToLavaTest { - @BeforeClass - public static void setUpBeforeClass() throws Exception { - } - private static World world; @Test diff --git a/src/test/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEventsTest.java b/src/test/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEventsTest.java new file mode 100644 index 000000000..156182864 --- /dev/null +++ b/src/test/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEventsTest.java @@ -0,0 +1,394 @@ +/** + * + */ +package us.tastybento.bskyblock.listeners.protection; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.Wither; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.ExplosionPrimeEvent; +import org.bukkit.scheduler.BukkitScheduler; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +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 us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.Settings; +import us.tastybento.bskyblock.api.user.User; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.managers.IslandsManager; +import us.tastybento.bskyblock.managers.LocalesManager; +import us.tastybento.bskyblock.managers.PlayersManager; +import us.tastybento.bskyblock.util.Util; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, BSkyBlock.class, User.class, Util.class }) +public class FlyingMobEventsTest { + + private BSkyBlock plugin; + private UUID uuid; + private User user; + private Settings s; + private IslandsManager im; + private PlayersManager pm; + private UUID notUUID; + private BukkitScheduler sch; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + // Set up plugin + plugin = mock(BSkyBlock.class); + Whitebox.setInternalState(BSkyBlock.class, "instance", plugin); + + // Settings + s = mock(Settings.class); + when(plugin.getSettings()).thenReturn(s); + + // Player + Player p = mock(Player.class); + // Sometimes use Mockito.withSettings().verboseLogging() + user = mock(User.class); + when(user.isOp()).thenReturn(false); + uuid = UUID.randomUUID(); + notUUID = UUID.randomUUID(); + while(notUUID.equals(uuid)) { + notUUID = UUID.randomUUID(); + } + when(user.getUniqueId()).thenReturn(uuid); + when(user.getPlayer()).thenReturn(p); + when(user.getName()).thenReturn("tastybento"); + User.setPlugin(plugin); + + // Player has island to begin with + im = mock(IslandsManager.class); + when(im.hasIsland(Mockito.any())).thenReturn(true); + when(im.isOwner(Mockito.any())).thenReturn(true); + when(im.getTeamLeader(Mockito.any())).thenReturn(uuid); + when(plugin.getIslands()).thenReturn(im); + + when(plugin.getPlayers()).thenReturn(pm); + + // Server & Scheduler + sch = mock(BukkitScheduler.class); + PowerMockito.mockStatic(Bukkit.class); + when(Bukkit.getScheduler()).thenReturn(sch); + + // Locales + LocalesManager lm = mock(LocalesManager.class); + when(lm.get(Mockito.any(), Mockito.any())).thenReturn("mock translation"); + when(plugin.getLocalesManager()).thenReturn(lm); + + // Normally in world + Util.setPlugin(plugin); + PowerMockito.mockStatic(Util.class); + when(Util.inWorld(Mockito.any(Entity.class))).thenReturn(true); + when(Util.inWorld(Mockito.any(Block.class))).thenReturn(true); + when(Util.inWorld(Mockito.any(Location.class))).thenReturn(true); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.protection.FlyingMobEvents#FlyingMobEvents(us.tastybento.bskyblock.BSkyBlock)}. + */ + @Test + public void testFlyingMobEvents() { + FlyingMobEvents fme = new FlyingMobEvents(plugin); + assertNotNull(fme); + Mockito.verify(sch).runTaskTimer(Mockito.eq(plugin), Mockito.any(Runnable.class), Mockito.eq(20L), Mockito.eq(20L)); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.protection.FlyingMobEvents#onMobSpawn(org.bukkit.event.entity.CreatureSpawnEvent)}. + */ + @Test + public void testOnMobSpawnNotInWorld() { + FlyingMobEvents fme = new FlyingMobEvents(plugin); + LivingEntity le = mock(LivingEntity.class); + CreatureSpawnEvent e = new CreatureSpawnEvent(le, SpawnReason.BUILD_WITHER); + // Not in world + when(Util.inWorld(Mockito.any(Entity.class))).thenReturn(false); + fme.onMobSpawn(e); + Mockito.verify(im, Mockito.never()).getIslandAt(Mockito.any(Location.class)); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.protection.FlyingMobEvents#onMobSpawn(org.bukkit.event.entity.CreatureSpawnEvent)}. + */ + @Test + public void testOnMobSpawnInWorldWrongType() { + FlyingMobEvents fme = new FlyingMobEvents(plugin); + LivingEntity le = mock(LivingEntity.class); + when(le.getType()).thenReturn(EntityType.AREA_EFFECT_CLOUD); + CreatureSpawnEvent e = new CreatureSpawnEvent(le, SpawnReason.BUILD_WITHER); + fme.onMobSpawn(e); + Mockito.verify(im, Mockito.never()).getIslandAt(Mockito.any(Location.class)); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.protection.FlyingMobEvents#onMobSpawn(org.bukkit.event.entity.CreatureSpawnEvent)}. + */ + @Test + public void testOnMobSpawnInWorldCorrectType() { + FlyingMobEvents fme = new FlyingMobEvents(plugin); + LivingEntity le = mock(LivingEntity.class); + when(le.getLocation()).thenReturn(mock(Location.class)); + Optional oi = Optional.of(mock(Island.class)); + when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(oi); + // Wither + when(le.getType()).thenReturn(EntityType.WITHER); + CreatureSpawnEvent e = new CreatureSpawnEvent(le, SpawnReason.BUILD_WITHER); + fme.onMobSpawn(e); + Mockito.verify(im).getIslandAt(Mockito.any(Location.class)); + // Blaze + when(le.getType()).thenReturn(EntityType.BLAZE); + e = new CreatureSpawnEvent(le, SpawnReason.NATURAL); + fme.onMobSpawn(e); + Mockito.verify(im, Mockito.times(2)).getIslandAt(Mockito.any(Location.class)); + // Ghast + when(le.getType()).thenReturn(EntityType.GHAST); + e = new CreatureSpawnEvent(le, SpawnReason.NATURAL); + fme.onMobSpawn(e); + Mockito.verify(im, Mockito.times(3)).getIslandAt(Mockito.any(Location.class)); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.protection.FlyingMobEvents#onMobExplosion(org.bukkit.event.entity.EntityExplodeEvent)}. + */ + @Test + public void testOnMobExplosionFail() { + FlyingMobEvents fme = new FlyingMobEvents(plugin); + // Entity, Location, list of Blocks, yield + EntityExplodeEvent e = new EntityExplodeEvent(null, null, null, 0); + // null entity + assertFalse(fme.onMobExplosion(e)); + + // Not in world + Entity ent = mock(Entity.class); + when(Util.inWorld(Mockito.any(Entity.class))).thenReturn(false); + e = new EntityExplodeEvent(ent, null, null, 0); + assertFalse(fme.onMobExplosion(e)); + + // Unknown entity (not in the list) + when(Util.inWorld(Mockito.any(Entity.class))).thenReturn(true); + assertFalse(fme.onMobExplosion(e)); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.protection.FlyingMobEvents#onMobExplosion(org.bukkit.event.entity.EntityExplodeEvent)}. + */ + @Test + public void testOnMobExplosionOnIsland() { + FlyingMobEvents fme = new FlyingMobEvents(plugin); + // Spawn an entity + LivingEntity le = mock(LivingEntity.class); + when(le.getLocation()).thenReturn(mock(Location.class)); + Island island = mock(Island.class); + // Start with ghast exploding in island space + when(island.inIslandSpace(Mockito.any(Location.class))).thenReturn(true); + Optional oi = Optional.of(island); + when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(oi); + // Wither + when(le.getType()).thenReturn(EntityType.WITHER); + CreatureSpawnEvent cee = new CreatureSpawnEvent(le, SpawnReason.BUILD_WITHER); + fme.onMobSpawn(cee); + // Make the wither explode + // Entity, Location, list of Blocks, yield + Block block = mock(Block.class); + // One block will be blown up by the wither + List affectedBlocks = new ArrayList<>(); + affectedBlocks.add(block); + // Create event + EntityExplodeEvent e = new EntityExplodeEvent(le, mock(Location.class), affectedBlocks, 0); + // In world + when(Util.inWorld(Mockito.any(Entity.class))).thenReturn(true); + // Nothing blocked + assertFalse(fme.onMobExplosion(e)); + assertFalse(e.isCancelled()); + assertFalse(e.blockList().isEmpty()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.protection.FlyingMobEvents#onMobExplosion(org.bukkit.event.entity.EntityExplodeEvent)}. + */ + @Test + public void testOnMobExplosionOffIsland() { + FlyingMobEvents fme = new FlyingMobEvents(plugin); + // Spawn an entity + LivingEntity le = mock(LivingEntity.class); + when(le.getLocation()).thenReturn(mock(Location.class)); + Island island = mock(Island.class); + // Ghast exploding outside of island space + when(island.inIslandSpace(Mockito.any(Location.class))).thenReturn(false); + Optional oi = Optional.of(island); + when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(oi); + // Wither + when(le.getType()).thenReturn(EntityType.WITHER); + CreatureSpawnEvent cee = new CreatureSpawnEvent(le, SpawnReason.BUILD_WITHER); + fme.onMobSpawn(cee); + // Make the wither explode + // Entity, Location, list of Blocks, yield + Block block = mock(Block.class); + // One block will be blown up by the wither + List affectedBlocks = new ArrayList<>(); + affectedBlocks.add(block); + // Create event + EntityExplodeEvent e = new EntityExplodeEvent(le, mock(Location.class), affectedBlocks, 0); + // In world + when(Util.inWorld(Mockito.any(Entity.class))).thenReturn(true); + // Blocked + assertTrue(fme.onMobExplosion(e)); + assertTrue(e.isCancelled()); + assertTrue(e.blockList().isEmpty()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.protection.FlyingMobEvents#onWitherExplode(org.bukkit.event.entity.ExplosionPrimeEvent)}. + */ + @Test + public void testOnWitherExplode() { + FlyingMobEvents fme = new FlyingMobEvents(plugin); + // Spawn an entity + LivingEntity le = mock(LivingEntity.class); + when(le.getLocation()).thenReturn(mock(Location.class)); + Island island = mock(Island.class); + // Ghast exploding outside of island space + when(island.inIslandSpace(Mockito.any(Location.class))).thenReturn(false); + Optional oi = Optional.of(island); + when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(oi); + // Wither + when(le.getType()).thenReturn(EntityType.WITHER); + CreatureSpawnEvent cee = new CreatureSpawnEvent(le, SpawnReason.BUILD_WITHER); + fme.onMobSpawn(cee); + // Make the wither explode + // Create event + ExplosionPrimeEvent e = new ExplosionPrimeEvent(le, 0, false); + // In world + when(Util.inWorld(Mockito.any(Entity.class))).thenReturn(true); + // Blocked + assertTrue(fme.onWitherExplode(e)); + assertTrue(e.isCancelled()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.protection.FlyingMobEvents#onWitherExplode(org.bukkit.event.entity.ExplosionPrimeEvent)}. + */ + @Test + public void testOnWitherSkullExplode() { + FlyingMobEvents fme = new FlyingMobEvents(plugin); + // Spawn a wither + Wither wither = mock(Wither.class); + when(wither.getLocation()).thenReturn(mock(Location.class)); + Island island = mock(Island.class); + // Ghast exploding outside of island space + when(island.inIslandSpace(Mockito.any(Location.class))).thenReturn(false); + Optional oi = Optional.of(island); + when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(oi); + // Wither + when(wither.getType()).thenReturn(EntityType.WITHER); + CreatureSpawnEvent cee = new CreatureSpawnEvent(wither, SpawnReason.BUILD_WITHER); + fme.onMobSpawn(cee); + // Make the wither shoot a skull + Projectile skull = mock(Projectile.class); + when(skull.getType()).thenReturn(EntityType.WITHER_SKULL); + when(skull.getShooter()).thenReturn(wither); + + // Create event + ExplosionPrimeEvent e = new ExplosionPrimeEvent(skull, 0, false); + // In world + when(Util.inWorld(Mockito.any(Entity.class))).thenReturn(true); + // Blocked + assertTrue(fme.onWitherExplode(e)); + assertTrue(e.isCancelled()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.protection.FlyingMobEvents#onWitherChangeBlocks(org.bukkit.event.entity.EntityChangeBlockEvent)}. + */ + @Test + public void testOnWitherChangeBlocks() { + FlyingMobEvents fme = new FlyingMobEvents(plugin); + // Spawn a wither + Wither wither = mock(Wither.class); + when(wither.getLocation()).thenReturn(mock(Location.class)); + Island island = mock(Island.class); + // Ghast exploding outside of island space + when(island.inIslandSpace(Mockito.any(Location.class))).thenReturn(false); + Optional oi = Optional.of(island); + when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(oi); + // Wither + when(wither.getType()).thenReturn(EntityType.WITHER); + CreatureSpawnEvent cee = new CreatureSpawnEvent(wither, SpawnReason.BUILD_WITHER); + fme.onMobSpawn(cee); + // Create event + /** + * + * @param what the Entity causing the change + * @param block the block (before the change) + * @param to the future material being changed to + * @param data the future block data + * @deprecated Magic value + */ + @SuppressWarnings("deprecation") + EntityChangeBlockEvent e = new EntityChangeBlockEvent(wither, mock(Block.class), Material.AIR, (byte) 0); + // In world + when(Util.inWorld(Mockito.any(Entity.class))).thenReturn(true); + // Blocked + fme.onWitherChangeBlocks(e); + assertTrue(e.isCancelled()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.protection.FlyingMobEvents#onMobDeath(org.bukkit.event.entity.EntityDeathEvent)}. + */ + @Test + public void testOnMobDeath() { + FlyingMobEvents fme = new FlyingMobEvents(plugin); + // Spawn a wither + Wither wither = mock(Wither.class); + // Wither + when(wither.getType()).thenReturn(EntityType.WITHER); + CreatureSpawnEvent cee = new CreatureSpawnEvent(wither, SpawnReason.BUILD_WITHER); + Island island = mock(Island.class); + Optional oi = Optional.of(island); + when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(oi); + fme.onMobSpawn(cee); + // Kill it + EntityDeathEvent e = new EntityDeathEvent(wither, null); + assertNotNull(fme.onMobDeath(e)); + } + +}