/* * 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(); } }