diff --git a/src/main/java/world/bentobox/bentobox/listeners/PlayerEntityPortalEvent.java b/src/main/java/world/bentobox/bentobox/listeners/PlayerEntityPortalEvent.java deleted file mode 100644 index f58960133..000000000 --- a/src/main/java/world/bentobox/bentobox/listeners/PlayerEntityPortalEvent.java +++ /dev/null @@ -1,163 +0,0 @@ -package world.bentobox.bentobox.listeners; - -import java.util.Objects; -import java.util.Optional; - -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.entity.Entity; -import org.bukkit.event.entity.EntityPortalEvent; -import org.bukkit.event.player.PlayerPortalEvent; -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; - -import world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.database.objects.Island; - -/** - * Abstracts PlayerPortalEvent and EntityPortalEvent - * @author tastybento - * @deprecated replaced not used in new listeners. - * @since 1.12.1 - */ -@Deprecated(since="1.21.0", forRemoval=true) -public class PlayerEntityPortalEvent { - - private final EntityPortalEvent epe; - private final PlayerPortalEvent ppe; - - /** - * Create a hybrid PlayerEntityPortalEvent - * @param epe - EntityPortalEvent - */ - public PlayerEntityPortalEvent(EntityPortalEvent epe) { - this.ppe = null; - this.epe = epe; - } - - /** - * Create a hybrid PlayerEntityPortalEvent - * @param ppe - PlayerPortalEvent - */ - public PlayerEntityPortalEvent(PlayerPortalEvent ppe) { - this.ppe = ppe; - this.epe = null; - } - - /** - * Returns whether the server will attempt to create a destination portal or not. - * Only applicable to {@link PlayerPortalEvent} - * @return whether there should create be a destination portal created - */ - public boolean getCanCreatePortal() { - return epe == null && ppe.getCanCreatePortal(); - } - - /** - * Returns the entity involved in this event - * @return Entity who is involved in this event - */ - @NonNull - public Entity getEntity() { - return epe == null ? ppe.getPlayer() : epe.getEntity(); - } - - /** - * Gets the location this player moved from - * @return Location the player or entity moved from - */ - @NonNull - public Location getFrom() { - return epe == null ? ppe.getFrom() : epe.getFrom(); - } - - /** - * Gets the location this player moved to - * @return Location the player moved to - */ - @Nullable - public Location getTo() { - return epe == null ? ppe.getTo() : epe.getTo(); - } - - /** - * @return true if constructed with an {@link EntityPortalEvent} - */ - public boolean isEntityPortalEvent() { - return epe != null; - } - - /** - * @return true if constructed with an {@link PlayerPortalEvent} - */ - public boolean isPlayerPortalEvent() { - return ppe != null; - } - - /** - * Sets the cancellation state of this event. A cancelled event will not be executed in the server, but will still pass to other plugins - * If a move or teleport event is cancelled, the player will be moved or teleported back to the Location as defined by getFrom(). This will not fire an event - * Specified by: setCancelled(...) in Cancellable - * @param cancel true if you wish to cancel this event - */ - public void setCancelled(boolean cancel) { - if (epe == null) { - ppe.setCancelled(cancel); - } else { - epe.setCancelled(cancel); - } - } - - /** - * Sets whether the server should attempt to create a destination portal or not. - * Only applicable to {@link PlayerPortalEvent} - * @param canCreatePortal Sets whether there should be a destination portal created - */ - public void setCanCreatePortal(boolean canCreatePortal) { - if (ppe != null) { - ppe.setCanCreatePortal(canCreatePortal); - } - - } - - /** - * Set the Block radius to search in for available portals. - * @param searchRadius the radius in which to search for a portal from the location - */ - public void setSearchRadius(int searchRadius) { - if (epe == null) { - ppe.setSearchRadius(searchRadius); - } else { - epe.setSearchRadius(searchRadius); - } - } - - /** - * Sets the location that this player will move to - * @param to New Location this player or entity will move to - */ - public void setTo(Location to) { - if (epe == null) { - ppe.setTo(to); - } else { - epe.setTo(to); - } - } - - /** - * Get island at the from location - * @return optional island at from location - */ - public Optional getIsland() { - return BentoBox.getInstance().getIslands().getProtectedIslandAt(getFrom()); - } - - /** - * Get the from world - * @return from world - */ - @NonNull - public World getWorld() { - return Objects.requireNonNull(getFrom().getWorld(), "From world is null!"); - } -} diff --git a/src/main/java/world/bentobox/bentobox/listeners/PortalTeleportationListener.java b/src/main/java/world/bentobox/bentobox/listeners/PortalTeleportationListener.java deleted file mode 100644 index a275d0d01..000000000 --- a/src/main/java/world/bentobox/bentobox/listeners/PortalTeleportationListener.java +++ /dev/null @@ -1,489 +0,0 @@ -package world.bentobox.bentobox.listeners; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.World.Environment; -import org.bukkit.block.BlockFace; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityPortalEnterEvent; -import org.bukkit.event.entity.EntityPortalEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerPortalEvent; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.util.Vector; -import org.eclipse.jdt.annotation.NonNull; - -import world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.api.addons.GameModeAddon; -import world.bentobox.bentobox.blueprints.Blueprint; -import world.bentobox.bentobox.blueprints.BlueprintPaster; -import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle; -import world.bentobox.bentobox.database.objects.Island; -import world.bentobox.bentobox.util.Util; -import world.bentobox.bentobox.util.teleport.SafeSpotTeleport; - -/** - * Handles teleportation via the Nether/End portals to the Nether and End dimensions of the worlds added by the GameModeAddons. - * - * @author tastybento - * @deprecated replaced by better listeners. - * @see world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener - * @see world.bentobox.bentobox.listeners.teleports.EntityTeleportListener - * @since 1.12.1 - */ -@Deprecated(since="1.21.0", forRemoval=true) -public class PortalTeleportationListener implements Listener { - - private final BentoBox plugin; - private final Set inPortal; - private final Set inTeleport; - - public PortalTeleportationListener(@NonNull BentoBox plugin) { - this.plugin = plugin; - inPortal = new HashSet<>(); - inTeleport = new HashSet<>(); - } - - /** - * Fires the event if nether or end is disabled at the system level - * @param e - EntityPortalEnterEvent - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onPlayerPortal(EntityPortalEnterEvent e) { - if (!(e.getEntity() instanceof Player)) { - return; - } - Entity entity = e.getEntity(); - Material type = e.getLocation().getBlock().getType(); - UUID uuid = entity.getUniqueId(); - if (inPortal.contains(uuid) || !plugin.getIWM().inWorld(Util.getWorld(e.getLocation().getWorld()))) { - return; - } - inPortal.add(uuid); - if (!Bukkit.getAllowNether() && type.equals(Material.NETHER_PORTAL)) { - // Schedule a time - Bukkit.getScheduler().runTaskLater(plugin, () -> { - // Check again if still in portal - if (inPortal.contains(uuid)) { - this.onIslandPortal(new PlayerPortalEvent((Player)entity, e.getLocation(), null, TeleportCause.NETHER_PORTAL, 0, false, 0)); - } - }, 40); - return; - } - // End portals are instant transfer - if (!Bukkit.getAllowEnd() && (type.equals(Material.END_PORTAL) || type.equals(Material.END_GATEWAY))) { - PlayerPortalEvent en = new PlayerPortalEvent((Player)entity, - e.getLocation(), - null, - type.equals(Material.END_PORTAL) ? TeleportCause.END_PORTAL : TeleportCause.END_GATEWAY, - 0, - false, - 0); - this.onIslandPortal(en); - } - } - - /** - * Handles non-player portal use. - * - * @param e - event - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onEntityPortal(EntityPortalEvent e) { - if (plugin.getIWM().inWorld(e.getFrom())) { - Optional mat = Arrays.stream(BlockFace.values()) - .map(bf -> e.getFrom().getBlock().getRelative(bf).getType()) - .filter(m -> m.equals(Material.NETHER_PORTAL) - || m.equals(Material.END_PORTAL) - || m.equals(Material.END_GATEWAY)) - .findFirst(); - if (mat.isEmpty()) { - e.setCancelled(true); - } else if (mat.get().equals(Material.NETHER_PORTAL)){ - processPortal(new PlayerEntityPortalEvent(e), Environment.NETHER); - } else { - processPortal(new PlayerEntityPortalEvent(e), Environment.THE_END); - } - } - } - - /** - * Remove inPortal flag only when player exits the portal - * @param e player move event - */ - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onExitPortal(PlayerMoveEvent e) { - if (!inPortal.contains(e.getPlayer().getUniqueId())) { - return; - } - if (e.getTo() != null && !e.getTo().getBlock().getType().equals(Material.NETHER_PORTAL)) { - inPortal.remove(e.getPlayer().getUniqueId()); - inTeleport.remove(e.getPlayer().getUniqueId()); - } - } - - /** - * Handles nether or end portals - * @param e - event - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onIslandPortal(PlayerPortalEvent e) { - switch (e.getCause()) { - case END_GATEWAY, END_PORTAL -> processPortal(new PlayerEntityPortalEvent(e), Environment.THE_END); - case NETHER_PORTAL -> processPortal(new PlayerEntityPortalEvent(e), Environment.NETHER); - default -> { - // Do nothing - } - - } - - } - - /** - * Process the portal action - * @param e - event - * @param env - environment that this relates to - NETHER or THE_END - * @return true if portal happens, false if not - */ - private boolean processPortal(final PlayerEntityPortalEvent e, final Environment env) { - World fromWorld = e.getFrom().getWorld(); - World overWorld = Util.getWorld(fromWorld); - if (overWorld == null || fromWorld == null || !plugin.getIWM().inWorld(overWorld)) { - // Do nothing special - return false; - } - - if (!isGenerate(overWorld, env)) { - e.setCancelled(true); - return false; - } - - if (!Bukkit.getAllowNether()) { - e.setCancelled(true); - } - - if (inTeleport.contains(e.getEntity().getUniqueId())) { - return false; - } - inTeleport.add(e.getEntity().getUniqueId()); - - // STANDARD NETHER OR END - if (!isIslands(overWorld, env)) { - handleStandardNetherOrEnd(e, fromWorld, overWorld, env); - return true; - } - // FROM NETHER OR END - // If entering a portal in the other world, teleport to a portal in overworld if there is one - if (fromWorld.getEnvironment().equals(env)) { - handleFromNetherOrEnd(e, overWorld, env); - return true; - } - // TO NETHER OR END - World toWorld = getNetherEndWorld(overWorld, env); - // Set whether portals should be created or not - e.setCanCreatePortal(plugin.getIWM().getAddon(overWorld).map(gm -> isMakePortals(gm, env)).orElse(false)); - // Set the destination location - // If portals cannot be created, then destination is the spawn point, otherwise it's the vector - e.setTo(getTo(e, env, toWorld)); - - // Find the distance from edge of island's protection and set the search radius - e.getIsland().ifPresent(i -> setSeachRadius(e, i)); - - // Check if there is an island there or not - if (e.getEntity().getType().equals(EntityType.PLAYER) - && plugin.getIWM().isPasteMissingIslands(overWorld) - && !plugin.getIWM().isUseOwnGenerator(overWorld) - && isGenerate(overWorld, env) - && isIslands(overWorld, env) - && getNetherEndWorld(overWorld, env) != null - && e.getIsland().filter(i -> !hasPartnerIsland(i, env)).map(i -> { - // No nether island present so paste the default one - e.setCancelled(true); - pasteNewIsland((Player)e.getEntity(), e.getTo(), i, env); - return true; - }).orElse(false)) { - // All done here - return true; - } - if (e.getCanCreatePortal()) { - // Let the server teleport - return true; - } - if (env.equals(Environment.THE_END)) { - // Prevent death from hitting the ground - e.getEntity().setVelocity(new Vector(0,0,0)); - e.getEntity().setFallDistance(0); - } - - // If we do not generate portals, teleportation should happen manually with safe spot builder. - // Otherwise, we could end up with situations when player is placed in mid air, if teleportation - // is done instantly. - // Our safe spot task is triggered in next tick, however, end teleportation happens in the same tick. - // It is placed outside THE_END check, as technically it could happen with the nether portal too. - e.setCancelled(true); - - // If there is a portal to go to already, then the player will go there - Bukkit.getScheduler().runTask(plugin, () -> { - if (!e.getEntity().getWorld().equals(toWorld)) { - // Else manually teleport entity - new SafeSpotTeleport.Builder(plugin) - .entity(e.getEntity()) - .location(e.getTo()) - .portal() - .thenRun(() -> { - e.getEntity().setVelocity(new Vector(0,0,0)); - e.getEntity().setFallDistance(0); - }) - .build(); - } - }); - return true; - } - - - /** - * Set the destination of this portal action - * @param e - event - * @param env - environment - * @param toWorld - to world - */ - Location getTo(PlayerEntityPortalEvent e, Environment env, World toWorld) - { - // Null check - not that useful - if (e.getFrom().getWorld() == null || toWorld == null) - { - return null; - } - - Location toLocation = Objects.requireNonNullElse(e.getIsland().map(island -> island.getSpawnPoint(env)). - orElse(e.getFrom().toVector().toLocation(toWorld)), e.getFrom().toVector().toLocation(toWorld)); - // Limit Y to the min/max world height. - toLocation.setY(Math.max(Math.min(toLocation.getY(), toWorld.getMaxHeight()), toWorld.getMinHeight())); - - if (!e.getCanCreatePortal()) - { - // Legacy portaling - return toLocation; - } - // Make portals - // For anywhere other than the end - it is the player's location that is used - if (!env.equals(Environment.THE_END)) - { - return toLocation; - } - // If the-end then we want the platform to always be generated in the same place no matter where - // they enter the portal - final int x = e.getFrom().getBlockX(); - final int z = e.getFrom().getBlockZ(); - final int y = e.getFrom().getBlockY(); - int i = x; - int j = z; - int k = y; - // If the from is not a portal, then we have to find it - if (!e.getFrom().getBlock().getType().equals(Material.END_PORTAL)) - { - // Find the portal - due to speed, it is possible that the player will be below or above the portal - for (k = toWorld.getMinHeight(); (k < e.getWorld().getMaxHeight()) && - !e.getWorld().getBlockAt(x, k, z).getType().equals(Material.END_PORTAL); k++); - } - // Find the maximum x and z corner - for (; (i < x + 5) && e.getWorld().getBlockAt(i, k, z).getType().equals(Material.END_PORTAL); i++) ; - for (; (j < z + 5) && e.getWorld().getBlockAt(x, k, j).getType().equals(Material.END_PORTAL); j++) ; - - // Mojang end platform generation is: - // AIR - // AIR - // OBSIDIAN - // and player is placed on second air block above obsidian. - // If Y coordinate is below 2, then obsidian platform is not generated and player falls in void. - return new Location(toWorld, i, Math.max(toWorld.getMinHeight() + 2, k), j); - } - - - /** - * Check if vanilla portals should be used - * @param gm - game mode - * @param env - environment - * @return true or false - */ - private boolean isMakePortals(GameModeAddon gm, Environment env) { - return env.equals(Environment.NETHER) ? - gm.getWorldSettings().isMakeNetherPortals() && Bukkit.getAllowNether() : - gm.getWorldSettings().isMakeEndPortals() && Bukkit.getAllowEnd(); - } - - /** - * Check if nether or end are generated - * @param overWorld - game world - * @param env - environment - * @return true or false - */ - private boolean isGenerate(World overWorld, Environment env) { - return env.equals(Environment.NETHER) ? plugin.getIWM().isNetherGenerate(overWorld) : plugin.getIWM().isEndGenerate(overWorld); - } - - /** - * Check if nether or end islands are generated - * @param overWorld - over world - * @param env - environment - * @return true or false - */ - private boolean isIslands(World overWorld, Environment env) { - return env.equals(Environment.NETHER) ? plugin.getIWM().isNetherIslands(overWorld) : plugin.getIWM().isEndIslands(overWorld); - } - - /** - * Get the nether or end world - * @param overWorld - over world - * @param env - environment - * @return nether or end world - */ - private World getNetherEndWorld(World overWorld, Environment env) { - return env.equals(Environment.NETHER) ? plugin.getIWM().getNetherWorld(overWorld) : plugin.getIWM().getEndWorld(overWorld); - } - - /** - * Check if the island has a nether or end island already - * @param i - island - * @param env - environment - * @return true or false - */ - private boolean hasPartnerIsland(Island i, Environment env) { - return env.equals(Environment.NETHER) ? i.hasNetherIsland() : i.hasEndIsland(); - } - - /** - * Check if the default nether or end are allowed by the server settings - * @param env - environment - * @return true or false - */ - private boolean isAllowedOnServer(Environment env) { - return env.equals(Environment.NETHER) ? Bukkit.getAllowNether() : Bukkit.getAllowEnd(); - } - - /** - * Handle teleport from nether or end to overworld - * @param e - event - * @param overWorld - over world - * @param env - environment - */ - private void handleFromNetherOrEnd(PlayerEntityPortalEvent e, World overWorld, Environment env) { - // Standard portals - if (plugin.getIWM().getAddon(overWorld).map(gm -> isMakePortals(gm, env)).orElse(false)) { - e.setTo(e.getFrom().toVector().toLocation(overWorld)); - // Find distance from edge of island's protection - plugin.getIslands().getIslandAt(e.getFrom()).ifPresent(i -> setSeachRadius(e, i)); - return; - } - // Custom portals - e.setCancelled(true); - // If this is from the island nether or end, then go to the same vector, otherwise try island home location - Location to = plugin.getIslands().getIslandAt(e.getFrom()).map(i -> i.getSpawnPoint(Environment.NORMAL)).orElse(e.getFrom().toVector().toLocation(overWorld)); - e.setTo(to); - // Else other worlds teleport to the nether - new SafeSpotTeleport.Builder(plugin) - .entity(e.getEntity()) - .location(to) - .portal() - .build(); - - } - - - /** - * Handle teleport from or to standard nether or end - * @param e - PlayerEntityPortalEvent - * @param fromWorld - from world - * @param overWorld - over world - * @param env - environment involved - */ - private void handleStandardNetherOrEnd(PlayerEntityPortalEvent e, World fromWorld, World overWorld, Environment env) { - if (fromWorld.getEnvironment() != env) { - World toWorld = Objects.requireNonNull(getNetherEndWorld(overWorld, env)); - Location spawnPoint = toWorld.getSpawnLocation(); - // If going to the nether and nether portals are active then just teleport to approx location - if (env.equals(Environment.NETHER) && plugin.getIWM().getWorldSettings(overWorld).isMakeNetherPortals()) { - spawnPoint = e.getFrom().toVector().toLocation(toWorld); - } - // If spawn is set as 0,63,0 in the End then move it to 100, 50 ,0. - if (env.equals(Environment.THE_END) && spawnPoint.getBlockX() == 0 && spawnPoint.getBlockZ() == 0) { - // Set to the default end spawn - spawnPoint = new Location(toWorld, 100, 50, 0); - toWorld.setSpawnLocation(100, 50, 0); - } - if (isAllowedOnServer(env)) { - // To Standard Nether or end - e.setTo(spawnPoint); - } else { - // Teleport to standard nether or end - new SafeSpotTeleport.Builder(plugin) - .entity(e.getEntity()) - .location(spawnPoint) - .portal() - .build(); - } - } - // From standard nether or end - else if (e.getEntity() instanceof Player player){ - e.setCancelled(true); - plugin.getIslands().homeTeleportAsync(overWorld, player); - } - - } - - - void setSeachRadius(PlayerEntityPortalEvent e, Island i) { - if (!i.onIsland(e.getFrom())) return; - // Find max x or max z - int x = Math.abs(i.getProtectionCenter().getBlockX() - e.getFrom().getBlockX()); - int z = Math.abs(i.getProtectionCenter().getBlockZ() - e.getFrom().getBlockZ()); - int diff = Math.max(plugin.getSettings().getMinPortalSearchRadius(), i.getProtectionRange() - Math.max(x, z)); - if (diff > 0 && diff < 128) { - e.setSearchRadius(diff); - } - } - - - /** - * Pastes the default nether or end island and teleports the player to the island's spawn point - * @param player - player to teleport after pasting - * @param to - the fallback location if a spawn point is not part of the blueprint - * @param island - the island - * @param env - NETHER or THE_END - */ - private void pasteNewIsland(Player player, Location to, Island island, Environment env) { - // Paste then teleport player - plugin.getIWM().getAddon(island.getWorld()).ifPresent(addon -> { - // Get the default bundle's nether or end blueprint - BlueprintBundle bb = plugin.getBlueprintsManager().getDefaultBlueprintBundle(addon); - if (bb != null) { - Blueprint bp = plugin.getBlueprintsManager().getBlueprints(addon).get(bb.getBlueprint(env)); - if (bp != null) { - new BlueprintPaster(plugin, bp, - to.getWorld(), - island).paste().thenAccept(b -> new SafeSpotTeleport.Builder(plugin) - .entity(player) - .location(island.getSpawnPoint(env) == null ? to : island.getSpawnPoint(env)) - // No need to use portal because there will be no portal on the other end - .build()); - } else { - plugin.logError("Could not paste default island in nether or end. Is there a nether-island or end-island blueprint?"); - } - } - }); - } -} diff --git a/src/main/java/world/bentobox/bentobox/listeners/teleports/AbstractTeleportListener.java b/src/main/java/world/bentobox/bentobox/listeners/teleports/AbstractTeleportListener.java index a450c55a0..36f8ef266 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/teleports/AbstractTeleportListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/teleports/AbstractTeleportListener.java @@ -311,7 +311,7 @@ public abstract class AbstractTeleportListener /** - * This method returns if missing islands should be generated uppon teleportation. + * This method returns if missing islands should be generated upon teleportation. * Can happen only in non-custom generators. * @param overWorld OverWorld * @return {@code true} if missing islands must be pasted, {@code false} otherwise. diff --git a/src/test/java/world/bentobox/bentobox/listeners/PortalTeleportationListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/PortalTeleportationListenerTest.java deleted file mode 100644 index 3bf11f288..000000000 --- a/src/test/java/world/bentobox/bentobox/listeners/PortalTeleportationListenerTest.java +++ /dev/null @@ -1,622 +0,0 @@ -package world.bentobox.bentobox.listeners; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -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.Collections; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Server; -import org.bukkit.World; -import org.bukkit.World.Environment; -import org.bukkit.block.Block; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.event.entity.EntityPortalEvent; -import org.bukkit.event.player.PlayerPortalEvent; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.scheduler.BukkitScheduler; -import org.bukkit.util.Vector; -import org.eclipse.jdt.annotation.Nullable; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -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 world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.Settings; -import world.bentobox.bentobox.api.addons.GameModeAddon; -import world.bentobox.bentobox.api.configuration.WorldSettings; -import world.bentobox.bentobox.api.user.User; -import world.bentobox.bentobox.blueprints.Blueprint; -import world.bentobox.bentobox.blueprints.BlueprintPaster; -import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle; -import world.bentobox.bentobox.database.objects.Island; -import world.bentobox.bentobox.managers.BlueprintsManager; -import world.bentobox.bentobox.managers.IslandWorldManager; -import world.bentobox.bentobox.managers.IslandsManager; -import world.bentobox.bentobox.managers.LocalesManager; -import world.bentobox.bentobox.managers.PlayersManager; -import world.bentobox.bentobox.util.Util; - -/** - * @author tastybento - * - */ -@RunWith(PowerMockRunner.class) -@PrepareForTest({Bukkit.class, BentoBox.class, User.class, Util.class, BlueprintPaster.class }) -public class PortalTeleportationListenerTest { - - @Mock - private BentoBox plugin; - @Mock - private IslandsManager im; - private PlayersManager pm; - @Mock - private IslandWorldManager iwm; - @Mock - private World world; - @Mock - private World nether; - @Mock - private World end; - @Mock - private Player p; - @Mock - private BlueprintsManager bpm; - @Mock - private GameModeAddon gameModeAddon; - @Mock - private WorldSettings ws; - @Mock - private Player player; - - @Before - public void setUp() throws Exception { - // Set up plugin - Whitebox.setInternalState(BentoBox.class, "instance", plugin); - - // island world mgr - when(world.getEnvironment()).thenReturn(Environment.NORMAL); - when(nether.getEnvironment()).thenReturn(Environment.NETHER); - when(end.getEnvironment()).thenReturn(Environment.THE_END); - Location endSpawn = mock(Location.class); - when(endSpawn.getWorld()).thenReturn(end); - when(end.getSpawnLocation()).thenReturn(endSpawn); - when(iwm.getEndWorld(any())).thenReturn(end); - when(iwm.isEndGenerate(any())).thenReturn(true); - when(iwm.getIslandWorld(any())).thenReturn(world); - when(iwm.getNetherWorld(any())).thenReturn(nether); - when(iwm.isNetherGenerate(any())).thenReturn(true); - when(iwm.inWorld(any(World.class))).thenReturn(true); - when(iwm.inWorld(any(Location.class))).thenReturn(true); - when(iwm.getNetherSpawnRadius(any())).thenReturn(100); - when(iwm.getWorldSettings(any())).thenReturn(ws); - when(plugin.getIWM()).thenReturn(iwm); - - PowerMockito.mockStatic(Util.class, Mockito.RETURNS_MOCKS); - when(Util.getWorld(any())).thenReturn(world); - - // Settings - Settings s = mock(Settings.class); - when(plugin.getSettings()).thenReturn(s); - - // Set up nether spawn - Location netherSpawn = mock(Location.class); - when(netherSpawn.toVector()).thenReturn(new Vector(0,0,0)); - when(netherSpawn.getWorld()).thenReturn(nether); - when(nether.getSpawnLocation()).thenReturn(netherSpawn); - - // Player - // Sometimes use Mockito.withSettings().verboseLogging() - User user = mock(User.class); - when(user.isOp()).thenReturn(false); - UUID uuid = UUID.randomUUID(); - UUID 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 - when(im.hasIsland(any(), any(UUID.class))).thenReturn(true); - when(im.isOwner(any(), any())).thenReturn(true); - when(im.getOwner(any(), any())).thenReturn(uuid); - Optional optionalIsland = Optional.empty(); - when(im.getIslandAt(any())).thenReturn(optionalIsland); - when(im.homeTeleportAsync(any(), any())).thenReturn(CompletableFuture.completedFuture(true)); - when(plugin.getIslands()).thenReturn(im); - - when(plugin.getPlayers()).thenReturn(pm); - - // Server & Scheduler - BukkitScheduler sch = mock(BukkitScheduler.class); - PowerMockito.mockStatic(Bukkit.class); - when(Bukkit.getScheduler()).thenReturn(sch); - Server server = mock(Server.class); - when(server.getAllowNether()).thenReturn(true); - when(Bukkit.getServer()).thenReturn(server); - - // Locales - LocalesManager lm = mock(LocalesManager.class); - when(lm.get(any(), any())).thenReturn("mock translation"); - when(plugin.getLocalesManager()).thenReturn(lm); - - // Normally in world - Util.setPlugin(plugin); - - // Addon - Optional opAddon = Optional.of(gameModeAddon); - when(iwm.getAddon(any())).thenReturn(opAddon); - - // Blueprints - when(plugin.getBlueprintsManager()).thenReturn(bpm); - @Nullable - BlueprintBundle defaultBB = new BlueprintBundle(); - Blueprint bp = new Blueprint(); - bp.setName("blueprintname"); - defaultBB.setBlueprint(World.Environment.NETHER, bp); - defaultBB.setBlueprint(World.Environment.THE_END, bp); - when(bpm.getDefaultBlueprintBundle(any())).thenReturn(defaultBB); - when(bpm.getBlueprints(any())).thenReturn(Collections.singletonMap("blueprintname", bp)); - // World Settings - when(gameModeAddon.getWorldSettings()).thenReturn(ws); - - // Player - when(player.getType()).thenReturn(EntityType.PLAYER); - - // Bukkit - when(Bukkit.getAllowNether()).thenReturn(true); - when(Bukkit.getAllowEnd()).thenReturn(true); - } - - @After - public void tearDown() { - User.clearUsers(); - Mockito.framework().clearInlineMocks(); - } - - private void wrongWorld() { - when(iwm.inWorld(any(World.class))).thenReturn(false); - when(iwm.inWorld(any(Location.class))).thenReturn(false); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalNotEnd() { - Location from = mock(Location.class); - // Teleport from world to nether - when(from.getWorld()).thenReturn(world); - when(from.toVector()).thenReturn(new Vector(1,2,3)); - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - // Wrong cause - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.CHORUS_FRUIT); - np.onIslandPortal(e); - assertFalse(e.isCancelled()); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalNoEndWorldGenerated() { - Location from = mock(Location.class); - // Teleport from world to end - when(from.getWorld()).thenReturn(world); - when(from.toVector()).thenReturn(new Vector(1,2,3)); - // No end world - when(iwm.isEndGenerate(any())).thenReturn(false); - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.END_PORTAL); - np.onIslandPortal(e); - assertTrue(e.isCancelled()); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalWrongWorld() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location loc = mock(Location.class); - - // Right cause, end exists, wrong world - when(loc.getWorld()).thenReturn(mock(World.class)); - wrongWorld(); - PlayerPortalEvent e = new PlayerPortalEvent(player, loc, null, TeleportCause.END_PORTAL); - when(iwm.isEndGenerate(world)).thenReturn(true); - np.onIslandPortal(e); - assertFalse(e.isCancelled()); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalNullWorld() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location loc = mock(Location.class); - when(loc.getWorld()).thenReturn(null); - PlayerPortalEvent e = new PlayerPortalEvent(player, loc, null, TeleportCause.END_PORTAL); - np.onIslandPortal(e); - assertFalse(e.isCancelled()); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalHome() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - // Teleport from end - when(from.getWorld()).thenReturn(end); - - // Player has no island - Player player = mock(Player.class); - when(player.getUniqueId()).thenReturn(UUID.randomUUID()); - when(im.hasIsland(any(), any(UUID.class))).thenReturn(false); - // Right cause, end exists, right world - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.END_PORTAL); - when(iwm.isEndGenerate(world)).thenReturn(true); - // No island for player - when(im.hasIsland(any(), any(UUID.class))).thenReturn(false); - np.onIslandPortal(e); - assertTrue(e.isCancelled()); - // Give player an island - when(im.hasIsland(any(), any(UUID.class))).thenReturn(true); - np.onIslandPortal(e); - assertTrue(e.isCancelled()); - verify(im).homeTeleportAsync(any(), eq(player)); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalNonBentoBoxWorld() { - when(iwm.inWorld(any(World.class))).thenReturn(false); - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - // Teleport from nether to world - when(from.getWorld()).thenReturn(mock(World.class)); - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.NETHER_PORTAL); - np.onIslandPortal(e); - // Verify - assertFalse(e.isCancelled()); - verify(iwm, never()).isEndGenerate(any()); - } - - /** - * Test method for {@link PortalTeleportationListener#onEntityPortal(org.bukkit.event.entity.EntityPortalEvent)}. - */ - @Test - public void testOnEntityPortal() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Entity ent = mock(Entity.class); - when(ent.getType()).thenReturn(EntityType.VILLAGER); - when(ent.getWorld()).thenReturn(world); - Location from = mock(Location.class); - when(from.getWorld()).thenReturn(world); - Block block = mock(Block.class); - when(from.getBlock()).thenReturn(block); - when(block.getRelative(any())).thenReturn(block); - when(block.getType()).thenReturn(Material.NETHER_PORTAL); - // Not in world - wrongWorld(); - EntityPortalEvent e = new EntityPortalEvent(ent, from, null); - np.onEntityPortal(e); - assertFalse(e.isCancelled()); - // In world - when(iwm.inWorld(any(World.class))).thenReturn(true); - when(iwm.inWorld(any(Location.class))).thenReturn(true); - e = new EntityPortalEvent(ent, from, null); - np.onEntityPortal(e); - assertFalse(e.isCancelled()); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalNotPortal() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - PlayerPortalEvent e = new PlayerPortalEvent(player, null, null, TeleportCause.COMMAND); - np.onIslandPortal(e); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalWrongWorldNether() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - when(from.getWorld()).thenReturn(mock(World.class)); - wrongWorld(); - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.NETHER_PORTAL); - np.onIslandPortal(e); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalFromWorldToNetherIsland() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - // Teleport from world to nether - when(from.getWorld()).thenReturn(world); - when(from.toVector()).thenReturn(new Vector(1,2,3)); - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.NETHER_PORTAL); - // Nether islands active - when(iwm.isNetherIslands(any())).thenReturn(true); - when(iwm.isNetherGenerate(any())).thenReturn(true); - np.onIslandPortal(e); - // Event is canceled - assertTrue(e.isCancelled()); - // If nether islands, then to = from but in nether - verify(from, times(2)).toVector(); - // Do not go to spawn - verify(nether, never()).getSpawnLocation(); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalFromWorldToNetherIslandWithSpawnDefined() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - Location to = mock(Location.class); - when(to.getWorld()).thenReturn(world); - // Teleport from world to nether - when(from.getWorld()).thenReturn(world); - when(from.toVector()).thenReturn(new Vector(1,2,3)); - PlayerPortalEvent e = new PlayerPortalEvent(player, from, to, TeleportCause.NETHER_PORTAL); - // Nether islands active - when(iwm.isNetherIslands(any())).thenReturn(true); - when(iwm.isNetherGenerate(any())).thenReturn(true); - when(iwm.getNetherWorld(any())).thenReturn(nether); - - Island island = mock(Island.class); - Location spawnLoc = mock(Location.class); - when(spawnLoc.getWorld()).thenReturn(world); - when(island.getSpawnPoint(any())).thenReturn(spawnLoc); - Optional optionalIsland = Optional.of(island); - // Island exists at location - when(im.getIslandAt(any())).thenReturn(optionalIsland); - - - np.onIslandPortal(e); - // Verify - assertTrue(e.isCancelled()); - // If nether islands, then to = from but in nether - verify(from, times(2)).toVector(); - // Do not go to spawn - verify(nether, never()).getSpawnLocation(); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalFromWorldToNetherIslandWithNoSpawnDefined() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - // Teleport from world to nether - when(from.getWorld()).thenReturn(world); - when(from.toVector()).thenReturn(new Vector(1,2,3)); - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.NETHER_PORTAL); - // Nether islands active - when(iwm.isNetherIslands(any())).thenReturn(true); - when(iwm.isNetherGenerate(any())).thenReturn(true); - - Island island = mock(Island.class); - when(island.getSpawnPoint(any())).thenReturn(null); - Optional optionalIsland = Optional.of(island); - // Island exists at location - when(im.getIslandAt(any())).thenReturn(optionalIsland); - - - np.onIslandPortal(e); - // Verify - assertTrue(e.isCancelled()); - // If nether islands, then to = from but in nether - verify(from, times(2)).toVector(); - // Do not go to spawn - verify(nether, never()).getSpawnLocation(); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalFromWorldToNetherStandard() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - // Teleport from world to nether - when(from.getWorld()).thenReturn(world); - when(from.toVector()).thenReturn(new Vector(1,2,3)); - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.NETHER_PORTAL); - // Nether islands inactive - when(iwm.isNetherIslands(any())).thenReturn(false); - when(iwm.isNetherGenerate(any())).thenReturn(true); - np.onIslandPortal(e); - // Verify - assertFalse(e.isCancelled()); - // We are not going to 1,2,3 - assertFalse(e.getTo().toString().contains("x=1.0,y=2.0,z=3.0")); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalFromWorldToNetherStandardMakePortals() { - when(ws.isMakeNetherPortals()).thenReturn(true); - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - // Teleport from world to nether - when(from.getWorld()).thenReturn(world); - when(from.toVector()).thenReturn(new Vector(1,2,3)); - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.NETHER_PORTAL); - // Nether islands inactive - when(iwm.isNetherIslands(any())).thenReturn(false); - when(iwm.isNetherGenerate(any())).thenReturn(true); - np.onIslandPortal(e); - // Verify - assertFalse(e.isCancelled()); - assertTrue(e.getTo().toString().contains("x=1.0,y=2.0,z=3.0")); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalFromNetherStandard() throws Exception { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - // Teleport from nether to world - when(from.getWorld()).thenReturn(nether); - when(from.toVector()).thenReturn(new Vector(1,2,3)); - Player p = mock(Player.class); - when(p.getUniqueId()).thenReturn(UUID.randomUUID()); - - PlayerPortalEvent e = new PlayerPortalEvent(p, from, null, TeleportCause.NETHER_PORTAL); - // Nether islands inactive - when(iwm.isNetherIslands(any())).thenReturn(false); - when(iwm.isNetherGenerate(any())).thenReturn(true); - - // Player should be teleported to their island - np.onIslandPortal(e); - // Verify - assertTrue(e.isCancelled()); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalFromNetherIsland() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - // Teleport from nether to world - when(from.getWorld()).thenReturn(nether); - when(from.toVector()).thenReturn(new Vector(1,2,3)); - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.NETHER_PORTAL); - // Nether islands active - when(iwm.isNetherIslands(any())).thenReturn(true); - when(iwm.isNetherGenerate(any())).thenReturn(true); - np.onIslandPortal(e); - // Verify - assertTrue(e.isCancelled()); - // If regular nether, then to = island location - verify(from).toVector(); - verify(im, never()).getIslandLocation(any(), any()); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalNullWorldNether() { - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - // Teleport from nether to world - when(from.getWorld()).thenReturn(null); - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.NETHER_PORTAL); - np.onIslandPortal(e); - // Verify - assertFalse(e.isCancelled()); - } - - /** - * Test method for {@link PortalTeleportationListener#onIslandPortal(org.bukkit.event.player.PlayerPortalEvent)}. - */ - @Test - public void testonIslandPortalNonBentoBoxWorldNether() { - when(iwm.inWorld(any(World.class))).thenReturn(false); - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - Location from = mock(Location.class); - // Teleport from nether to world - when(from.getWorld()).thenReturn(mock(World.class)); - PlayerPortalEvent e = new PlayerPortalEvent(player, from, null, TeleportCause.NETHER_PORTAL); - np.onIslandPortal(e); - // Verify - assertFalse(e.isCancelled()); - verify(iwm, never()).isNetherGenerate(any()); - } - - - /** - * Test method for {@link PortalTeleportationListener#setSeachRadius(PlayerPortalEvent, Island) - */ - @Test - public void testSetSeachRadius() { - Location from = mock(Location.class); - Location to = mock(Location.class); - PlayerPortalEvent e = new PlayerPortalEvent(p, from, to); - Island island = mock(Island.class); - when(island.onIsland(any())).thenReturn(true); - Location center = mock(Location.class); - when(center.getBlockX()).thenReturn(200); - when(center.getBlockZ()).thenReturn(200); - when(island.getProtectionCenter()).thenReturn(center); - when(island.getProtectionRange()).thenReturn(200); - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - when(from.getBlockZ()).thenReturn(205); - assertEquals(128, e.getSearchRadius()); - - for (int x = 200; x < 410; x++) { - when(from.getBlockX()).thenReturn(x); - np.setSeachRadius(new PlayerEntityPortalEvent(e), island); - if (x >= 400) { - assertEquals(1, e.getSearchRadius()); - } else if (x < 273) { - assertEquals(128, e.getSearchRadius()); - } else if (x < 400) { - assertEquals(400 - x, e.getSearchRadius()); - } - } - } - - /** - * Test method for {@link PortalTeleportationListener#setSeachRadius(PlayerPortalEvent, Island) - */ - @Test - public void testSetSeachRadiusNotOnIsland() { - Location from = mock(Location.class); - PlayerPortalEvent e = new PlayerPortalEvent(p, from, null); - Island island = mock(Island.class); - when(island.onIsland(any())).thenReturn(false); - PortalTeleportationListener np = new PortalTeleportationListener(plugin); - np.setSeachRadius(new PlayerEntityPortalEvent(e), island); - assertEquals(128, e.getSearchRadius()); - } -}