@Override
  public void executeCommand(Player admin, String[] params) {
    if (admin.getAccessLevel() < AdminConfig.COMMAND_PRISON) {
      PacketSendUtility.sendMessage(admin, "You dont have enough rights to execute this command!");
      return;
    }

    if (params.length == 0 || params.length > 2) {
      PacketSendUtility.sendMessage(admin, "syntax //rprison <player>");
      return;
    }

    try {
      Player playerFromPrison = World.getInstance().findPlayer(Util.convertName(params[0]));

      if (playerFromPrison != null) {
        PunishmentService.setIsInPrison(playerFromPrison, false, 0);
        PacketSendUtility.sendMessage(
            admin, "Player " + playerFromPrison.getName() + " removed from prison.");
      }
    } catch (NoSuchElementException nsee) {
      PacketSendUtility.sendMessage(admin, "Usage: //rprison <player>");
    } catch (Exception e) {
      PacketSendUtility.sendMessage(admin, "Usage: //rprison <player>");
    }
  }
  /** {@inheritDoc} */
  @Override
  protected void runImpl() {
    Player activePlayer = getConnection().getActivePlayer();

    Iterator<Player> it = World.getInstance().getPlayersIterator();

    List<Player> matches = new ArrayList<Player>(MAX_RESULTS);

    if (activePlayer != null && activePlayer.getLevel() < 10) {
      sendPacket(SM_SYSTEM_MESSAGE.LEVEL_NOT_ENOUGH_FOR_SEARCH("10"));
      return;
    }
    while (it.hasNext() && matches.size() < MAX_RESULTS) {
      Player player = it.next();
      if (!player.isSpawned()) continue;
      else if (player.getFriendList().getStatus() == Status.OFFLINE) continue;
      else if (lfgOnly == 1 && !player.isLookingForGroup()) continue;
      else if (!name.isEmpty() && !player.getName().toLowerCase().contains(name.toLowerCase()))
        continue;
      else if (minLevel != 0xFF && player.getLevel() < minLevel) continue;
      else if (maxLevel != 0xFF && player.getLevel() > maxLevel) continue;
      else if (classMask > 0 && (player.getPlayerClass().getMask() & classMask) == 0) continue;
      else if (region > 0 && player.getActiveRegion().getMapId() != region) continue;
      else if ((player.getCommonData().getRace() != activePlayer.getCommonData().getRace())
          && (CustomConfig.FACTIONS_SEARCH_MODE == false)) continue;
      else
      // This player matches criteria
      {
        matches.add(player);
      }
    }

    sendPacket(new SM_PLAYER_SEARCH(matches, region));
  }
  /**
   * This method is called when player leaves the game, which includes just two cases: either player
   * goes back to char selection screen or it's leaving the game [closing client].<br>
   * <br>
   * <b><font color='red'>NOTICE: </font> This method is called only from {@link AionConnection} and
   * {@link CM_QUIT} and must not be called from anywhere else</b>
   *
   * @param player
   */
  public static void playerLoggedOut(final Player player) {
    log.info(
        "Player logged out: "
            + player.getName()
            + " Account: "
            + player.getClientConnection().getAccount().getName());
    player.onLoggedOut();

    // Update prison timer
    if (player.isInPrison()) {
      long prisonTimer = System.currentTimeMillis() - player.getStartPrison();
      prisonTimer = player.getPrisonTimer() - prisonTimer;

      player.setPrisonTimer(prisonTimer);

      log.debug("Update prison timer to " + prisonTimer / 1000 + " seconds !");
    }

    // store current effects
    DAOManager.getDAO(PlayerEffectsDAO.class).storePlayerEffects(player);
    DAOManager.getDAO(ItemCooldownsDAO.class).storeItemCooldowns(player);
    DAOManager.getDAO(PlayerLifeStatsDAO.class).updatePlayerLifeStat(player);
    player.getEffectController().removeAllEffects();

    player.getLifeStats().cancelAllTasks();

    if (player.getLifeStats().isAlreadyDead()) TeleportService.moveToBindLocation(player, false);

    if (DuelService.getInstance().isDueling(player.getObjectId()))
      DuelService.getInstance().loseDuel(player);

    if (player.getSummon() != null) player.getSummon().getController().release(UnsummonType.LOGOUT);

    PunishmentService.stopPrisonTask(player, true);

    player.getCommonData().setOnline(false);
    player.getCommonData().setLastOnline(new Timestamp(System.currentTimeMillis()));

    player.setClientConnection(null);

    if (player.isLegionMember()) LegionService.getInstance().onLogout(player);

    if (player.isInGroup()) GroupService.getInstance().scheduleRemove(player);

    if (player.isInAlliance()) AllianceService.getInstance().onLogout(player);

    player.getController().delete();
    DAOManager.getDAO(PlayerDAO.class).onlinePlayer(player, false);

    if (!GSConfig.DISABLE_CHAT_SERVER) ChatService.onPlayerLogout(player);

    storePlayer(player);
    player.getEquipment().setOwner(null);
  }
 /**
  * This method is called just after player logged in to the game.<br>
  * <br>
  * <b><font color='red'>NOTICE: </font> This method called only from {@link CM_ENTER_WORLD} and
  * must not be called from anywhere else.</b>
  *
  * @param player
  */
 public static void playerLoggedIn(Player player) {
   log.info(
       "Player logged in: "
           + player.getName()
           + " Account: "
           + player.getClientConnection().getAccount().getName());
   player.getCommonData().setOnline(true);
   DAOManager.getDAO(PlayerDAO.class).onlinePlayer(player, true);
   player.getFriendList().setStatus(Status.ONLINE);
   player.onLoggedIn();
 }
 /**
  * Constructs new <tt>SM_MESSAGE </tt> packet
  *
  * @param player who sent message
  * @param message actual message
  * @param chatType what chat type should be used
  */
 public SM_MESSAGE(Player player, String message, ChatType chatType) {
   this.player = player;
   this.senderObjectId = player.getObjectId();
   this.senderName = player.getName();
   this.message = message;
   this.race = player.getCommonData().getRace();
   this.chatType = chatType;
   this.x = player.getX();
   this.y = player.getY();
   this.z = player.getZ();
 }
  /** {@inheritDoc} */
  @Override
  protected void runImpl() {

    Player activePlayer = getConnection().getActivePlayer();
    Friend target = activePlayer.getFriendList().getFriend(targetName);
    if (target == null) {
      log.warn(
          activePlayer.getName()
              + " tried to delete friend "
              + targetName
              + " who is not his friend");
      sendPacket(SM_SYSTEM_MESSAGE.BUDDYLIST_NOT_IN_LIST);
    } else {
      SocialService.deleteFriend(activePlayer, target.getOid());
    }
  }
Exemple #7
0
  @Override
  public void execute(Player player, String... params) {
    if ((params.length < 0) || (params.length < 1)) {
      onFail(player, null);
      return;
    }
    int itemId = 0;
    long itemCount = 1;
    Player receiver;

    try {
      String item = params[0];
      // Some item links have space before Id
      if (item.equals("[item:")) {
        item = params[1];
        Pattern id = Pattern.compile("(\\d{9})");
        Matcher result = id.matcher(item);
        if (result.find()) itemId = Integer.parseInt(result.group(1));

        if (params.length == 3) itemCount = Long.parseLong(params[2]);
      } else {
        Pattern id = Pattern.compile("\\[item:(\\d{9})");
        Matcher result = id.matcher(item);

        if (result.find()) itemId = Integer.parseInt(result.group(1));
        else itemId = Integer.parseInt(params[0]);

        if (params.length == 2) itemCount = Long.parseLong(params[1]);
      }
      receiver = player;
    } catch (NumberFormatException e) {
      receiver = World.getInstance().findPlayer(Util.convertName(params[0]));
      if (receiver == null) {
        PacketSendUtility.sendMessage(player, "Could not find a player by that name.");
        return;
      }

      try {
        String item = params[1];
        // Some item links have space before Id
        if (item.equals("[item:")) {
          item = params[2];
          Pattern id = Pattern.compile("(\\d{9})");
          Matcher result = id.matcher(item);
          if (result.find()) itemId = Integer.parseInt(result.group(1));

          if (params.length == 4) itemCount = Long.parseLong(params[3]);
        } else {
          Pattern id = Pattern.compile("\\[item:(\\d{9})");
          Matcher result = id.matcher(item);

          if (result.find()) itemId = Integer.parseInt(result.group(1));
          else itemId = Integer.parseInt(params[1]);

          if (params.length == 3) itemCount = Long.parseLong(params[2]);
        }
      } catch (NumberFormatException ex) {
        PacketSendUtility.sendMessage(player, "You must give number to itemid.");
        return;
      } catch (Exception ex2) {
        PacketSendUtility.sendMessage(player, "Occurs an error.");
        return;
      }
    }

    if (DataManager.ITEM_DATA.getItemTemplate(itemId) == null) {
      PacketSendUtility.sendMessage(player, "Item id is incorrect: " + itemId);
      return;
    }

    if (!AdminService.getInstance().canOperate(player, receiver, itemId, "command //add")) return;

    long count = ItemService.addItem(receiver, itemId, itemCount);

    if (count == 0) {
      if (player != receiver) {
        PacketSendUtility.sendMessage(
            player,
            "You successfully gave "
                + itemCount
                + " x [item:"
                + itemId
                + "] to "
                + receiver.getName()
                + ".");
        PacketSendUtility.sendMessage(
            receiver,
            "You successfully received "
                + itemCount
                + " x [item:"
                + itemId
                + "] from "
                + player.getName()
                + ".");
      } else
        PacketSendUtility.sendMessage(
            player, "You successfully received " + itemCount + " x [item:" + itemId + "]");
    } else {
      PacketSendUtility.sendMessage(player, "Item couldn't be added");
    }
  }
 /**
  * Remove Player from this Container.
  *
  * @param player
  */
 public void remove(Player player) {
   playersById.remove(player.getObjectId());
   playersByName.remove(player.getName());
 }
 /**
  * Add Player to this Container.
  *
  * @param player
  */
 public void add(Player player) {
   if (playersById.put(player.getObjectId(), player) != null)
     throw new DuplicateAionObjectException();
   if (playersByName.put(player.getName(), player) != null)
     throw new DuplicateAionObjectException();
 }
Exemple #10
0
  private boolean checkAnimationTime() {
    if (!(effector instanceof Player) || skillMethod != SkillMethod.CAST) // TODO item skills?
    return true;
    Player player = (Player) effector;

    // if player is without weapon, dont check animation time
    if (player.getEquipment().getMainHandWeaponType() == null) return true;

    /** exceptions for certain skills -herb and mana treatment -traps */
    // dont check herb , mana treatment and concentration enhancement
    switch (this.getSkillId()) {
      case 1803: // bandage heal
      case 1804: // herb treatment
      case 1805:
      case 1825:
      case 1827:
      case 2672:
      case 1823: // mana treatment
      case 1824:
      case 1826:
      case 1828:
      case 2673:
      case 1078: // concentration enhancement
      case 1125:
      case 1468:
      case 11580:
        return true;
    }
    if (this.getSkillTemplate().getSubType() == SkillSubType.SUMMONTRAP) return true;

    Motion motion = this.getSkillTemplate().getMotion();

    if (motion == null || motion.getName() == null) {
      log.warn("missing motion for skillId: " + this.getSkillId());
      return true;
    }

    if (motion.getInstantSkill() && hitTime != 0) {
      log.warn(
          "Instant and hitTime not 0! modified client_skills? player objectid: "
              + player.getObjectId());
      return false;
    } else if (!motion.getInstantSkill() && hitTime == 0) {
      log.warn("modified client_skills! player objectid: " + player.getObjectId());
      return false;
    }

    MotionTime motionTime = DataManager.MOTION_DATA.getMotionTime(motion.getName());

    if (motionTime == null) {
      log.warn(
          "missing motiontime for motionName: "
              + motion.getName()
              + " skillId: "
              + this.getSkillId());
      return true;
    }

    WeaponTypeWrapper weapons =
        new WeaponTypeWrapper(
            player.getEquipment().getMainHandWeaponType(),
            player.getEquipment().getOffHandWeaponType());
    float serverTime = motionTime.getTimeForWeapon(player.getRace(), player.getGender(), weapons);
    int clientTime = hitTime;

    if (serverTime == 0) {
      log.warn(
          "missing weapon time for motionName: "
              + motion.getName()
              + " weapons: "
              + weapons.toString()
              + " skillId: "
              + this.getSkillId());
      return true;
    }

    // adjust client time with ammotime
    long ammoTime = 0;
    double distance = MathUtil.getDistance(effector, firstTarget);
    if (getSkillTemplate().getAmmoSpeed() != 0)
      ammoTime =
          Math.round(distance / getSkillTemplate().getAmmoSpeed() * 1000); // checked with client
    clientTime -= ammoTime;

    // adjust servertime with motion play speed
    if (motion.getSpeed() != 100) {
      serverTime /= 100f;
      serverTime *= (float) motion.getSpeed();
    }

    Stat2 attackSpeed = player.getGameStats().getAttackSpeed();

    // adjust serverTime with attackSpeed
    if (attackSpeed.getBase() != attackSpeed.getCurrent())
      serverTime *= ((float) attackSpeed.getCurrent() / (float) attackSpeed.getBase());

    // tolerance
    if (duration == 0) serverTime *= 0.9f;
    else serverTime *= 0.5f;

    int finalTime = Math.round(serverTime);
    if (motion.getInstantSkill() && hitTime == 0) {
      this.serverTime = (int) ammoTime;
    } else {
      if (clientTime < finalTime) {
        // check for no animation Hacks
        if (SecurityConfig.NO_ANIMATION) {
          float clientTme = clientTime;
          float serverTme = serverTime;
          float checkTme = clientTme / serverTme;
          // check if values are too low
          if (clientTime < 0 || checkTme < SecurityConfig.NO_ANIMATION_VALUE) {
            if (SecurityConfig.NO_ANIMATION_KICK) {
              player.getClientConnection().close(new SM_QUIT_RESPONSE(), false);
              AuditLogger.info(
                  player,
                  "Modified client_skills:"
                      + this.getSkillId()
                      + " (clientTime<finalTime:"
                      + clientTime
                      + "/"
                      + finalTime
                      + ") Kicking Player: "
                      + player.getName());
            } else {
              AuditLogger.info(
                  player,
                  "Modified client_skills:"
                      + this.getSkillId()
                      + " (clientTime<finalTime:"
                      + clientTime
                      + "/"
                      + finalTime
                      + ")");
            }
            return false;
          }
        }
        log.warn(
            "Possible modified client_skills:"
                + this.getSkillId()
                + " (clientTime<finalTime:"
                + clientTime
                + "/"
                + finalTime
                + ") player Name: "
                + player.getName());
      }
      this.serverTime = hitTime;
    }
    player.setNextSkillUse(System.currentTimeMillis() + duration + finalTime);
    return true;
  }
  @Override
  public void executeCommand(Player admin, String[] params) {
    if (admin.getAccessLevel() < AdminConfig.COMMAND_POWERUP) {
      PacketSendUtility.sendMessage(admin, "You dont have enough rights to execute this command");
      return;
    }
    int index = 2;
    int i = 0;
    Player player = null;
    if (params.length != 0) {
      if ("help".startsWith(params[i])) {
        PacketSendUtility.sendMessage(admin, "0 to return to normal state");
        PacketSendUtility.sendMessage(admin, "//powerup <Multiplier = 2>");
        PacketSendUtility.sendMessage(
            admin,
            "Syntax:  //powerup [playerName] [Multiplier = 2]\n"
                + "  This command multiplies your actual power to the number given.\n"
                + "  Using 0 as the Multiplier resets the power to normal.\n"
                + "  Notice: You can ommit parameters between [], especially playerName.\n"
                + "  Target: Named player, then targeted player, only then self.\n"
                + "  Default Value: Multiplier is 2.");
        return;
      }
      player = World.getInstance().findPlayer(Util.convertName(params[i]));
      if (player == null) {
        VisibleObject target = admin.getTarget();
        if (target instanceof Player) player = (Player) target;
        else player = admin;
      } else i++;
      try {
        index = Integer.parseInt(params[i]);
      } catch (NumberFormatException ex) {
        PacketSendUtility.sendMessage(admin, "Wrong input use //powerup help");
        return;
      } catch (Exception ex2) {
        PacketSendUtility.sendMessage(admin, "Occurs an error.");
        return;
      }
    }
    if (index == 0) {
      player.getGameStats().recomputeStats();
      player.getLifeStats().increaseHp(TYPE.HP, admin.getLifeStats().getMaxHp() + 1);
      player.getLifeStats().increaseMp(TYPE.MP, admin.getLifeStats().getMaxMp() + 1);
      PacketSendUtility.sendPacket(player, new SM_STATS_INFO(admin));
      if (player == admin) PacketSendUtility.sendMessage(player, "You are now normal again.");
      else {
        PacketSendUtility.sendMessage(
            admin, "Player " + player.getName() + " is now normal again.");
        PacketSendUtility.sendMessage(
            player, "Admin " + admin.getName() + " made you normal again.");
      }
      return;
    }
    player.getGameStats().setStat(StatEnum.MAXMP, admin.getLifeStats().getMaxHp() * index);
    player.getGameStats().setStat(StatEnum.MAXHP, admin.getLifeStats().getMaxMp() * index);

    player
        .getGameStats()
        .setStat(StatEnum.BLOCK, admin.getGameStats().getStatBonus(StatEnum.BLOCK) * index);
    player
        .getGameStats()
        .setStat(StatEnum.EVASION, admin.getGameStats().getStatBonus(StatEnum.EVASION) * index);
    player
        .getGameStats()
        .setStat(StatEnum.HEALTH, admin.getGameStats().getStatBonus(StatEnum.HEALTH) * index);
    player
        .getGameStats()
        .setStat(StatEnum.ACCURACY, admin.getGameStats().getStatBonus(StatEnum.ACCURACY) * index);
    player
        .getGameStats()
        .setStat(StatEnum.PARRY, admin.getGameStats().getStatBonus(StatEnum.PARRY) * index);

    player
        .getGameStats()
        .setStat(
            StatEnum.MAIN_HAND_ACCURACY,
            admin.getGameStats().getStatBonus(StatEnum.MAIN_HAND_ACCURACY) * index);
    player
        .getGameStats()
        .setStat(
            StatEnum.MAIN_HAND_CRITICAL,
            admin.getGameStats().getStatBonus(StatEnum.MAIN_HAND_CRITICAL) * index);
    player
        .getGameStats()
        .setStat(
            StatEnum.MAIN_HAND_POWER,
            admin.getGameStats().getStatBonus(StatEnum.MAIN_HAND_POWER) * index);
    player
        .getGameStats()
        .setStat(
            StatEnum.MAIN_HAND_ATTACK_SPEED,
            admin.getGameStats().getStatBonus(StatEnum.MAIN_HAND_POWER) * index);
    player
        .getGameStats()
        .setStat(
            StatEnum.OFF_HAND_ACCURACY,
            admin.getGameStats().getStatBonus(StatEnum.OFF_HAND_ACCURACY) * index);
    player
        .getGameStats()
        .setStat(
            StatEnum.OFF_HAND_CRITICAL,
            admin.getGameStats().getStatBonus(StatEnum.OFF_HAND_CRITICAL) * index);
    player
        .getGameStats()
        .setStat(
            StatEnum.OFF_HAND_POWER,
            admin.getGameStats().getStatBonus(StatEnum.OFF_HAND_POWER) * index);
    player
        .getGameStats()
        .setStat(
            StatEnum.OFF_HAND_ATTACK_SPEED,
            admin.getGameStats().getStatBonus(StatEnum.OFF_HAND_ATTACK_SPEED) * index);

    player
        .getGameStats()
        .setStat(
            StatEnum.MAGICAL_ATTACK,
            admin.getGameStats().getStatBonus(StatEnum.MAGICAL_ATTACK) * index);
    player
        .getGameStats()
        .setStat(
            StatEnum.MAGICAL_ACCURACY,
            admin.getGameStats().getStatBonus(StatEnum.MAGICAL_ACCURACY) * index);
    player
        .getGameStats()
        .setStat(
            StatEnum.MAGICAL_CRITICAL,
            admin.getGameStats().getStatBonus(StatEnum.MAGICAL_CRITICAL) * index);
    player
        .getGameStats()
        .setStat(
            StatEnum.MAGICAL_RESIST,
            admin.getGameStats().getStatBonus(StatEnum.MAGICAL_RESIST) * index);
    player
        .getGameStats()
        .setStat(
            StatEnum.BOOST_MAGICAL_SKILL,
            admin.getGameStats().getStatBonus(StatEnum.BOOST_MAGICAL_SKILL) * index * 15);

    player
        .getGameStats()
        .setStat(StatEnum.REGEN_MP, admin.getGameStats().getStatBonus(StatEnum.REGEN_MP) * index);
    player
        .getGameStats()
        .setStat(StatEnum.REGEN_HP, admin.getGameStats().getStatBonus(StatEnum.REGEN_HP) * index);

    player.getLifeStats().increaseHp(TYPE.HP, admin.getLifeStats().getMaxHp() + 1);
    player.getLifeStats().increaseMp(TYPE.MP, admin.getLifeStats().getMaxMp() + 1);
    PacketSendUtility.sendPacket(player, new SM_STATS_INFO(admin));
    if (player == admin)
      PacketSendUtility.sendMessage(
          player, "You are now " + index + " times more powerfull than before.");
    else {
      PacketSendUtility.sendMessage(
          admin,
          "Player " + player.getName() + " is now " + index + " times more powerfull than before.");
      PacketSendUtility.sendMessage(
          player,
          "Admin " + admin.getName() + " made you " + index + " times more powerfull than before.");
    }
  }
Exemple #12
0
  public void executeCommand(Player admin, String[] params) {
    if (params == null || params.length < 1) {
      PacketSendUtility.sendMessage(admin, "syntax //bind < all | elyos | asmos >");
      return;
    }

    if (params[0].equals("all")) {
      if (admin.getAccessLevel() < AdminConfig.COMMAND_MOVETOMEALLALL) {
        PacketSendUtility.sendMessage(admin, "You dont have enough rights to execute this command");
        return;
      }

      World world = admin.getActiveRegion().getWorld();
      Iterator<Player> players = world.getPlayersIterator();
      while (players.hasNext()) {
        Player p = players.next();
        if (!p.equals(admin)) {
          teleportService.teleportTo(
              p,
              admin.getWorldId(),
              admin.getInstanceId(),
              admin.getX(),
              admin.getY(),
              admin.getZ(),
              admin.getHeading(),
              5);
          PacketSendUtility.sendPacket(p, new SM_PLAYER_SPAWN(p));

          PacketSendUtility.sendMessage(admin, "Player " + p.getName() + " teleported.");
          PacketSendUtility.sendMessage(p, "Vous avez ete teleporte par " + admin.getName() + ".");
        }
      }
    }

    if (params[0].equals("elyos")) {
      if (admin.getAccessLevel() < AdminConfig.COMMAND_MOVETOMEALLELYOS) {
        PacketSendUtility.sendMessage(admin, "You dont have enough rights to execute this command");
        return;
      }

      World world = admin.getActiveRegion().getWorld();
      Iterator<Player> players = world.getPlayersIterator();
      while (players.hasNext()) {
        Player p = players.next();
        if (!p.equals(admin)) {
          if (p.getCommonData().getRace() == Race.ELYOS) {
            teleportService.teleportTo(
                p,
                admin.getWorldId(),
                admin.getInstanceId(),
                admin.getX(),
                admin.getY(),
                admin.getZ(),
                admin.getHeading(),
                5);
            PacketSendUtility.sendPacket(p, new SM_PLAYER_SPAWN(p));

            PacketSendUtility.sendMessage(admin, "Player " + p.getName() + " teleported.");
            PacketSendUtility.sendMessage(
                p, "Vous avez ete teleporte par " + admin.getName() + ".");
          }
        }
      }
    }

    if (params[0].equals("asmos")) {
      if (admin.getAccessLevel() < AdminConfig.COMMAND_MOVETOMEALLASMOS) {
        PacketSendUtility.sendMessage(admin, "You dont have enough rights to execute this command");
        return;
      }

      World world = admin.getActiveRegion().getWorld();
      Iterator<Player> players = world.getPlayersIterator();
      while (players.hasNext()) {
        Player p = players.next();
        if (!p.equals(admin)) {
          if (p.getCommonData().getRace() == Race.ASMODIANS) {
            teleportService.teleportTo(
                p,
                admin.getWorldId(),
                admin.getInstanceId(),
                admin.getX(),
                admin.getY(),
                admin.getZ(),
                admin.getHeading(),
                5);
            PacketSendUtility.sendPacket(p, new SM_PLAYER_SPAWN(p));

            PacketSendUtility.sendMessage(admin, "Player " + p.getName() + " teleported.");
            PacketSendUtility.sendMessage(
                p, "Vous avez ete teleporte par " + admin.getName() + ".");
          }
        }
      }
    }
  }