/*
* 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.model.gameobjects.player;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import com.aionemu.gameserver.model.gameobjects.Item;
import com.aionemu.gameserver.model.gameobjects.PersistentState;
import com.aionemu.gameserver.model.items.ItemStorage;
import com.aionemu.gameserver.network.aion.serverpackets.SM_DELETE_ITEM;
import com.aionemu.gameserver.network.aion.serverpackets.SM_UPDATE_ITEM;
import com.aionemu.gameserver.network.aion.serverpackets.SM_UPDATE_WAREHOUSE_ITEM;
import com.aionemu.gameserver.utils.PacketSendUtility;
/**
* @author Avol
* modified by ATracer, kosyachok
*/
public class Storage
{
private Player owner;
protected ItemStorage storage;
private Item kinahItem;
protected int storageType;
protected Queue<Item> deletedItems = new ConcurrentLinkedQueue<Item>();
/**
* Can be of 2 types: UPDATED and UPDATE_REQUIRED
*/
private PersistentState persistentState = PersistentState.UPDATED;
/**
* Will be enhanced during development.
*/
public Storage(StorageType storageType)
{
switch(storageType)
{
case CUBE:
storage = new ItemStorage(108);
this.storageType = storageType.getId();
break;
case REGULAR_WAREHOUSE:
storage = new ItemStorage(104);
this.storageType = storageType.getId();
break;
case ACCOUNT_WAREHOUSE:
storage = new ItemStorage(16);
this.storageType = storageType.getId();
break;
case LEGION_WAREHOUSE:
storage = new ItemStorage(24); // TODO: FIND OUT WHAT MAX IS
this.storageType = storageType.getId();
break;
}
}
/**
* @param owner
*/
public Storage(Player owner, StorageType storageType)
{
this(storageType);
this.owner = owner;
}
/**
* @return the owner
*/
public Player getOwner()
{
return owner;
}
/**
* @param owner the owner to set
*/
public void setOwner(Player owner)
{
this.owner = owner;
}
/**
* @return the kinahItem
*/
public Item getKinahItem()
{
return kinahItem;
}
public int getStorageType()
{
return storageType;
}
/**
* Increasing kinah amount is persisted immediately
*
* @param amount
*/
public void increaseKinah(int amount)
{
kinahItem.increaseItemCount(amount);
if(storageType == StorageType.CUBE.getId())
PacketSendUtility.sendPacket(getOwner(), new SM_UPDATE_ITEM(kinahItem));
if (storageType == StorageType.ACCOUNT_WAREHOUSE.getId())
PacketSendUtility.sendPacket(getOwner(), new SM_UPDATE_WAREHOUSE_ITEM(kinahItem, storageType));
setPersistentState(PersistentState.UPDATE_REQUIRED);
}
/**
* Decreasing kinah amount is persisted immediately
*
* @param amount
*/
public boolean decreaseKinah(int amount)
{
boolean operationResult = kinahItem.decreaseItemCount(amount);
if(operationResult)
{
if(storageType == StorageType.CUBE.getId())
PacketSendUtility.sendPacket(getOwner(), new SM_UPDATE_ITEM(kinahItem));
if (storageType == StorageType.ACCOUNT_WAREHOUSE.getId())
PacketSendUtility.sendPacket(getOwner(), new SM_UPDATE_WAREHOUSE_ITEM(kinahItem, storageType));
}
setPersistentState(PersistentState.UPDATE_REQUIRED);
return operationResult;
}
/**
*
* This method should be called only for new items added to inventory (loading from DB)
* If item is equiped - will be put to equipment
* if item is unequiped - will be put to default bag for now
* Kinah is stored separately as it will be used frequently
*
* @param item
*/
public void onLoadHandler(Item item)
{
if(item.isEquipped())
{
owner.getEquipment().onLoadHandler(item);
}
else if(item.getItemTemplate().isKinah())
{
kinahItem = item;
}
else
{
storage.putToNextAvailableSlot(item);
}
}
/**
* Used to put item into storage cube at first avaialble slot (no check for existing item)
* During unequip/equip process persistImmediately should be false
*
* @param item
* @param persistImmediately
* @return Item
*/
public Item putToBag(Item item)
{
Item resultItem = storage.putToNextAvailableSlot(item);
if(resultItem != null)
{
resultItem.setItemLocation(storageType);
}
setPersistentState(PersistentState.UPDATE_REQUIRED);
return resultItem;
}
/**
* Removes item completely from inventory.
* Every remove operation is persisted immediately now
*
* @param item
*/
public void removeFromBag(Item item, boolean persist)
{
boolean operationResult = storage.removeItemFromStorage(item);
if(operationResult && persist)
{
item.setPersistentState(PersistentState.DELETED);
deletedItems.add(item);
setPersistentState(PersistentState.UPDATE_REQUIRED);
}
}
/**
* Used to reduce item count in bag or completely remove by ITEMID
* This method operates in iterative manner overl all items with specified ITEMID.
* Return value can be the following:
* - true - item removal was successfull
* - false - not enough amount of items to reduce
* or item is not present
*
* @param itemId
* @param count
* @return true or false
*/
public boolean removeFromBagByItemId(int itemId, int count)
{
if(count < 1)
return false;
List<Item> items = storage.getItemsFromStorageByItemId(itemId);
for(Item item : items)
{
count = decreaseItemCount(item, count);
if(count == 0)
break;
}
boolean result = count >=0;
if(result)
setPersistentState(PersistentState.UPDATE_REQUIRED);
return result;
}
/**
*
* @param itemId
* @return Item
*/
public Item getFirstItemByItemId(int itemId)
{
List<Item> items = storage.getItemsFromStorageByItemId(itemId);
return items.get(0);
}
/**
* Used to reduce item count in bag or completely remove by OBJECTID
* Return value can be the following:
* - true - item removal was successfull
* - false - not enough amount of items to reduce
* or item is not present
*
* @param itemObjId
* @param count
* @return true or false
*/
public boolean removeFromBagByObjectId(int itemObjId, int count)
{
if(count < 1)
return false;
Item item = storage.getItemFromStorageByItemObjId(itemObjId);
boolean result = decreaseItemCount(item, count) >= 0;
if(result)
setPersistentState(PersistentState.UPDATE_REQUIRED);
return result;
}
/**
* This method decreases inventory's item by count and sends
* appropriate packets to owner.
* Item will be saved in database after update or deleted if count=0 (and persist=true)
*
* @param count should be > 0
* @param item
* @return
*/
public int decreaseItemCount(Item item, int count)
{
int itemCount = item.getItemCount();
if(itemCount >= count)
{
item.decreaseItemCount(count);
count = 0;
}
else
{
item.decreaseItemCount(itemCount);
count -= itemCount;
}
if(item.getItemCount() == 0)
{
storage.removeItemFromStorage(item);
PacketSendUtility.sendPacket(getOwner(), new SM_DELETE_ITEM(item.getObjectId()));
deletedItems.add(item);
}
else
PacketSendUtility.sendPacket(getOwner(), new SM_UPDATE_ITEM(item));
setPersistentState(PersistentState.UPDATE_REQUIRED);
return count;
}
/**
* Method primarily used when saving to DB
*
* @return List<Item>
*/
public List<Item> getAllItems()
{
List<Item> allItems = new ArrayList<Item>();
if(kinahItem != null)
allItems.add(kinahItem);
allItems.addAll(storage.getStorageItems());
return allItems;
}
/**
* All deleted items with persistent state DELETED
*
* @return
*/
public Queue<Item> getDeletedItems()
{
return deletedItems;
}
/**
* Searches for item with specified itemId in equipment and cube
*
* @param itemId
* @return List<Item>
*/
public List<Item> getAllItemsByItemId(int itemId)
{
List<Item> allItemsByItemId = new ArrayList<Item>();
for (Item item : storage.getStorageItems())
{
if(item.getItemTemplate().getTemplateId() == itemId)
allItemsByItemId.add(item);
}
return allItemsByItemId;
}
public List<Item> getStorageItems()
{
return storage.getStorageItems();
}
/**
* Will look item in default item bag
*
* @param value
* @return Item
*/
public Item getItemByObjId(int value)
{
return storage.getItemFromStorageByItemObjId(value);
}
/**
*
* @param value
* @return List<Item>
*/
public List<Item> getItemsByItemId(int value)
{
return storage.getItemsFromStorageByItemId(value);
}
/**
*
* @param itemId
* @return number of items using search by itemid
*/
public int getItemCountByItemId(int itemId)
{
List<Item> items = getItemsByItemId(itemId);
int count = 0;
for(Item item : items)
{
count += item.getItemCount();
}
return count;
}
/**
* Checks whether default cube is full
*
* @return true or false
*/
public boolean isFull()
{
return storage.isFull();
}
/**
* Number of available slots of the underlying storage
*
* @return
*/
public int getNumberOfFreeSlots()
{
return storage.getNumberOfFreeSlots();
}
/**
* Sets the Inventory Limit from Cube Size
*
* @param Limit
*/
public void setLimit(int limit)
{
this.storage.setLimit(limit);
}
/**
* Limit value of the underlying storage
*
* @return
*/
public int getLimit()
{
return this.storage.getLimit();
}
/**
* @return the persistentState
*/
public PersistentState getPersistentState()
{
return persistentState;
}
/**
* @param persistentState the persistentState to set
*/
public void setPersistentState(PersistentState persistentState)
{
this.persistentState = persistentState;
}
/**
* @param item
* @param count
*/
public void increaseItemCount(Item item, int count)
{
item.increaseItemCount(count);
setPersistentState(PersistentState.UPDATE_REQUIRED);
}
/**
* Size of underlying storage
*
* @return
*/
public int size()
{
return storage.size();
}
}