@Override
  public String onAsk(L2PcInstance player, L2Npc npc, int ask, int reply) {
    int ownerId;
    if (ask == -1724) {
      switch (reply) {
        case 1: // Взойти на корабль
          if (player.isTransformed()) {
            player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_TRANSFORMED);
            return null;
          }
          if (player.isParalyzed()) {
            player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_PETRIFIED);
            return null;
          }
          if (player.isDead() || player.isFakeDeath()) {
            player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_DEAD);
            return null;
          }
          if (player.isFishing()) {
            player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_FISHING);
            return null;
          }
          if (player.isInCombat()) {
            player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_IN_BATTLE);
            return null;
          }
          if (player.isInDuel()) {
            player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_IN_A_DUEL);
            return null;
          }
          if (player.isSitting()) {
            player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_SITTING);
            return null;
          }
          if (player.isCastingNow()) {
            player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_CASTING);
            return null;
          }
          if (player.isCursedWeaponEquipped()) {
            player.sendPacket(
                SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_A_CURSED_WEAPON_IS_EQUIPPED);
            return null;
          }
          if (player.isCombatFlagEquipped()) {
            player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_HOLDING_A_FLAG);
            return null;
          }
          if (!player.getPets().isEmpty() || player.isMounted()) {
            player.sendPacket(
                SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_A_PET_OR_A_SERVITOR_IS_SUMMONED);
            return null;
          }
          if (player.isFlyingMounted()) {
            player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_NOT_MEET_REQUEIREMENTS);
            return null;
          }

          if (_dockedShip != null) {
            _dockedShip.addPassenger(player);
          }
          break;
        case 2: // Призвать корабль
          if (_dockedShip != null) {
            if (_dockedShip.isOwner(player)) {
              player.sendPacket(SystemMessageId.THE_AIRSHIP_IS_ALREADY_EXISTS);
            }
            return null;
          }
          if (_isBusy) {
            player.sendPacket(SystemMessageId.ANOTHER_AIRSHIP_ALREADY_SUMMONED);
            return null;
          }
          if ((player.getClanPrivileges() & L2Clan.CP_CL_SUMMON_AIRSHIP)
              != L2Clan.CP_CL_SUMMON_AIRSHIP) {
            player.sendPacket(SystemMessageId.THE_AIRSHIP_NO_PRIVILEGES);
            return null;
          }
          ownerId = player.getClanId();
          if (!AirShipManager.getInstance().hasAirShipLicense(ownerId)) {
            player.sendPacket(SystemMessageId.THE_AIRSHIP_NEED_LICENSE_TO_SUMMON);
            return null;
          }
          if (AirShipManager.getInstance().hasAirShip(ownerId)) {
            player.sendPacket(SystemMessageId.THE_AIRSHIP_ALREADY_USED);
            return null;
          }
          if (!player.destroyItemByItemId(ProcessType.CONSUME, STARSTONE, SUMMON_COST, npc, true)) {
            player.sendPacket(
                SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_NEED_MORE_S1)
                    .addItemName(STARSTONE));
            return null;
          }

          _isBusy = true;
          L2AirShipInstance ship =
              AirShipManager.getInstance()
                  .getNewAirShip(_shipSpawnX, _shipSpawnY, _shipSpawnZ, _shipHeading, ownerId);
          if (ship != null) {
            if (_arrivalPath != null) {
              ship.executePath(_arrivalPath);
            }

            if (_arrivalMessage == null) {
              _arrivalMessage =
                  new NS(
                      npc.getObjectId(),
                      ChatType.SHOUT,
                      npc.getNpcId(),
                      NpcStringId
                          .THE_AIRSHIP_HAS_BEEN_SUMMONED_IT_WILL_AUTOMATICALLY_DEPART_IN_5_MINUTES);
            }

            npc.broadcastPacket(_arrivalMessage);
          } else {
            _isBusy = false;
          }
          break;
        case 3: // Подать заявку
          if (player.getClan() == null || player.getClan().getLevel() < 5) {
            player.sendPacket(SystemMessageId.THE_AIRSHIP_NEED_CLANLVL_5_TO_SUMMON);
            return null;
          }
          if (!player.isClanLeader()) {
            player.sendPacket(SystemMessageId.THE_AIRSHIP_NO_PRIVILEGES);
            return null;
          }
          ownerId = player.getClanId();
          if (AirShipManager.getInstance().hasAirShipLicense(ownerId)) {
            player.sendPacket(SystemMessageId.THE_AIRSHIP_SUMMON_LICENSE_ALREADY_ACQUIRED);
            return null;
          }
          if (!player.destroyItemByItemId(ProcessType.CONSUME, LICENSE, 1, npc, true)) {
            player.sendPacket(
                SystemMessage.getSystemMessage(SystemMessageId.THE_AIRSHIP_NEED_MORE_S1)
                    .addItemName(STARSTONE));
            return null;
          }

          AirShipManager.getInstance().registerLicense(ownerId);
          player.sendPacket(SystemMessageId.THE_AIRSHIP_SUMMON_LICENSE_ENTERED);
          break;
      }
    } else if (ask == -2011) {
      switch (reply) {
        case 1: // Отправиться в Семя Бессмертия
          player.teleToLocation(-212808, 209672, 4257);
          return null;
        case 2: // Отправиться в Семя Разрушения
          player.teleToLocation(-248536, 250280, 4311);
          return null;
        case 3: // Отправиться в Семя Уничтожения
          player.teleToLocation(-175512, 154488, 2689);
          return null;
        case 4:
          player.teleToLocation(-149406, 255247, -80);
          return null;
        case 5: // Отправиться в Семя Индустриализции
          if (player.getLevel() >= 95) {
            player.teleToLocation(-147348, 152615, -14048);
            return null;
          }
      }
    }
    return null;
  }
  public GameServerStartup() throws Exception {
    long serverLoadStart = System.currentTimeMillis();

    gameServer = this;

    printSection("Database Engine");
    L2DatabaseFactory.getInstance();

    printSection("IDFactory Engine");
    IdFactory.getInstance();
    _log.log(Level.INFO, "IdFactory: Free ObjectID's remaining: " + IdFactory.getInstance().size());

    ThreadPoolManager.getInstance();

    printSection("Engines");
    ScriptsManager.getInstance();
    ServerPacketOpCodeManager.getInstance();

    printSection("World Engine");
    Colors.loadColors();
    GameTimeController.init();
    InstanceManager.getInstance();
    WorldManager.getInstance();
    MapRegionManager.getInstance();
    Announcements.getInstance();
    GlobalVariablesManager.getInstance();
    AccountShareDataTable.getInstance();
    DynamicSpawnData.getInstance();
    ResidenceFunctionData.getInstance();

    printSection("Skills Engine");
    BuffStackGroupData.getInstance();
    EnchantSkillGroupsTable.getInstance();
    SkillTable.getInstance().load(false);
    SkillTreesData.getInstance();

    printSection("Items Engine");
    ItemTable.getInstance().loadClient();
    ItemTable.getInstance().load(false);
    SummonItemsData.getInstance();
    EnchantBonusData.getInstance();
    BuyListData.getInstance();
    MultiSellData.getInstance();
    RecipeData.getInstance();
    // PrimeShopTable.getInstance(); TODO
    ArmorSetsTable.getInstance();
    FishData.getInstance();
    FishingRodsData.getInstance();
    EnchantItemData.getInstance();
    EnchantEffectTable.getInstance();
    CrystallizationData.getInstance();
    SoulCrystalData.getInstance();
    ShapeShiftingItemsData.getInstance();
    HennaTable.getInstance();
    HennaTreeTable.getInstance();
    AugmentationData.getInstance();
    ItemPriceData.getInstance();
    AbilityPointsData.getInstance();
    AlchemyDataTable.getInstance();

    printSection("Characters Engine");
    CharTemplateTable.getInstance();
    ClassTemplateTable.getInstance();
    CharNameTable.getInstance();
    ExperienceTable.getInstance();
    AdminTable.getInstance();
    RaidBossPointsManager.getInstance();
    RelationListManager.getInstance();
    PetDataTable.getInstance();
    CharSummonTable.getInstance();
    SummonPointsTable.getInstance();
    HitConditionBonus.getInstance();
    ObsceneFilterTable.getInstance();

    printSection("Clans Engine");
    ClanTable.getInstance();
    ClanTable.getInstance().restoreWars();
    ClanHallSiegeManager.getInstance();
    ClanHallManager.getInstance();
    AuctionManager.getInstance();

    printSection("Geodata Engine");
    GeoEngine.init();
    PathFinding.init();
    DoorGeoEngine.init();

    printSection("NPCs Engine");
    HerbDropTable.getInstance();
    NpcTable.getInstance();
    AutoChatDataTable.getInstance();
    NpcWalkerRoutesData.getInstance();
    WalkingManager.getInstance();
    ZoneManager.getInstance();
    StaticObjectsData.getInstance();
    ItemAuctionManager.getInstance();
    CastleManager.getInstance();
    FortManager.getInstance().init();
    SpawnTable.getInstance();
    AutoSpawnHandler.getInstance();
    HellboundManager.getInstance();
    RaidBossSpawnManager.getInstance();
    DayNightSpawnManager.getInstance().trim().notifyChangeMode();
    GrandBossManager.getInstance().initZones();
    FourSepulchersManager.getInstance().init();
    TeleportListTable.getInstance();
    BeautyShopData.getInstance();
    CustomDropListDataXml.getInstance();

    printSection("Residence Siege Engine");
    CastleSiegeManager.getInstance().getSieges();
    FortSpawnList.getInstance();
    FortSiegeManager.getInstance();
    CastleManorManager.getInstance();
    CastleMercTicketManager.getInstance();
    ManorData.getInstance();
    ResidenceSiegeMusicList.getInstance();

    printSection("Olympiad Engine");
    Olympiad.getInstance();
    HeroManager.getInstance();

    printSection("Cache Engine");
    CrestCache.getInstance();
    HtmCache.getInstance();

    PartyMatchWaitingList.getInstance();
    PartyMatchRoomList.getInstance();
    PetitionManager.getInstance();
    CursedWeaponsManager.getInstance();
    CommunityBuffTable.getInstance();
    CommunityTeleportData.getInstance();

    printSection("Mods Engine");
    PcCafePointsManager.getInstance();

    if (Config.MMO_TOP_MANAGER_ENABLED) {
      MMOTopManager.getInstance();
    }
    if (Config.L2_TOP_MANAGER_ENABLED) {
      L2TopManager.getInstance();
    }

    printSection("Handlers Engine");
    ActionHandler.getInstance();
    ActionShiftHandler.getInstance();
    AdminCommandHandler.getInstance();
    BypassCommandManager.getInstance();
    ChatCommandManager.getInstance();
    EffectHandler.getInstance();
    ItemHandler.getInstance();
    SkillHandler.getInstance();
    TargetHandler.getInstance();
    TransformHandler.getInstance();
    UserCommandManager.getInstance();
    VoicedHandlerManager.getInstance();

    printSection("Transformations Engine");
    TransformationManager.getInstance();
    TransformationManager.getInstance().report();

    printSection("Jump Engine");
    CharJumpRoutesTable.getInstance();

    printSection("Commission Engine");
    CommissionManager.getInstance();

    printSection("ClanSearch Engine");
    ClanSearchManager.getInstance();

    printSection("Awakening Engine");
    AwakeningManager.getInstance();

    printSection("World Statistics Engine");
    if (ConfigWorldStatistic.WORLD_STATISTIC_ENABLED) {
      WorldStatisticsManager.getInstance();
    } else {
      _log.log(Level.INFO, "World Statistic Engine Disabled");
    }

    printSection("Quests Engine");
    QuestManager.getInstance();
    DynamicQuestManager.getInstance();
    BoatManager.getInstance();
    AirShipManager.getInstance();
    ShuttleManager.getInstance();
    GraciaSeedsManager.getInstance();
    if (Config.ALLOW_WEDDING) {
      WeddingManager.getInstance();
    }
    AutoChatDataTable.getInstance().setAutoChatActive(true);

    printSection("Scripts Engine");
    ScriptsManager.getInstance().executeCoreScripts();

    TaskManager.getInstance();

    QuestManager.getInstance().report();

    if (Config.SAVE_DROPPED_ITEM) {
      ItemsOnGroundManager.getInstance();
    }

    if (Config.AUTODESTROY_ITEM_AFTER > 0 || Config.HERB_AUTO_DESTROY_TIME > 0) {
      ItemsOnGroundAutoDestroyManager.getInstance();
    }

    CastleManager.getInstance().spawnDoors();
    FortManager.getInstance().spawnDoors();

    if (Config.ALLOW_MAIL) {
      MailManager.getInstance();
    }

    MentorManager.getInstance();
    DuelManager.getInstance();

    Runtime.getRuntime().addShutdownHook(GameServerShutdown.getInstance());

    _log.log(Level.INFO, "IdFactory: Free ObjectID's remaining: " + IdFactory.getInstance().size());

    EventManager.getEventsInstances();

    KnownListUpdateTaskManager.getInstance();

    if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS) {
      OfflineTradersTable.restoreOfflineTraders();
    }

    if (Config.DEADLOCK_DETECTOR) {
      _deadDetectThread = new DeadLockDetector();
      _deadDetectThread.setDaemon(true);
      _deadDetectThread.start();
    } else {
      _deadDetectThread = null;
    }

    printSection("Finalization");
    System.runFinalization();
    System.gc();
    Util.printMemoryInfo();
    Util.printCpuInfo();
    Util.printOSInfo();
    Toolkit.getDefaultToolkit().beep();

    printSection("Server Thread");
    LoginServerThread.getInstance().start();

    SelectorConfig sc = new SelectorConfig();
    sc.MAX_READ_PER_PASS = Config.MMO_MAX_READ_PER_PASS;
    sc.MAX_SEND_PER_PASS = Config.MMO_MAX_SEND_PER_PASS;
    sc.SLEEP_TIME = Config.MMO_SELECTOR_SLEEP_TIME;
    sc.HELPER_BUFFER_COUNT = Config.MMO_HELPER_BUFFER_COUNT;
    sc.TCP_NODELAY = Config.MMO_TCP_NODELAY;

    _gamePacketHandler = new L2GamePacketHandler();
    _selectorThread =
        new SelectorThread<>(
            sc, _gamePacketHandler, _gamePacketHandler, _gamePacketHandler, new IPv4Filter());

    InetAddress bindAddress = null;
    if (!Config.GAMESERVER_HOSTNAME.equals("*")) {
      try {
        bindAddress = InetAddress.getByName(Config.GAMESERVER_HOSTNAME);
      } catch (UnknownHostException e1) {
        _log.log(
            Level.ERROR,
            "GameServerStartup: The GameServer bind address is invalid, using all avaliable IPs. Reason: "
                + e1.getMessage(),
            e1);
      }
    }

    try {
      _selectorThread.openServerSocket(bindAddress, Config.PORT_GAME);
    } catch (IOException e) {
      _log.log(
          Level.FATAL,
          "GameServerStartup:: Failed to open server socket. Reason: " + e.getMessage(),
          e);
      System.exit(1);
    }
    _selectorThread.start();
    _log.log(Level.INFO, "Maximum Numbers of Connected Players: " + Config.MAXIMUM_ONLINE_USERS);
    long serverLoadEnd = System.currentTimeMillis();
    _log.log(
        Level.INFO, "Server Loaded in " + (serverLoadEnd - serverLoadStart) / 1000L + " seconds");

    AutoAnnounceTaskManager.getInstance();

    XMLRPCServer.getInstance();
  }
  protected void validityCheck() {
    L2ScriptZone zone = ZoneManager.getInstance().getZoneById(_dockZone, L2ScriptZone.class);
    if (zone == null) {
      _log.log(Level.WARN, getName() + ": Invalid zone " + _dockZone + ", controller disabled");
      _isBusy = true;
      return;
    }

    VehiclePathPoint p;
    if (_arrivalPath != null) {
      if (_arrivalPath.length == 0) {
        _log.log(Level.WARN, getName() + ": Zero arrival path length.");
        _arrivalPath = null;
      } else {
        p = _arrivalPath[_arrivalPath.length - 1];
        if (!zone.isInsideZone(p.x, p.y, p.z)) {
          _log.log(
              Level.WARN,
              getName()
                  + ": Arrival path finish point ("
                  + p.x
                  + ','
                  + p.y
                  + ','
                  + p.z
                  + ") not in zone "
                  + _dockZone);
          _arrivalPath = null;
        }
      }
    }
    if (_arrivalPath == null) {
      if (!ZoneManager.getInstance()
          .getZoneById(_dockZone, L2ScriptZone.class)
          .isInsideZone(_shipSpawnX, _shipSpawnY, _shipSpawnZ)) {
        _log.log(
            Level.WARN,
            getName()
                + ": Arrival path is null and spawn point not in zone "
                + _dockZone
                + ", controller disabled");
        _isBusy = true;
        return;
      }
    }

    if (_departPath != null) {
      if (_departPath.length == 0) {
        _log.log(Level.WARN, getName() + ": Zero depart path length.");
        _departPath = null;
      } else {
        p = _departPath[_departPath.length - 1];
        if (zone.isInsideZone(p.x, p.y, p.z)) {
          _log.log(
              Level.WARN,
              getName()
                  + ": Departure path finish point ("
                  + p.x
                  + ','
                  + p.y
                  + ','
                  + p.z
                  + ") in zone "
                  + _dockZone);
          _departPath = null;
        }
      }
    }

    if (_teleportsTable != null) {
      if (_fuelTable == null) {
        _log.log(Level.WARN, getName() + ": Fuel consumption not defined.");
      } else {
        if (_teleportsTable.length == _fuelTable.length) {
          AirShipManager.getInstance()
              .registerAirShipTeleportList(_dockZone, _locationId, _teleportsTable, _fuelTable);
        } else {
          _log.log(Level.WARN, getName() + ": Fuel consumption not match teleport list.");
        }
      }
    }
  }