@Override
  public void perform() {
    // TODO: Hide this command on help also.
    if (!Conf.homesEnabled) {
      fme.msg("<b>Sorry, Faction homes are disabled on this server.");
      return;
    }

    if (!Conf.homesTeleportCommandEnabled) {
      fme.msg("<b>Sorry, the ability to teleport to Faction homes is disabled on this server.");
      return;
    }

    if (!myFaction.hasHome()) {
      fme.msg(
          "<b>You faction does not have a home. "
              + (fme.getRole().value < Role.MODERATOR.value
                  ? "<i> Ask your leader to:"
                  : "<i>You should:"));
      fme.sendMessage(p.cmdBase.cmdSethome.getUseageTemplate());
      return;
    }

    if (!Conf.homesTeleportAllowedFromEnemyTerritory && fme.isInEnemyTerritory()) {
      fme.msg(
          "<b>You cannot teleport to your faction home while in the territory of an enemy faction.");
      return;
    }

    if (!Conf.homesTeleportAllowedFromDifferentWorld
        && me.getWorld().getUID() != myFaction.getHome().getWorld().getUID()) {
      fme.msg("<b>You cannot teleport to your faction home while in a different world.");
      return;
    }

    Faction faction = Board.getFactionAt(new FLocation(me.getLocation()));

    // if player is not in a safe zone or their own faction territory, only
    // allow teleport if no enemies are nearby
    if (Conf.homesTeleportAllowedEnemyDistance > 0
        && !faction.isSafeZone()
        && (!fme.isInOwnTerritory()
            || (fme.isInOwnTerritory() && !Conf.homesTeleportIgnoreEnemiesIfInOwnTerritory))) {
      Location loc = me.getLocation();
      World w = loc.getWorld();
      double x = loc.getX();
      double y = loc.getY();
      double z = loc.getZ();

      for (Player p : me.getServer().getOnlinePlayers()) {
        if (p == null || !p.isOnline() || p.isDead() || p == fme || p.getWorld() != w) continue;

        FPlayer fp = FPlayers.i.get(p);
        if (fme.getRelationTo(fp) != Relation.ENEMY) continue;

        Location l = p.getLocation();
        double dx = Math.abs(x - l.getX());
        double dy = Math.abs(y - l.getY());
        double dz = Math.abs(z - l.getZ());
        double max = Conf.homesTeleportAllowedEnemyDistance;

        // box-shaped distance check
        if (dx > max || dy > max || dz > max) continue;

        fme.msg(
            "<b>You cannot teleport to your faction home while an enemy is within "
                + Conf.homesTeleportAllowedEnemyDistance
                + " blocks of you.");
        return;
      }
    }

    // if Essentials teleport handling is enabled and available, pass the
    // teleport off to it (for delay and cooldown)
    if (EssentialsFeatures.handleTeleport(me, myFaction.getHome())) return;

    // if economy is enabled, they're not on the bypass list, and this
    // command has a cost set, make 'em pay
    if (!payForCommand(
        Conf.econCostHome,
        "to teleport to your faction home",
        "for teleporting to your faction home")) return;

    // Create a smoke effect
    if (Conf.homesTeleportCommandSmokeEffectEnabled) {
      List<Location> smokeLocations = new ArrayList<Location>();
      smokeLocations.add(me.getLocation());
      smokeLocations.add(me.getLocation().clone().add(0, 1, 0));
      smokeLocations.add(myFaction.getHome());
      smokeLocations.add(myFaction.getHome().clone().add(0, 1, 0));
      SmokeUtil.spawnCloudRandom(smokeLocations, Conf.homesTeleportCommandSmokeEffectThickness);
    }

    me.teleport(myFaction.getHome());
  }
  public boolean playerCanUseItemHere(Player player, Block block, Material material) {

    if (Conf.adminBypassPlayers.contains(player.getName())) {
      return true;
    }

    FLocation loc = new FLocation(block);
    Faction otherFaction = Board.getFactionAt(loc);

    if (otherFaction.hasPlayersOnline()) {
      if (!Conf.territoryDenyUseageMaterials.contains(material)) {
        return true; // Item isn't one we're preventing for online factions.
      }
    } else {
      if (!Conf.territoryDenyUseageMaterialsWhenOffline.contains(material)) {
        return true; // Item isn't one we're preventing for offline factions.
      }
    }

    FPlayer me = FPlayer.get(player);

    if (otherFaction.isNone()) {
      if (!Conf.wildernessDenyUseage
          || Factions.hasPermAdminBypass(player)
          || Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) {
        return true; // This is not faction territory. Use whatever you like here.
      }
      me.sendMessage("You can't use " + TextUtil.getMaterialName(material) + " in the wilderness.");
      return false;
    } else if (otherFaction.isSafeZone()) {
      if (!Conf.safeZoneDenyUseage || Factions.hasPermManageSafeZone(player)) {
        return true;
      }
      me.sendMessage("You can't use " + TextUtil.getMaterialName(material) + " in a safe zone.");
      return false;
    } else if (otherFaction.isWarZone()) {
      if (!Conf.warZoneDenyUseage || Factions.hasPermManageWarZone(player)) {
        return true;
      }
      me.sendMessage("You can't use " + TextUtil.getMaterialName(material) + " in a war zone.");
      return false;
    }

    Faction myFaction = me.getFaction();
    Relation rel = myFaction.getRelation(otherFaction);
    boolean ownershipFail =
        Conf.ownedAreasEnabled
            && Conf.ownedAreaDenyUseage
            && !otherFaction.playerHasOwnershipRights(me, loc);

    // Cancel if we are not in our own territory
    if (!rel.isMember() && rel.confDenyUseage()) {
      me.sendMessage(
          "You can't use "
              + TextUtil.getMaterialName(material)
              + " in the territory of "
              + otherFaction.getTag(myFaction));
      return false;
    }
    // Also cancel if player doesn't have ownership rights for this claim
    else if (rel.isMember() && ownershipFail && !Factions.hasPermOwnershipBypass(player)) {
      me.sendMessage(
          "You can't use "
              + TextUtil.getMaterialName(material)
              + " in this territory, it is owned by: "
              + myFaction.getOwnerListString(loc));
      return false;
    }

    return true;
  }