/** {@inheritDoc} */
  @Override
  public TeleportResult safelyTeleport(
      CommandSender teleporter, Entity teleportee, MVDestination d) {
    if (d instanceof InvalidDestination) {
      this.plugin.log(Level.FINER, "Entity tried to teleport to an invalid destination");
      return TeleportResult.FAIL_INVALID;
    }
    Player teleporteePlayer = null;
    if (teleportee instanceof Player) {
      teleporteePlayer = ((Player) teleportee);
    } else if (teleportee.getPassenger() instanceof Player) {
      teleporteePlayer = ((Player) teleportee.getPassenger());
    }

    if (teleporteePlayer == null) {
      return TeleportResult.FAIL_INVALID;
    }
    MultiverseCore.addPlayerToTeleportQueue(teleporter.getName(), teleporteePlayer.getName());

    Location safeLoc = d.getLocation(teleportee);
    if (d.useSafeTeleporter()) {
      safeLoc = this.getSafeLocation(teleportee, d);
    }

    if (safeLoc != null) {
      if (teleportee.teleport(safeLoc)) {
        if (!d.getVelocity().equals(new Vector(0, 0, 0))) {
          teleportee.setVelocity(d.getVelocity());
        }
        return TeleportResult.SUCCESS;
      }
      return TeleportResult.FAIL_OTHER;
    }
    return TeleportResult.FAIL_UNSAFE;
  }
  /**
   * Called when the portal is ready to take the player to the destination.
   *
   * @param event The Portal event.
   */
  @EventHandler
  public void playerPortal(PlayerPortalEvent event) {
    if (event.isCancelled()) {
      return;
    }
    PortalDetector detector = new PortalDetector(this.plugin);
    try {
      String destString = detector.getNotchPortalDestination(event.getPlayer(), event.getFrom());
      if (destString != null) {
        this.plugin.log(Level.FINER, "Found a Multiverse Sign");
        DestinationFactory df = this.plugin.getCore().getDestFactory();
        event.useTravelAgent(true);
        MVDestination dest = df.getDestination(destString);
        event.setPortalTravelAgent(
            new MVTravelAgent(this.plugin.getCore(), dest, event.getPlayer()));
        event.setTo(dest.getLocation(event.getPlayer()));
      }

    } catch (NoMultiverseSignFoundException e) {
      // This will simply act as a notch portal.
      this.plugin.log(Level.FINER, "Did NOT find a Multiverse Sign");
    } catch (MoreThanOneSignFoundException e) {
      this.plugin
          .getCore()
          .getMessaging()
          .sendMessage(
              event.getPlayer(),
              String.format(
                  "%sSorry %sbut more than 1 sign was found where the second line was [mv] or [multiverse]. Please remove one of the signs.",
                  ChatColor.RED, ChatColor.WHITE),
              false);
      event.setCancelled(true);
    }
  }
 public boolean playerCanGoToDestination(Player player, MVDestination d) {
   if (d instanceof InvalidDestination || !d.isValid()) {
     this.plugin
         .getCore()
         .getMessaging()
         .sendMessage(player, "The Destination on this sign is Invalid!", false);
     return false;
   }
   return this.plugin
       .getCore()
       .getMVPerms()
       .hasPermission(player, d.getRequiredPermission(), true);
 }
 /** {@inheritDoc} */
 @Override
 public Location getSafeLocation(Entity e, MVDestination d) {
   Location l = d.getLocation(e);
   if (plugin.getBlockSafety().playerCanSpawnHereSafely(l)) {
     plugin.log(Level.FINE, "The first location you gave me was safe.");
     return l;
   }
   if (e instanceof Minecart) {
     Minecart m = (Minecart) e;
     if (!plugin.getBlockSafety().canSpawnCartSafely(m)) {
       return null;
     }
   } else if (e instanceof Vehicle) {
     Vehicle v = (Vehicle) e;
     if (!plugin.getBlockSafety().canSpawnVehicleSafely(v)) {
       return null;
     }
   }
   Location safeLocation = this.getSafeLocation(l);
   if (safeLocation != null) {
     // Add offset to account for a vehicle on dry land!
     if (e instanceof Minecart && !plugin.getBlockSafety().isEntitiyOnTrack(safeLocation)) {
       safeLocation.setY(safeLocation.getBlockY() + .5);
       this.plugin.log(Level.FINER, "Player was inside a minecart. Offsetting Y location.");
     }
     this.plugin.log(Level.FINE, "Had to look for a bit, but I found a safe place for ya!");
     return safeLocation;
   }
   if (e instanceof Player) {
     Player p = (Player) e;
     this.plugin.getMessaging().sendMessage(p, "No safe locations found!", false);
     this.plugin.log(Level.FINER, "No safe location found for " + p.getName());
   } else if (e.getPassenger() instanceof Player) {
     Player p = (Player) e.getPassenger();
     this.plugin.getMessaging().sendMessage(p, "No safe locations found!", false);
     this.plugin.log(Level.FINER, "No safe location found for " + p.getName());
   }
   this.plugin.log(
       Level.FINE,
       "Sorry champ, you're basically trying to teleport into a minefield. I should just kill you now.");
   return null;
 }