public boolean teleport(Entity entity, Field sourceField, String announce) {
    Field destinationField =
        plugin.getForceFieldManager().getDestinationField(sourceField.getOwner(), sourceField);

    if (destinationField != null) {
      if (sourceField.getSettings().getTeleportMaxDistance() > 0) {
        if (sourceField.getLocation().distance(destinationField.getLocation())
            > sourceField.getSettings().getTeleportMaxDistance()) {
          Player player = Bukkit.getServer().getPlayerExact(sourceField.getOwner());

          if (player != null) {
            ChatBlock.send(
                player, "teleportMaxDistance", sourceField.getSettings().getTeleportMaxDistance());
          }
          return false;
        }
      }

      if (sourceField.getSettings().getTeleportCost() > 0) {
        if (plugin.getPermissionsManager().hasEconomy()) {
          if (PermissionsManager.hasMoney(
              sourceField.getOwner(), sourceField.getSettings().getTeleportCost())) {
            plugin
                .getPermissionsManager()
                .playerCharge(sourceField.getOwner(), sourceField.getSettings().getTeleportCost());
          } else {
            Player player = Bukkit.getServer().getPlayerExact(sourceField.getOwner());

            if (player != null) {
              ChatBlock.send(player, "economyNotEnoughMoney");
            }
            return false;
          }
        }
      }

      if (sourceField.hasFlag(FieldFlag.TELEPORT_RELATIVELY)) {
        return plugin
            .getTeleportationManager()
            .teleport(
                new TeleportEntry(
                    entity,
                    new RelativeBlock(sourceField.toVec(), new Vec(entity.getLocation())),
                    sourceField,
                    destinationField,
                    announce));
      } else {
        return plugin
            .getTeleportationManager()
            .teleport(new TeleportEntry(entity, sourceField, destinationField, announce));
      }
    }

    return false;
  }
  /** @param event */
  @EventHandler(priority = EventPriority.HIGH)
  public void onVehicleDestroy(VehicleDestroyEvent event) {
    Vehicle vehicle = event.getVehicle();

    Field field =
        plugin
            .getForceFieldManager()
            .getEnabledSourceField(vehicle.getLocation(), FieldFlag.PREVENT_VEHICLE_DESTROY);

    if (field != null) {
      if (event.getAttacker() instanceof Player) {
        Player player = (Player) event.getAttacker();

        if (FieldFlag.PREVENT_VEHICLE_DESTROY.applies(field, player)) {
          if (plugin.getPermissionsManager().has(player, "preciousstones.bypass.destroy")) {
            plugin.getCommunicationManager().notifyBypassDestroyVehicle(player, vehicle, field);
          } else {
            event.setCancelled(true);
            plugin.getCommunicationManager().warnDestroyVehicle(player, vehicle, field);
            return;
          }
        }
      }
    }
  }
  /**
   * Gets the maximum amount of fields a player can place
   *
   * @param player
   * @param fs the field settings of the field you need to get the limit of
   * @return the limit, -1 if no limit
   */
  public int getLimit(Player player, FieldSettings fs) {
    List<Integer> limits = fs.getLimits();

    if (limits.isEmpty()) {
      return -1;
    }

    List<Integer> playersLimits = new ArrayList<Integer>();

    // get all the counts for all limits the player has

    for (int i = limits.size() - 1; i >= 0; i--) {
      if (plugin.getPermissionsManager().has(player, "preciousstones.limit" + (i + 1))) {
        playersLimits.add(limits.get(i));
      }
    }

    // return the highest one

    if (!playersLimits.isEmpty()) {
      return Collections.max(playersLimits);
    }

    return -1;
  }
  /**
   * @param player
   * @param field
   */
  public void enterLightning(final Player player, final Field field) {
    if (plugin.getPermissionsManager().hasPermission(player, "preciousstones.bypass.lightning")) {
      return;
    }

    if (!plugin.getForceFieldManager().isAllowed(field, player.getName())) {
      FieldSettings fs = field.getSettings();

      final int delay = fs.getLightningDelaySeconds();
      final int leftbehind = fs.getLightningReplaceBlock();

      if (fs.hasFlag(FieldFlag.LIGHTNING)) {
        plugin.getCommunicationManager().showLightning(player);

        plugin
            .getServer()
            .getScheduler()
            .scheduleSyncDelayedTask(
                plugin,
                new Runnable() {
                  public void run() {
                    Block block = plugin.getForceFieldManager().getBlock(field);

                    player.getWorld().strikeLightning(player.getLocation());

                    if (leftbehind >= 0) {
                      plugin.getForceFieldManager().silentRelease(field);
                      block.setType(Material.getMaterial(leftbehind));
                    }
                  }
                },
                delay * 20L);
      }
    }
  }
  /**
   * Whether the player has reached the placing limit for a field
   *
   * @param player
   * @param fs the field settings of the field you need to get the limit of
   * @return
   */
  public boolean reachedLimit(Player player, FieldSettings fs) {
    List<Integer> limits = fs.getLimits();

    if (limits.isEmpty()) {
      return false;
    }

    if (plugin.getPermissionsManager().has(player, "preciousstones.bypass.limits")) {
      return false;
    }

    int limit = getLimit(player, fs);
    int count =
        plugin.getForceFieldManager().getFieldCount(player.getName(), fs.getTypeEntry())
            + plugin
                .getForceFieldManager()
                .getRentedFieldCount(player.getName(), fs.getTypeEntry());

    if (limit == -1) {
      return false;
    }

    if (limit == 0) {
      ChatHelper.send(player, "limitsCannotPlace", fs.getTitle());
      return true;
    }

    if (count >= limit) {
      ChatHelper.send(player, "limitsReached", fs.getTitle(), limit);
      return true;
    }

    int totalCount = plugin.getForceFieldManager().getTotalFieldCount(player.getName());

    if (totalCount >= plugin.getSettingsManager().getGlobalFieldLimit()) {
      ChatHelper.send(player, "limitsReachedGlobal", limit);
      return true;
    }

    return false;
  }
  public boolean teleport(List<TeleportEntry> entries) {
    for (TeleportEntry entry : entries) {
      Entity entity = entry.getEntity();
      Location destination = entry.getDestination();
      Field sourceField = entry.getSourceField();
      Vec currentPosition = null;

      if (entity instanceof Player) {
        Player player = (Player) entity;

        plugin.getPlayerManager().getPlayerEntry(player.getName()).setTeleporting(false);

        // done teleport players with bypass permission

        if (plugin.getPermissionsManager().has(player, "preciousstones.bypass.teleport")) {
          continue;
        }

        // don't teleport if sneaking bypasses

        if (sourceField.hasFlag(FieldFlag.SNEAKING_BYPASS)
            && !sourceField.hasFlag(FieldFlag.TELEPORT_ON_SNEAK)) {
          if (player.isSneaking()) {
            continue;
          }
        }

        currentPosition = new Vec(player.getLocation());
      }

      // prepare teleport destination

      World world = destination.getWorld();

      Vec safe = findSafeLocation(destination);
      double x = safe.getX() + .5D;
      double y = safe.getY();
      double z = safe.getZ() + .5D;

      if (y == -1) {
        continue;
      }

      if (!world.isChunkLoaded(destination.getBlockX() >> 4, destination.getBlockZ() >> 4)) {
        world.loadChunk(destination.getBlockX() >> 4, destination.getBlockZ() >> 4);
      }

      Location loc =
          new Location(
              world, x, y, z, entity.getLocation().getYaw(), entity.getLocation().getPitch());

      // teleport the player

      if (sourceField.hasFlag(FieldFlag.TELEPORT_EXPLOSION_EFFECT)) {
        world.createExplosion(entity.getLocation(), -1);
      }

      entity.teleport(loc);

      if (sourceField.hasFlag(FieldFlag.TELEPORT_EXPLOSION_EFFECT)) {
        world.createExplosion(loc, -1);
      }

      if (entity instanceof Player) {
        Player player = (Player) entity;

        if (sourceField.hasFlag(FieldFlag.TELEPORT_ANNOUNCE)) {
          if (!entry.getAnnounce().isEmpty()) {
            ChatBlock.send(player, entry.getAnnounce());
          }
        }

        // start teleport back countdown

        if (sourceField.getSettings().getTeleportBackAfterSeconds() > 0) {
          if (sourceField.hasFlag(FieldFlag.TELEPORT_ANNOUNCE)) {
            ChatBlock.send(
                player,
                "teleportAnnounceBack",
                sourceField.getSettings().getTeleportBackAfterSeconds());
          }

          PlayerEntry playerEntry = plugin.getPlayerManager().getPlayerEntry(player.getName());

          playerEntry.setTeleportSecondsRemaining(
              sourceField.getSettings().getTeleportBackAfterSeconds());
          playerEntry.setTeleportVec(currentPosition);
          playerEntry.startTeleportCountDown();
          plugin.getStorageManager().offerPlayer(player.getName());
        }
      }
    }

    return true;
  }