/*
* 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.HashMap;
import java.util.Map;
import com.aionemu.gameserver.model.gameobjects.Item;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.player.Storage;
import com.aionemu.gameserver.model.items.ItemStone;
import com.aionemu.gameserver.model.trade.Exchange;
import com.aionemu.gameserver.model.trade.ExchangeItem;
import com.aionemu.gameserver.network.aion.serverpackets.SM_EXCHANGE_ADD_ITEM;
import com.aionemu.gameserver.network.aion.serverpackets.SM_EXCHANGE_ADD_KINAH;
import com.aionemu.gameserver.network.aion.serverpackets.SM_EXCHANGE_CONFIRMATION;
import com.aionemu.gameserver.network.aion.serverpackets.SM_EXCHANGE_REQUEST;
import com.aionemu.gameserver.restrictions.RestrictionsManager;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.google.inject.Inject;
/**
* @author ATracer
*
*/
public class ExchangeService
{
@Inject
private ItemService itemService;
private Map<Integer, Exchange> exchanges = new HashMap<Integer, Exchange>();
/**
* @param objectId
* @param objectId2
*/
public void registerExchange(Player player1, Player player2)
{
if(!validateParticipants(player1, player2))
return;
player1.setTrading(true);
player2.setTrading(true);
exchanges.put(player1.getObjectId(), new Exchange(player1, player2));
exchanges.put(player2.getObjectId(), new Exchange(player2, player1));
PacketSendUtility.sendPacket(player2, new SM_EXCHANGE_REQUEST(player1.getName()));
PacketSendUtility.sendPacket(player1, new SM_EXCHANGE_REQUEST(player2.getName()));
}
/**
* @param player1
* @param player2
*/
private boolean validateParticipants(Player player1, Player player2)
{
return RestrictionsManager.canTrade(player1) && RestrictionsManager.canTrade(player2);
}
public Player getCurrentParter(Player player)
{
Exchange exchange = exchanges.get(player.getObjectId());
return exchange != null ? exchange.getTargetPlayer() : null;
}
/**
*
* @param player
* @return Exchange
*/
public Exchange getCurrentExchange(Player player)
{
return exchanges.get(player.getObjectId());
}
/**
*
* @param player
* @return Exchange
*/
public Exchange getCurrentParnterExchange(Player player)
{
Player partner = getCurrentParter(player);
return partner != null ? getCurrentExchange(partner) : null;
}
/**
* @param activePlayer
* @param itemCount
*/
public void addKinah(Player activePlayer, int itemCount)
{
Exchange currentExchange = getCurrentExchange(activePlayer);
if(currentExchange.isLocked())
return;
if(itemCount < 1)
return;
//count total amount in inventory
int availableCount = activePlayer.getInventory().getKinahItem().getItemCount();
//count amount that was already added to exchange
availableCount -= currentExchange.getKinahCount();
int countToAdd = availableCount > itemCount ? itemCount : availableCount;
if(countToAdd > 0)
{
Player partner = getCurrentParter(activePlayer);
PacketSendUtility.sendPacket(activePlayer, new SM_EXCHANGE_ADD_KINAH(countToAdd, 0));
PacketSendUtility.sendPacket(partner, new SM_EXCHANGE_ADD_KINAH(countToAdd, 1));
currentExchange.addKinah(countToAdd);
}
}
/**
* @param activePlayer
* @param itemObjId
* @param itemCount
*/
public void addItem(Player activePlayer, int itemObjId, int itemCount)
{
Item item = activePlayer.getInventory().getItemByObjId(itemObjId);
if(item == null)
return;
if(itemCount < 1)
return;
if(itemCount > item.getItemCount())
return;
Player partner = getCurrentParter(activePlayer);
Exchange currentExchange = getCurrentExchange(activePlayer);
if(currentExchange.isLocked())
return;
if(currentExchange.isExchangeListFull())
return;
ExchangeItem exchangeItem = currentExchange.getItems().get(item.getObjectId());
int actuallAddCount = 0;
//item was not added previosly
if(exchangeItem == null)
{
Item newItem = itemService.newItem(item.getItemTemplate().getTemplateId(), itemCount);
exchangeItem = new ExchangeItem(itemObjId, itemCount, newItem);
currentExchange.addItem(itemObjId, exchangeItem);
if(item.hasManaStones())
{
for(ItemStone stone : item.getItemStones())
{
itemService.addManaStone(newItem, stone.getItemId());
}
}
if(item.getGodStone() != null)
{
newItem.addGodStone(item.getGodStone().getItemId());
}
actuallAddCount = itemCount;
}
//item was already added
else
{
//if player add item count that is more than possible
//happens with exploits
if(item.getItemCount() == exchangeItem.getItemCount())
return;
int possibleToAdd = item.getItemCount() - exchangeItem.getItemCount();
actuallAddCount = itemCount > possibleToAdd ? possibleToAdd : itemCount;
exchangeItem.addCount(actuallAddCount);
}
PacketSendUtility.sendPacket(activePlayer, new SM_EXCHANGE_ADD_ITEM(0, exchangeItem.getNewItem()));
PacketSendUtility.sendPacket(partner, new SM_EXCHANGE_ADD_ITEM(1, exchangeItem.getNewItem()));
}
/**
* @param activePlayer
*/
public void lockExchange(Player activePlayer)
{
Exchange exchange = getCurrentExchange(activePlayer);
if(exchange != null)
{
exchange.lock();
Player currentParter = getCurrentParter(activePlayer);
PacketSendUtility.sendPacket(currentParter, new SM_EXCHANGE_CONFIRMATION(3));
}
}
/**
* @param activePlayer
*/
public void cancelExchange(Player activePlayer)
{
Exchange exchange1 = getCurrentExchange(activePlayer);
if(exchange1 != null)
exchange1.cancel(itemService);
Exchange exchange2 = getCurrentParnterExchange(activePlayer);
if(exchange2 != null)
exchange2.cancel(itemService);
Player currentParter = getCurrentParter(activePlayer);;
cleanupExchanges(activePlayer, currentParter);
if(currentParter != null)
PacketSendUtility.sendPacket(currentParter, new SM_EXCHANGE_CONFIRMATION(1));
}
/**
* @param activePlayer
*/
public void confirmExchange(Player activePlayer)
{
Exchange currentExchange = getCurrentExchange(activePlayer);
currentExchange.confirm();
Player currentPartner = getCurrentParter(activePlayer);
PacketSendUtility.sendPacket(currentPartner, new SM_EXCHANGE_CONFIRMATION(2));
if(getCurrentExchange(currentPartner).isConfirmed())
{
performTrade(activePlayer, currentPartner);
}
}
/**
* @param activePlayer
* @param currentPartner
*/
private void performTrade(Player activePlayer, Player currentPartner)
{
//TODO message here
if(!validateExchange(activePlayer, currentPartner))
return;
PacketSendUtility.sendPacket(activePlayer, new SM_EXCHANGE_CONFIRMATION(0));
PacketSendUtility.sendPacket(currentPartner, new SM_EXCHANGE_CONFIRMATION(0));
Exchange exchange1 = getCurrentExchange(activePlayer);
Exchange exchange2 = getCurrentExchange(currentPartner);
cleanupExchanges(activePlayer, currentPartner);
removeItemsFromInventory(activePlayer, exchange1);
removeItemsFromInventory(currentPartner, exchange2);
putItemToInventory(currentPartner, exchange1);
putItemToInventory(activePlayer, exchange2);
}
/**
*
* @param activePlayer
* @param currentPartner
*/
private void cleanupExchanges(Player activePlayer, Player currentPartner)
{
if(activePlayer != null)
{
exchanges.remove(activePlayer.getObjectId());
activePlayer.setTrading(false);
}
if(currentPartner != null)
{
exchanges.remove(currentPartner.getObjectId());
currentPartner.setTrading(false);
}
}
/**
* @param player
* @param exchange
*/
private void removeItemsFromInventory(Player player, Exchange exchange)
{
Storage inventory = player.getInventory();
for(ExchangeItem exchangeItem : exchange.getItems().values())
{
int itemObjId = exchangeItem.getItemObjId();
Item itemInInventory = inventory.getItemByObjId(itemObjId);
int itemCount = exchangeItem.getNewItem().getItemCount();
inventory.decreaseItemCount(itemInInventory, itemCount);
}
player.getInventory().decreaseKinah(exchange.getKinahCount());
}
/**
* @param activePlayer
* @param currentPartner
* @return
*/
private boolean validateExchange(Player activePlayer, Player currentPartner)
{
Exchange exchange1 = getCurrentExchange(activePlayer);
Exchange exchange2 = getCurrentExchange(currentPartner);
return validateInventorySize(activePlayer, exchange2)
&& validateInventorySize(currentPartner, exchange1);
}
private boolean validateInventorySize(Player activePlayer, Exchange exchange)
{
int numberOfFreeSlots = activePlayer.getInventory().getNumberOfFreeSlots();
return numberOfFreeSlots >= exchange.getItems().size();
}
/**
*
* @param player
* @param exchange
*/
private void putItemToInventory(Player player, Exchange exchange)
{
for(ExchangeItem exchangeItem : exchange.getItems().values())
{
Item itemToPut = exchangeItem.getNewItem();
player.getInventory().putToBag(itemToPut);
itemService.updateItem(player, itemToPut, true);
}
player.getInventory().increaseKinah(exchange.getKinahCount());
}
}