Package l2p.gameserver.model

Source Code of l2p.gameserver.model.L2TradeList

package l2p.gameserver.model;

import java.util.Collection;
import java.util.concurrent.ConcurrentLinkedQueue;

import l2p.Config;
import l2p.extensions.Stat;
import l2p.extensions.multilang.CustomMessage;
import l2p.gameserver.model.base.Transaction;
import l2p.gameserver.model.items.Inventory;
import l2p.gameserver.model.items.L2ItemInstance;
import l2p.gameserver.serverpackets.SystemMessage;
import l2p.gameserver.tables.ItemTable;
import l2p.util.GArray;
import l2p.util.Log;
import l2p.util.SafeMath;
import l2p.util.Strings;

/**
* Контейнер для приватных магазинов покупки и продажи.
*
* @see Transaction
* @see L2ManufactureList
*/
public class L2TradeList
{
  private final GArray<L2ItemInstance> _items = new GArray<L2ItemInstance>();
  private int _listId;
  private String _buyStoreName, _sellStoreName;

  public L2TradeList(int listId)
  {
    _listId = listId;
  }

  public L2TradeList()
  {
    this(0);
  }

  public void addItem(L2ItemInstance item)
  {
    synchronized(_items)
    {
      _items.add(item);
    }
  }

  public void removeAll()
  {
    _items.clear();
  }

  /**
   * @return Returns the listId.
   */
  public int getListId()
  {
    return _listId;
  }

  public void setSellStoreName(String name)
  {
    _sellStoreName = Strings.stripToSingleLine(name);
  }

  public String getSellStoreName()
  {
    return _sellStoreName;
  }

  public void setBuyStoreName(String name)
  {
    _buyStoreName = Strings.stripToSingleLine(name);
  }

  public String getBuyStoreName()
  {
    return _buyStoreName;
  }

  /**
   * @return Returns the items.
   */
  public GArray<L2ItemInstance> getItems()
  {
    return _items;
  }

  /**
   * Проверяет, есть ли у игрока player в наличии необходимое количество вещей
   */
  public static boolean validateTrade(L2Player player, Collection<TradeItem> items)
  {
    Inventory playersInv = player.getInventory();
    L2ItemInstance playerItem;
    synchronized(items)
    {
      for(TradeItem item : items)
      {
        playerItem = playersInv.getItemByObjectId(item.getObjectId());
        if(playerItem == null || playerItem.getCount() < item.getCount() || playerItem.getEnchantLevel() < item.getEnchantLevel() || !playerItem.canBeTraded(player))
        {
          return false;
        }
      }
      // TODO: добавить проверку на перевес после трейда с учетом отданного
      //if(!playersInv.validateCapacity(_items) || !playersInv.validateWeight(_items))
      //      return false;
    }
    return true;
  }

  public void updateSellList(L2Player player, ConcurrentLinkedQueue<TradeItem> list)
  {
    Inventory playersInv = player.getInventory();
    L2ItemInstance item;
    for(L2ItemInstance temp : _items)
    {
      item = playersInv.getItemByObjectId(temp.getObjectId());
      if(item == null || item.getCount() <= 0)
      {
        for(TradeItem i : list)
        {
          if(i.getObjectId() == temp.getItemId())
          {
            list.remove(i);
            break;
          }
        }
      }
      else if(item.getCount() < temp.getCount())
      {
        temp.setCount(item.getCount());
      }
    }
  }

  public synchronized boolean buySellItems(L2Player buyer, ConcurrentLinkedQueue<TradeItem> listToBuy, L2Player seller, ConcurrentLinkedQueue<TradeItem> listToSell)
  {
    Inventory sellerInv = seller.getInventory();
    Inventory buyerInv = buyer.getInventory();
    TradeItem sellerTradeItem = null;
    L2ItemInstance sellerInventoryItem = null;
    L2ItemInstance TransferItem = null;
    L2ItemInstance temp;
    ConcurrentLinkedQueue<TradeItem> unsold = new ConcurrentLinkedQueue<TradeItem>();
    unsold.addAll(listToSell);
    long cost = 0, amount = 0;
    for(TradeItem buyerTradeItem : listToBuy)
    {
      sellerTradeItem = null;
      for(TradeItem unsoldItem : unsold)
      {
        if(unsoldItem.getItemId() == buyerTradeItem.getItemId() && unsoldItem.getOwnersPrice() == buyerTradeItem.getOwnersPrice())
        {
          sellerTradeItem = unsoldItem;
          break;
        }
      }
      if(sellerTradeItem == null)
      {
        continue;
      }
      sellerInventoryItem = sellerInv.getItemByObjectId(sellerTradeItem.getObjectId());
      unsold.remove(sellerTradeItem);
      if(sellerInventoryItem == null)
      {
        continue;
      }
      long buyerItemCount = buyerTradeItem.getCount();
      long sellerItemCount = sellerTradeItem.getCount();
      if(sellerItemCount > sellerInventoryItem.getCount())
      {
        sellerItemCount = sellerInventoryItem.getCount();
      }
      if(seller.getPrivateStoreType() == L2Player.STORE_PRIVATE_SELL || seller.getPrivateStoreType() == L2Player.STORE_PRIVATE_SELL_PACKAGE)
      {
        if(buyerItemCount > sellerItemCount)
        {
          buyerTradeItem.setCount(sellerItemCount);
        }
        if(buyerItemCount > sellerInventoryItem.getCount())
        {
          buyerTradeItem.setCount(sellerInventoryItem.getCount());
        }
        buyerItemCount = buyerTradeItem.getCount();
        amount = buyerItemCount;
        cost = amount * sellerTradeItem.getOwnersPrice();
      }
      if(buyer.getPrivateStoreType() == L2Player.STORE_PRIVATE_BUY)
      {
        if(sellerItemCount > buyerItemCount)
        {
          sellerTradeItem.setCount(buyerItemCount);
        }
        if(sellerItemCount > sellerInventoryItem.getCount())
        {
          sellerTradeItem.setCount(sellerInventoryItem.getCount());
        }
        sellerItemCount = sellerTradeItem.getCount();
        amount = sellerItemCount;
        cost = amount * buyerTradeItem.getOwnersPrice();
      }
      if(buyer.getAdena() < cost)
      {
        return false;
      }
      try
      {
        SafeMath.safeMulLong(buyerItemCount, buyerTradeItem.getOwnersPrice());
        SafeMath.safeMulLong(sellerItemCount, sellerTradeItem.getOwnersPrice());
      }
      catch(ArithmeticException e)
      {
        return false;
      }
      TransferItem = sellerInv.dropItem(sellerInventoryItem.getObjectId(), amount, false);
      Log.LogItem(seller, buyer, Log.PrivateStoreSell, TransferItem, amount);
      buyer.reduceAdena(cost, false);
      seller.addAdena(cost);
      int tax = (int) (cost * Config.SERVICES_TRADE_TAX / 100);
      if(seller.isInZone(L2Zone.ZoneType.offshore))
      {
        tax = (int) (cost * Config.SERVICES_OFFSHORE_TRADE_TAX / 100);
      }
      if(Config.SERVICES_TRADE_TAX_ONLY_OFFLINE && !seller.isInOfflineMode())
      {
        tax = 0;
      }
      if(seller.getReflection().getId() == -1) // Особая зона в Parnassus
      {
        tax = 0;
      }
      if(tax > 0)
      {
        seller.reduceAdena(tax, true);
        Stat.addTax(tax);
        seller.sendMessage(new CustomMessage("trade.HavePaidTax", seller).addNumber(tax));
      }
      temp = buyerInv.addItem(TransferItem);
      Log.LogItem(buyer, seller, Log.PrivateStoreBuy, TransferItem, amount);
      if(!temp.isStackable())
      {
        if(temp.getEnchantLevel() > 0)
        {
          seller.sendPacket(new SystemMessage(SystemMessage._S2S3_HAS_BEEN_SOLD_TO_S1_AT_THE_PRICE_OF_S4_ADENA).addString(buyer.getName()).addNumber(temp.getEnchantLevel()).addItemName(sellerInventoryItem.getItemId()).addNumber(cost));
          buyer.sendPacket(new SystemMessage(SystemMessage._S2S3_HAS_BEEN_PURCHASED_FROM_S1_AT_THE_PRICE_OF_S4_ADENA).addString(seller.getName()).addNumber(temp.getEnchantLevel()).addItemName(sellerInventoryItem.getItemId()).addNumber(cost));
        }
        else
        {
          seller.sendPacket(new SystemMessage(SystemMessage.S2_IS_SOLD_TO_S1_AT_THE_PRICE_OF_S3_ADENA).addString(buyer.getName()).addItemName(sellerInventoryItem.getItemId()).addNumber(cost));
          buyer.sendPacket(new SystemMessage(SystemMessage.S2_HAS_BEEN_PURCHASED_FROM_S1_AT_THE_PRICE_OF_S3_ADENA).addString(seller.getName()).addItemName(sellerInventoryItem.getItemId()).addNumber(cost));
        }
      }
      else
      {
        seller.sendPacket(new SystemMessage(SystemMessage.S2_S3_HAVE_BEEN_SOLD_TO_S1_FOR_S4_ADENA).addString(buyer.getName()).addItemName(sellerInventoryItem.getItemId()).addNumber(amount).addNumber(cost));
        buyer.sendPacket(new SystemMessage(SystemMessage.S3_S2_HAS_BEEN_PURCHASED_FROM_S1_FOR_S4_ADENA).addString(seller.getName()).addItemName(sellerInventoryItem.getItemId()).addNumber(amount).addNumber(cost));
      }
      sellerInventoryItem = null;
    }
    seller.sendChanges();
    buyer.sendChanges();
    updateSellerSellList(listToBuy, seller, listToSell);
    updateBuyerBuyList(buyer, listToBuy, listToSell);
    return true;
  }

  private void updateBuyerBuyList(L2Player buyer, ConcurrentLinkedQueue<TradeItem> listToBuy, ConcurrentLinkedQueue<TradeItem> listToSell)
  {
    GArray<TradeItem> tmp;
    if(buyer.getPrivateStoreType() == L2Player.STORE_PRIVATE_BUY)
    {
      tmp = new GArray<TradeItem>();
      tmp.addAll(buyer.getBuyList());
outer:
      for(TradeItem bl : listToBuy)
      {
        for(TradeItem sl : listToSell)
        {
          if(sl.getItemId() == bl.getItemId() && sl.getOwnersPrice() == bl.getOwnersPrice())
          {
            if(!ItemTable.getInstance().getTemplate(bl.getItemId()).isStackable())
            {
              tmp.remove(bl);
            }
            else
            {
              bl.setCount(bl.getCount() - sl.getCount());
              if(bl.getCount() <= 0)
              {
                tmp.remove(bl);
              }
            }
            listToSell.remove(sl);
            continue outer;
          }
        }
      }
      ConcurrentLinkedQueue<TradeItem> newlist = new ConcurrentLinkedQueue<TradeItem>();
      newlist.addAll(tmp);
      buyer.setBuyList(newlist);
    }
  }

  private void updateSellerSellList(ConcurrentLinkedQueue<TradeItem> listToBuy, L2Player seller, ConcurrentLinkedQueue<TradeItem> listToSell)
  {
    if(seller.getPrivateStoreType() == L2Player.STORE_PRIVATE_SELL_PACKAGE)
    {
      seller.setSellList(null);
      return;
    }
    GArray<TradeItem> tmp;
    if(seller.getPrivateStoreType() == L2Player.STORE_PRIVATE_SELL)
    {
      tmp = new GArray<TradeItem>();
      tmp.addAll(seller.getSellList());
      for(TradeItem sl : listToSell)
      {
        for(TradeItem bl : listToBuy)
        {
          if(sl.getItemId() == bl.getItemId() && sl.getOwnersPrice() == bl.getOwnersPrice())
          {
            L2ItemInstance inst = seller.getInventory().getItemByObjectId(sl.getObjectId());
            if(inst == null || inst.getCount() <= 0)
            {
              tmp.remove(sl);
              continue;
            }
            if(inst.isStackable())
            {
              sl.setCount(sl.getCount() - bl.getCount());
              if(sl.getCount() <= 0)
              {
                tmp.remove(sl);
                continue;
              }
              if(inst.getCount() < sl.getCount())
              {
                sl.setCount(inst.getCount());
              }
            }
          }
        }
      }
      ConcurrentLinkedQueue<TradeItem> newlist = new ConcurrentLinkedQueue<TradeItem>();
      newlist.addAll(tmp);
      seller.setSellList(newlist);
    }
  }

  /**
   * Проверяет наличие всех продаваемых предметов для листа продажи и наличия нужной денежной суммы для листа покупки.
   */
  public static boolean validateList(L2Player player)
  {
    if(player.getPrivateStoreType() == L2Player.STORE_PRIVATE_SELL || player.getPrivateStoreType() == L2Player.STORE_PRIVATE_SELL_PACKAGE)
    {
      ConcurrentLinkedQueue<TradeItem> selllist = player.getSellList();
      for(TradeItem tl : selllist)
      {
        L2ItemInstance inst = player.getInventory().getItemByObjectId(tl.getObjectId());
        if(inst == null || inst.getCount() <= 0)
        {
          if(player.getPrivateStoreType() == L2Player.STORE_PRIVATE_SELL_PACKAGE)
          {
            cancelStore(player);
            return false;
          }
          selllist.remove(tl);
          continue;
        }
        if(inst.isStackable() && inst.getCount() < tl.getCount())
        {
          if(player.getPrivateStoreType() == L2Player.STORE_PRIVATE_SELL_PACKAGE)
          {
            cancelStore(player);
            return false;
          }
          tl.setCount(inst.getCount());
        }
      }
    }
    else if(player.getPrivateStoreType() == L2Player.STORE_PRIVATE_BUY)
    {
      ConcurrentLinkedQueue<TradeItem> buylist = player.getBuyList();
      long sum = 0;
      for(TradeItem tl : buylist)
      {
        sum += tl.getOwnersPrice() * tl.getCount();
      }
      if(player.getAdena() < sum)
      {
        cancelStore(player);
        return false;
      }
    }
    return true;
  }

  /**
   * Ссаживает чара с трейда. Оффлайн трейдеров кикает.
   */
  public static void cancelStore(L2Player activeChar)
  {
    activeChar.setPrivateStoreType(L2Player.STORE_PRIVATE_NONE);
    activeChar.getBuyList().clear();
    if(activeChar.isInOfflineMode() && Config.SERVICES_OFFLINE_TRADE_KICK_NOT_TRADING)
    {
      activeChar.setOfflineMode(false);
      activeChar.logout(false, false, false, true);
      if(activeChar.getNetConnection() != null)
      {
        activeChar.getNetConnection().disconnectOffline();
      }
    }
    else
    {
      activeChar.broadcastUserInfo(true);
    }
  }
}
TOP

Related Classes of l2p.gameserver.model.L2TradeList

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.