/*
* This file is part of aion-unique <aion-unique.org>.
*
* aion-unique is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* aion-unique is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with aion-unique. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aionemu.gameserver.services;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import com.aionemu.gameserver.dataholders.GoodsListData;
import com.aionemu.gameserver.dataholders.TradeListData;
import com.aionemu.gameserver.model.gameobjects.Item;
import com.aionemu.gameserver.model.gameobjects.Npc;
import com.aionemu.gameserver.model.gameobjects.player.AbyssRank;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.player.Storage;
import com.aionemu.gameserver.model.templates.TradeListTemplate;
import com.aionemu.gameserver.model.templates.TradeListTemplate.TradeTab;
import com.aionemu.gameserver.model.templates.goods.GoodsList;
import com.aionemu.gameserver.model.trade.TradeItem;
import com.aionemu.gameserver.model.trade.TradeList;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ABYSS_RANK;
import com.aionemu.gameserver.network.aion.serverpackets.SM_DELETE_ITEM;
import com.aionemu.gameserver.network.aion.serverpackets.SM_INVENTORY_UPDATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_UPDATE_ITEM;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.world.World;
import com.google.inject.Inject;
/**
* @author ATracer
*
*/
public class TradeService
{
private static final Logger log = Logger.getLogger(TradeService.class);
@Inject
private ItemService itemService;
@Inject
private World world;
@Inject
private TradeListData tradeListData;
@Inject
private GoodsListData goodsListData;
/**
*
* @param player
* @param tradeList
* @return true or false
*/
public boolean performBuyFromShop(Player player, TradeList tradeList)
{
if(!validateBuyItems(tradeList))
{
PacketSendUtility.sendMessage(player, "Some items are not allowed to be selled from this npc");
return false;
}
Storage inventory = player.getInventory();
Item kinahItem = inventory.getKinahItem();
// 1. check kinah
if(!tradeList.calculateBuyListPrice(player, 2))
return false;
// 2. check free slots, need to check retail behaviour
int freeSlots = inventory.getLimit() - inventory.getAllItems().size() + 1;
if(freeSlots < tradeList.size())
return false; // TODO message
int tradeListPrice = tradeList.getRequiredKinah();
List<Item> addedItems = new ArrayList<Item>();
for(TradeItem tradeItem : tradeList.getTradeItems())
{
int count = itemService.addItem(player, tradeItem.getItemTemplate().getTemplateId(), tradeItem.getCount());
if(count != 0)
{
log.warn(String.format("CHECKPOINT: itemservice couldnt add all items on buy: %d %d %d %d", player
.getObjectId(), tradeItem.getItemTemplate().getTemplateId(), tradeItem.getCount(), count));
inventory.decreaseKinah(tradeListPrice);
return false;
}
}
inventory.decreaseKinah(tradeListPrice);
PacketSendUtility.sendPacket(player, new SM_UPDATE_ITEM(kinahItem));
PacketSendUtility.sendPacket(player, new SM_INVENTORY_UPDATE(addedItems));
// TODO message
return true;
}
/**
* Probably later merge with regular buy
*
* @param player
* @param tradeList
* @return true or false
*/
public boolean performBuyFromAbyssShop(Player player, TradeList tradeList)
{
if(!validateBuyItems(tradeList))
{
PacketSendUtility.sendMessage(player, "Some items are not allowed to be selled from this npc");
return false;
}
Storage inventory = player.getInventory();
int freeSlots = inventory.getLimit() - inventory.getAllItems().size() + 1;
AbyssRank rank = player.getAbyssRank();
// 1. check required items and ap
if(!tradeList.calculateAbyssBuyListPrice(player))
return false;
// 2. check free slots, need to check retail behaviour
if(freeSlots < tradeList.size())
return false; // TODO message
List<Item> addedItems = new ArrayList<Item>();
for(TradeItem tradeItem : tradeList.getTradeItems())
{
int count = itemService.addItem(player, tradeItem.getItemTemplate().getTemplateId(), tradeItem.getCount());
if(count != 0)
{
log.warn(String.format("CHECKPOINT: itemservice couldnt add all items on buy: %d %d %d %d", player
.getObjectId(), tradeItem.getItemTemplate().getTemplateId(), tradeItem.getCount(), count));
rank.addAp(-tradeList.getRequiredAp());
return false;
}
}
rank.addAp(-tradeList.getRequiredAp());
Map<Integer, Integer> requiredItems = tradeList.getRequiredItems();
for(Integer itemId : requiredItems.keySet())
{
player.getInventory().removeFromBagByItemId(itemId, requiredItems.get(itemId));
}
PacketSendUtility.sendPacket(player, new SM_ABYSS_RANK(rank));
PacketSendUtility.sendPacket(player, new SM_INVENTORY_UPDATE(addedItems));
// TODO message
return true;
}
/**
* @param tradeList
*/
private boolean validateBuyItems(TradeList tradeList)
{
Npc npc = (Npc) world.findAionObject(tradeList.getSellerObjId());
TradeListTemplate tradeListTemplate = tradeListData.getTradeListTemplate(npc.getObjectTemplate()
.getTemplateId());
Set<Integer> allowedItems = new HashSet<Integer>();
for(TradeTab tradeTab : tradeListTemplate.getTradeTablist())
{
GoodsList goodsList = goodsListData.getGoodsListById(tradeTab.getId());
if(goodsList != null && goodsList.getItemIdList() != null)
{
allowedItems.addAll(goodsList.getItemIdList());
}
}
for(TradeItem tradeItem : tradeList.getTradeItems())
{
if(!allowedItems.contains(tradeItem.getItemId()))
return false;
}
return true;
}
/**
*
* @param player
* @param tradeList
* @return true or false
*/
public boolean performSellToShop(Player player, TradeList tradeList)
{
Storage inventory = player.getInventory();
int kinahReward = 0;
for(TradeItem tradeItem : tradeList.getTradeItems())
{
Item item = inventory.getItemByObjId(tradeItem.getItemId());
// 1) don't allow to sell fake items;
if(item == null)
return false;
if(item.getItemCount() - tradeItem.getCount() == 0)
{
inventory.removeFromBag(item, true); // need to be here to avoid exploit by sending packet with many
// items with same unique ids
kinahReward += item.getItemTemplate().getPrice() * item.getItemCount();
// TODO check retail packet here
PacketSendUtility.sendPacket(player, new SM_DELETE_ITEM(item.getObjectId()));
}
else if(item.getItemCount() - tradeItem.getCount() > 0)
{
if(inventory.decreaseItemCount(item, tradeItem.getCount()) > 0)
{
// TODO check retail packet here
kinahReward += item.getItemTemplate().getPrice() * tradeItem.getCount();
PacketSendUtility.sendPacket(player, new SM_UPDATE_ITEM(item));
}
else
return false;
}
else
return false;
}
Item kinahItem = inventory.getKinahItem();
inventory.increaseKinah(kinahReward / 2);
PacketSendUtility.sendPacket(player, new SM_UPDATE_ITEM(kinahItem));
return true;
}
/**
* @return the tradeListData
*/
public TradeListData getTradeListData()
{
return tradeListData;
}
}