public void cancelRegisteredItem(Player player, int brokerItemId) {
    if (player.getInventory().isFull()) {
      PacketSendUtility.sendPacket(player, new SM_SYSTEM_MESSAGE(901298));
      return;
    }
    int playerId = player.getObjectId();
    Map<Integer, BrokerItem> brokerItems = getRaceBrokerItems(player.getCommonData().getRace());
    BrokerItem brokerItem = brokerItems.get(brokerItemId);

    if (brokerItem == null) return;
    if (playerId != brokerItem.getSellerId()) {
      Logger.getLogger(this.getClass())
          .info(
              "[AUDIT]Player: "
                  + player.getName()
                  + " is trying to steal: "
                  + brokerItem.getItemId()
                  + " => Hacking!");
      return;
    }
    synchronized (brokerItem) {
      if (brokerItem != null) {
        Item item = player.getInventory().putToBag(brokerItem.getItem());
        PacketSendUtility.sendPacket(player, new SM_INVENTORY_UPDATE(item, true));
        PacketSendUtility.sendPacket(player, new SM_BROKER_ITEMS(brokerItemId, 4));
        brokerItem.setPersistentState(PersistentState.DELETED);
        saveManager.add(new BrokerOpSaveTask(brokerItem));
        brokerItems.remove(brokerItemId);
      }
      showRegisteredItems(player);
    }
  }
  private void initBrokerService() {
    int loadedBrokerItemsCount = 0;
    int loadedSettledItemsCount = 0;

    List<BrokerItem> brokerItems = DAOManager.getDAO(BrokerDAO.class).loadBroker();

    for (BrokerItem item : brokerItems) {
      if (item.getItemBrokerRace() == BrokerRace.ASMODIAN) {
        if (item.isSettled()) {
          asmodianSettledItems.put(item.getItemUniqueId(), item);
          loadedSettledItemsCount++;
        } else {
          asmodianBrokerItems.put(item.getItemUniqueId(), item);
          loadedBrokerItemsCount++;
        }
      } else if (item.getItemBrokerRace() == BrokerRace.ELYOS) {
        if (item.isSettled()) {
          elyosSettledItems.put(item.getItemUniqueId(), item);
          loadedSettledItemsCount++;
        } else {
          elyosBrokerItems.put(item.getItemUniqueId(), item);
          loadedBrokerItemsCount++;
        }
      }
    }

    log.info("Loaded " + loadedBrokerItemsCount + " Broker Items");
    log.info("Loaded " + loadedSettledItemsCount + " Settled Items");
    log.info("Broker loaded successfully");
  }
  private BrokerItem[] getItemsByMask(Player player, int clientMask, boolean cached) {
    List<BrokerItem> searchItems = new ArrayList<BrokerItem>();

    BrokerItemMask brokerMask = BrokerItemMask.getBrokerMaskById(clientMask);

    if (cached) {
      BrokerItem[] brokerItems = getFilteredItems(player);
      if (brokerItems == null) return null;

      for (BrokerItem item : brokerItems) {
        if (item == null || item.getItem() == null || item.isSold()) continue;

        if (brokerMask.isMatches(item.getItem())) {
          searchItems.add(item);
        }
      }
    } else {
      Map<Integer, BrokerItem> brokerItems = getRaceBrokerItems(player.getCommonData().getRace());
      if (brokerItems == null) return null;
      for (BrokerItem item : brokerItems.values()) {
        if (item == null || item.getItem() == null || item.isSold()) continue;

        if (brokerMask.isMatches(item.getItem())) {
          searchItems.add(item);
        }
      }
    }

    BrokerItem[] items = searchItems.toArray(new BrokerItem[searchItems.size()]);
    getPlayerCache(player).setBrokerListCache(items);
    getPlayerCache(player).setBrokerMaskCache(clientMask);

    return items;
  }
 private BrokerPlayerCache getPlayerCache(Player player) {
   BrokerPlayerCache cacheEntry = playerBrokerCache.get(player.getObjectId());
   if (cacheEntry == null) {
     cacheEntry = new BrokerPlayerCache();
     playerBrokerCache.put(player.getObjectId(), cacheEntry);
   }
   return cacheEntry;
 }
  public void showRegisteredItems(Player player) {
    Map<Integer, BrokerItem> brokerItems = getRaceBrokerItems(player.getCommonData().getRace());

    List<BrokerItem> registeredItems = new ArrayList<BrokerItem>();
    int playerId = player.getObjectId();

    for (BrokerItem item : brokerItems.values()) {
      if (item != null
          && item.getItem() != null
          && !item.isSold()
          && !item.isSettled()
          && playerId == item.getSellerId()) registeredItems.add(item);
    }

    PacketSendUtility.sendPacket(
        player,
        new SM_BROKER_ITEMS(registeredItems.toArray(new BrokerItem[registeredItems.size()]), 1));
  }
  private void putToSettled(Race race, BrokerItem brokerItem, boolean isSold) {
    if (isSold) brokerItem.removeItem();
    else brokerItem.setSettled();

    brokerItem.setPersistentState(PersistentState.UPDATE_REQUIRED);

    switch (race) {
      case ASMODIANS:
        asmodianSettledItems.put(brokerItem.getItemUniqueId(), brokerItem);
        break;

      case ELYOS:
        elyosSettledItems.put(brokerItem.getItemUniqueId(), brokerItem);
        break;
    }

    Player seller = World.getInstance().findPlayer(brokerItem.getSellerId());

    saveManager.add(new BrokerOpSaveTask(brokerItem));

    if (seller != null) {
      Map<Integer, BrokerItem> brokerSettledItems =
          getRaceBrokerSettledItems(seller.getCommonData().getRace());

      int playerId = seller.getObjectId();

      List<BrokerItem> settledItems = new ArrayList<BrokerItem>();

      long totalKinah = 0;

      for (BrokerItem item : brokerSettledItems.values()) {
        if (item != null && playerId == item.getSellerId()) {
          settledItems.add(item);

          if (item.isSold()) totalKinah += item.getPrice();
        }
      }

      DescriptionId desId = new DescriptionId(brokerItem.getItem().getNameID());
      PacketSendUtility.sendPacket(seller, new SM_SYSTEM_MESSAGE(1301047, desId));
      showRegisteredItems(seller);
      PacketSendUtility.sendPacket(seller, new SM_BROKER_ITEMS(null, totalKinah, 2, 5));
    }
  }
  public void showRequestedItems(
      Player player,
      int clientMask,
      int sortType,
      int startPage,
      List<Integer> searchItemsId,
      boolean search) {
    BrokerItem[] searchItems = null;
    int playerBrokerMaskCache = getPlayerMask(player);
    BrokerItemMask brokerMaskById = BrokerItemMask.getBrokerMaskById(clientMask);
    boolean isChidrenMask = brokerMaskById.isChildrenMask(playerBrokerMaskCache);
    if (search && searchItemsId != null && clientMask == 0) {
      Map<Integer, BrokerItem> brokerItems = getRaceBrokerItems(player.getCommonData().getRace());
      if (brokerItems == null) return;
      searchItems = brokerItems.values().toArray(new BrokerItem[brokerItems.values().size()]);
    } else if (getFilteredItems(player).length == 0 || !isChidrenMask) {
      searchItems = getItemsByMask(player, clientMask, false);
    } else if (isChidrenMask) {
      searchItems = getItemsByMask(player, clientMask, true);
    } else searchItems = getFilteredItems(player);

    if (searchItems == null || searchItems.length < 0) return;

    int totalSearchItemsCount = searchItems.length;

    getPlayerCache(player).setBrokerSortTypeCache(sortType);
    getPlayerCache(player).setBrokerStartPageCache(startPage);

    if (search && searchItemsId != null) {
      List<BrokerItem> itemsFound = new ArrayList<BrokerItem>();
      for (BrokerItem item : searchItems) {
        if (searchItemsId.contains(item.getItemId())) itemsFound.add(item);
      }
      getPlayerCache(player).setSearchItemsId(searchItemsId);
      searchItems = itemsFound.toArray(new BrokerItem[itemsFound.size()]);
    } else getPlayerCache(player).setSearchItemsId(null);

    sortBrokerItems(searchItems, sortType);
    searchItems = getRequestedPage(searchItems, startPage);

    PacketSendUtility.sendPacket(
        player, new SM_BROKER_ITEMS(searchItems, totalSearchItemsCount, startPage));
  }
  private void checkExpiredItems() {
    Map<Integer, BrokerItem> asmoBrokerItems = getRaceBrokerItems(Race.ASMODIANS);
    Map<Integer, BrokerItem> elyosBrokerItems = getRaceBrokerItems(Race.ELYOS);

    Timestamp currentTime = new Timestamp(Calendar.getInstance().getTimeInMillis());

    for (BrokerItem item : asmoBrokerItems.values()) {
      if (item != null && item.getExpireTime().getTime() <= currentTime.getTime()) {
        expireItem(Race.ASMODIANS, item);
        asmodianBrokerItems.remove(item.getItemUniqueId());
      }
    }

    for (BrokerItem item : elyosBrokerItems.values()) {
      if (item != null && item.getExpireTime().getTime() <= currentTime.getTime()) {
        expireItem(Race.ELYOS, item);
        this.elyosBrokerItems.remove(item.getItemUniqueId());
      }
    }
  }
  public void onPlayerLogin(Player player) {
    Map<Integer, BrokerItem> brokerSettledItems =
        getRaceBrokerSettledItems(player.getCommonData().getRace());

    int playerId = player.getObjectId();

    List<BrokerItem> settledItems = new ArrayList<BrokerItem>();

    long totalKinah = 0;

    for (BrokerItem item : brokerSettledItems.values()) {
      if (item != null && playerId == item.getSellerId()) {
        settledItems.add(item);

        if (item.isSold()) totalKinah += item.getPrice();
      }
    }

    PacketSendUtility.sendPacket(player, new SM_BROKER_ITEMS(null, totalKinah, 1, 5));
    if (totalKinah > 0) PacketSendUtility.sendPacket(player, new SM_SYSTEM_MESSAGE(1400131));
  }
  public void showSettledItems(Player player) {
    Map<Integer, BrokerItem> brokerSettledItems =
        getRaceBrokerSettledItems(player.getCommonData().getRace());

    List<BrokerItem> settledItems = new ArrayList<BrokerItem>();

    int playerId = player.getObjectId();
    long totalKinah = 0;

    for (BrokerItem item : brokerSettledItems.values()) {
      if (item != null && playerId == item.getSellerId()) {
        settledItems.add(item);

        if (item.isSold()) totalKinah += item.getPrice();
      }
    }

    PacketSendUtility.sendPacket(
        player,
        new SM_BROKER_ITEMS(
            settledItems.toArray(new BrokerItem[settledItems.size()]), totalKinah, 0, 5));
  }
 public void removePlayerCache(Player player) {
   playerBrokerCache.remove(player.getObjectId());
 }
  public void settleAccount(Player player) {
    Race playerRace = player.getCommonData().getRace();
    Map<Integer, BrokerItem> brokerSettledItems = getRaceBrokerSettledItems(playerRace);
    List<BrokerItem> collectedItems = new ArrayList<BrokerItem>();
    int playerId = player.getObjectId();
    long kinahCollect = 0;
    boolean itemsLeft = false;

    for (BrokerItem item : brokerSettledItems.values()) {
      if (item.getSellerId() == playerId) collectedItems.add(item);
    }

    for (BrokerItem item : collectedItems) {
      if (item.isSold()) {
        boolean result = false;
        switch (playerRace) {
          case ASMODIANS:
            result = asmodianSettledItems.remove(item.getItemUniqueId()) != null;
            break;
          case ELYOS:
            result = elyosSettledItems.remove(item.getItemUniqueId()) != null;
            break;
        }

        if (result) {
          item.setPersistentState(PersistentState.DELETED);
          saveManager.add(new BrokerOpSaveTask(item));
          kinahCollect += item.getPrice();
        }
      } else {
        if (item.getItem() != null) {
          Item resultItem = player.getInventory().putToBag(item.getItem());
          if (resultItem != null) {
            boolean result = false;
            switch (playerRace) {
              case ASMODIANS:
                result = asmodianSettledItems.remove(item.getItemUniqueId()) != null;
                break;
              case ELYOS:
                result = elyosSettledItems.remove(item.getItemUniqueId()) != null;
                break;
            }

            if (result) {
              item.setPersistentState(PersistentState.DELETED);
              saveManager.add(new BrokerOpSaveTask(item));
              PacketSendUtility.sendPacket(
                  player, new SM_INVENTORY_UPDATE(Collections.singletonList(resultItem)));
            }
          } else itemsLeft = true;

        } else log.warn("Broker settled item missed. ObjID: " + item.getItemUniqueId());
      }
    }

    player.getInventory().increaseKinah(kinahCollect);

    showSettledItems(player);

    if (!itemsLeft) PacketSendUtility.sendPacket(player, new SM_BROKER_ITEMS(6));
  }
  public void registerItem(Player player, int itemUniqueId, long price, int itemCount) {
    Map<Integer, BrokerItem> brokerItems = getRaceBrokerItems(player.getCommonData().getRace());

    List<BrokerItem> registeredItems = new ArrayList<BrokerItem>();
    int playerId = player.getObjectId();

    for (BrokerItem item : brokerItems.values()) {
      if (item != null
          && item.getItem() != null
          && !item.isSold()
          && !item.isSettled()
          && playerId == item.getSellerId()) registeredItems.add(item);
    }

    if (registeredItems.size() >= 15) {
      PacketSendUtility.sendPacket(player, new SM_SYSTEM_MESSAGE(1300653));
      return;
    }

    Item itemToRegister = player.getInventory().getItemByObjId(itemUniqueId);
    Race playerRace = player.getCommonData().getRace();

    if (itemToRegister == null) return;

    if (!itemToRegister.getItemTemplate().isTradeable()) {
      PacketSendUtility.sendPacket(player, new SM_SYSTEM_MESSAGE(1300652));
      return;
    }

    if (itemToRegister.isSoulBound()) return;

    BrokerRace brRace;

    if (playerRace == Race.ASMODIANS) brRace = BrokerRace.ASMODIAN;
    else if (playerRace == Race.ELYOS) brRace = BrokerRace.ELYOS;
    else return;

    double priceRate = player.getPrices().getGlobalPrices(player.getCommonData().getRace()) * .01;
    double taxRate = player.getPrices().getTaxes(player.getCommonData().getRace()) * .01;
    double priceMod = player.getPrices().getGlobalPricesModifier() * .01;
    double priceFactor = 0.02 * priceRate * taxRate * priceMod;
    long registrationCommition =
        (long) (price * priceFactor * (registeredItems.size() >= 10 ? 2 : 1));

    if (registrationCommition < 10) registrationCommition = 10;

    if (player.getInventory().getKinahItem().getItemCount() < registrationCommition) {
      PacketSendUtility.sendPacket(player, new SM_SYSTEM_MESSAGE(1300647));
      return;
    }

    if (itemCount < itemToRegister.getItemCount() && itemCount > 0) {
      Item newItem =
          ItemService.newItem(
              itemToRegister.getItemTemplate().getTemplateId(),
              itemCount,
              itemToRegister.getCrafterName(),
              playerId,
              itemToRegister.getTempItemTimeLeft(),
              itemToRegister.getTempTradeTimeLeft());
      player.getInventory().decreaseItemCount(itemToRegister, itemCount);
      PacketSendUtility.sendPacket(player, new SM_UPDATE_ITEM(itemToRegister));
      itemToRegister = newItem;
    } else {
      boolean removeResult = player.getInventory().removeFromBag(itemToRegister, false);
      if (!removeResult) return;
      PacketSendUtility.sendPacket(player, new SM_DELETE_ITEM(itemToRegister.getObjectId()));
    }

    boolean decreaseResult = player.getInventory().decreaseKinah(registrationCommition);
    if (!decreaseResult) return;

    itemToRegister.setItemLocation(126);

    BrokerItem newBrokerItem =
        new BrokerItem(
            player, itemToRegister, price, player.getName(), player.getObjectId(), brRace);

    switch (brRace) {
      case ASMODIAN:
        asmodianBrokerItems.put(newBrokerItem.getItemUniqueId(), newBrokerItem);
        break;

      case ELYOS:
        elyosBrokerItems.put(newBrokerItem.getItemUniqueId(), newBrokerItem);
        break;
    }

    BrokerOpSaveTask bost =
        new BrokerOpSaveTask(
            newBrokerItem,
            itemToRegister,
            player.getInventory().getKinahItem(),
            player.getObjectId());
    saveManager.add(bost);

    BrokerItem[] brokerItem = new BrokerItem[1];
    brokerItem[0] = newBrokerItem;
    PacketSendUtility.sendPacket(
        player, new SM_BROKER_ITEMS(brokerItem, registeredItems.size() + 1, 3));
  }