@Override
 public boolean onDialogSelect(Player player, int dialogId, int questId, int extendedRewardIndex) {
   QuestEnv env = new QuestEnv(getOwner(), player, questId, dialogId);
   env.setExtendedRewardIndex(extendedRewardIndex);
   checkEntryConditions(player, dialogId, questId);
   if (QuestEngine.getInstance().onDialog(env)) {
     return true;
   }
   return true;
 }
  private void checkDialog(Player player) {
    int npcId = getNpcId();
    List<Integer> relatedQuests = QuestEngine.getInstance().getQuestNpc(npcId).getOnTalkEvent();
    boolean playerHasQuest = false;
    boolean playerCanStartQuest = false;
    if (!relatedQuests.isEmpty()) {
      for (int questId : relatedQuests) {
        QuestState qs = player.getQuestStateList().getQuestState(questId);
        if (qs != null
            && (qs.getStatus() == QuestStatus.START || qs.getStatus() == QuestStatus.REWARD)) {
          playerHasQuest = true;
          break;
        } else if (qs == null || qs.getStatus() == QuestStatus.NONE || qs.canRepeat()) {
          if (QuestService.checkStartConditions(
              new QuestEnv(getOwner(), player, questId, 0), true)) {
            playerCanStartQuest = true;
            continue;
          }
        }
      }
    }

    if (playerHasQuest) {
      boolean isRewardStep = false;
      for (int questId : relatedQuests) {
        QuestState qs = player.getQuestStateList().getQuestState(questId);
        if (qs != null && qs.getStatus() == QuestStatus.REWARD) {
          PacketSendUtility.sendPacket(
              player, new SM_DIALOG_WINDOW(getObjectId(), rewardDialogId, questId));
          isRewardStep = true;
          break;
        }
      }
      if (!isRewardStep) {
        PacketSendUtility.sendPacket(player, new SM_DIALOG_WINDOW(getObjectId(), questDialogId));
      }
    } else if (playerCanStartQuest) {
      PacketSendUtility.sendPacket(player, new SM_DIALOG_WINDOW(getObjectId(), startingDialogId));
    } else {
      PacketSendUtility.sendPacket(player, new SM_DIALOG_WINDOW(getObjectId(), 1011, 0));
    }
  }
  /** {@inheritDoc} */
  @Override
  protected void runImpl() {
    Player player = getConnection().getActivePlayer();

    if (player.isProtectionActive()) {
      player.getController().stopProtectionActiveTask();
    }

    Item item = player.getInventory().getItemByObjId(uniqueItemId);
    Item targetItem = player.getInventory().getItemByObjId(targetItemId);
    HouseObject<?> targetHouseObject = null;

    if (item == null) {
      log.warn(
          String.format(
              "CHECKPOINT: null item use action: %d %d", player.getObjectId(), uniqueItemId));
      return;
    }

    if (targetItem == null) targetItem = player.getEquipment().getEquippedItemByObjId(targetItemId);
    if (targetItem == null && player.getHouseRegistry() != null)
      targetHouseObject = player.getHouseRegistry().getObjectByObjId(targetItemId);

    if (item.getItemTemplate().getTemplateId() == 165000001
        && targetItem.getItemTemplate().canExtract()) {
      PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_ITEM_COLOR_ERROR);
      return;
    }

    // check use item multicast delay exploit cast (spam)
    if (player.isCasting()) {
      // PacketSendUtility.sendMessage(this.getOwner(),
      // "You must wait until cast time finished to use skill again.");
      player.getController().cancelCurrentSkill();
      // On retail the item is cancelling the current skill and then procs normally
      // return;
    }

    if (!RestrictionsManager.canUseItem(player, item)) return;

    if (item.getItemTemplate().getRace() != Race.PC_ALL
        && item.getItemTemplate().getRace() != player.getRace()) {
      PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_CANNOT_USE_ITEM_INVALID_RACE);
      return;
    }

    int requiredLevel =
        item.getItemTemplate().getRequiredLevel(player.getCommonData().getPlayerClass());
    if (requiredLevel == -1) {
      PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_CANNOT_USE_ITEM_INVALID_CLASS);
      return;
    }

    if (requiredLevel > player.getLevel()) {
      PacketSendUtility.sendPacket(
          player,
          SM_SYSTEM_MESSAGE.STR_CANNOT_USE_ITEM_TOO_LOW_LEVEL_MUST_BE_THIS_LEVEL(
              item.getNameId(), requiredLevel));
      return;
    }

    HandlerResult result =
        QuestEngine.getInstance().onItemUseEvent(new QuestEnv(null, player, 0, 0), item);
    if (result == HandlerResult.FAILED) return; // don't remove item

    ItemActions itemActions = item.getItemTemplate().getActions();
    ArrayList<AbstractItemAction> actions = new ArrayList<AbstractItemAction>();

    if (itemActions == null) {
      PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_ITEM_IS_NOT_USABLE);
      return;
    }

    for (AbstractItemAction itemAction : itemActions.getItemActions()) {
      // check if the item can be used before placing it on the cooldown list.
      if (targetHouseObject != null && itemAction instanceof IHouseObjectDyeAction) {
        IHouseObjectDyeAction action = (IHouseObjectDyeAction) itemAction;
        if (action != null && action.canAct(player, item, targetHouseObject))
          actions.add(itemAction);
      } else if (itemAction.canAct(player, item, targetItem)) actions.add(itemAction);
    }

    if (actions.size() == 0) {
      PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_ITEM_IS_NOT_USABLE);
      return;
    }

    // Store Item CD in server Player variable.
    // Prevents potion spamming, and relogging to use kisks/aether jelly/long CD items.
    ItemUseLimits limits = item.getItemTemplate().getUseLimits();
    if (player.isItemUseDisabled(limits)) {
      PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_ITEM_CANT_USE_UNTIL_DELAY_TIME);
      return;
    }

    if (limits.getGenderPermitted() != null && limits.getGenderPermitted() != player.getGender()) {
      PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_CANNOT_USE_ITEM_INVALID_GENDER);
      return;
    }
    int useDelay = player.getItemCooldown(item.getItemTemplate());
    if (useDelay > 0) {
      player.addItemCoolDown(
          item.getItemTemplate().getUseLimits().getDelayId(),
          System.currentTimeMillis() + useDelay,
          useDelay / 1000);
    }

    // notify item use observer
    player.getObserveController().notifyItemuseObservers(item);

    for (AbstractItemAction itemAction : actions) {
      if (targetHouseObject != null && itemAction instanceof IHouseObjectDyeAction) {
        IHouseObjectDyeAction action = (IHouseObjectDyeAction) itemAction;
        action.act(player, item, targetHouseObject);
      } else if (type == 6) {

        // Multi Returns Items (Scroll Teleporter)
        if (itemAction instanceof MultiReturnAction) {
          MultiReturnAction action = (MultiReturnAction) itemAction;
          int SelectedMapIndex = returnId;
          action.act(player, item, SelectedMapIndex);
        }
      } else {
        itemAction.act(player, item, targetItem);
      }
    }
    PacketSendUtility.sendPacket(
        player,
        SM_SYSTEM_MESSAGE.STR_USE_ITEM(new DescriptionId(item.getItemTemplate().getNameId())));
  }
  @Override
  protected void runImpl() {
    Player activePlayer = getConnection().getActivePlayer();

    if (activePlayer.getHouseRegistry() != null) sendPacket(new SM_HOUSE_OBJECTS(activePlayer));
    if (activePlayer.isInInstance()) {
      sendPacket(
          new SM_INSTANCE_COUNT_INFO(activePlayer.getWorldId(), activePlayer.getInstanceId()));
    }
    if (activePlayer.getItemEffectId() <= 1) activePlayer.updataItemEffectId();
    sendPacket(new SM_PLAYER_INFO(activePlayer, false));
    activePlayer.getController().startProtectionActiveTask();
    sendPacket(
        new SM_MOTION(activePlayer.getObjectId(), activePlayer.getMotions().getActiveMotions()));

    WindstreamTemplate template =
        DataManager.WINDSTREAM_DATA.getStreamTemplate(activePlayer.getPosition().getMapId());
    Location2D location;
    if (template != null)
      for (int i = 0; i < template.getLocations().getLocation().size(); i++) {
        location = template.getLocations().getLocation().get(i);
        sendPacket(
            new SM_WINDSTREAM_ANNOUNCE(
                location.getFlyPathType().getId(),
                template.getMapid(),
                location.getId(),
                location.getState()));
      }
    location = null;
    template = null;

    /** Spawn player into the world. */
    // If already spawned, despawn before spawning into the world
    if (activePlayer.isSpawned()) World.getInstance().despawn(activePlayer);
    World.getInstance().spawn(activePlayer);

    activePlayer.getController().refreshZoneImpl();

    // because fortress buff should only be avaible in fortress 5011-6011-6021
    SiegeService.getInstance().fortressBuffRemove(activePlayer);

    // SM_SHIELD_EFFECT, SM_ABYSS_ARTIFACT_INFO3
    if (activePlayer.isInSiegeWorld()) {
      SiegeService.getInstance().onEnterSiegeWorld(activePlayer);
    }

    // SM_NPC_INFO
    BaseService.getInstance().onEnterBaseWorld(activePlayer);

    // SM_SERIAL_KILLER
    SerialKillerService.getInstance().onEnterMap(activePlayer);

    // SM_RIFT_ANNOUNCE
    // RiftInformer.sendRiftsInfo(activePlayer);
    InstanceRiftSpawnManager.sendInstanceRiftStatus(activePlayer);

    // SM_UPGRADE_ARCADE
    // sendPacket(new SM_UPGRADE_ARCADE(true));

    // SM_NEARBY_QUESTS
    activePlayer.getController().updateNearbyQuests();

    /** Loading weather for the player's region */
    WeatherService.getInstance().loadWeather(activePlayer);

    QuestEngine.getInstance().onEnterWorld(new QuestEnv(null, activePlayer, 0, 0));

    activePlayer.getController().onEnterWorld();

    // zone channel message (is this must be here?)
    if (!WorldMapType.getWorld(activePlayer.getWorldId()).isPersonal())
      sendPacket(new SM_SYSTEM_MESSAGE(1390122, activePlayer.getPosition().getInstanceId()));

    activePlayer.getEffectController().updatePlayerEffectIcons();
    sendPacket(SM_CUBE_UPDATE.cubeSize(StorageType.CUBE, activePlayer));

    Pet pet = activePlayer.getPet();
    if (pet != null && !pet.isSpawned()) World.getInstance().spawn(pet);
    activePlayer.setPortAnimation(0);

    TownService.getInstance().onEnterWorld(activePlayer);
  }