dwo.gameserver.model.items.itemcontainer.PcInventory.java Source code

Java tutorial

Introduction

Here is the source code for dwo.gameserver.model.items.itemcontainer.PcInventory.java

Source

/*
 * This program 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.
 * 
 * This program 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
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package dwo.gameserver.model.items.itemcontainer;

import dwo.config.Config;
import dwo.gameserver.engine.databaseengine.FiltredPreparedStatement;
import dwo.gameserver.engine.databaseengine.L2DatabaseFactory;
import dwo.gameserver.engine.databaseengine.ThreadConnection;
import dwo.gameserver.model.actor.instance.L2PcInstance;
import dwo.gameserver.model.items.ItemTable;
import dwo.gameserver.model.items.TradeItem;
import dwo.gameserver.model.items.base.L2Item;
import dwo.gameserver.model.items.base.instance.L2ItemInstance;
import dwo.gameserver.model.items.base.instance.L2ItemInstance.ItemLocation;
import dwo.gameserver.model.items.base.proptypes.ProcessType;
import dwo.gameserver.model.items.base.type.L2EtcItemType;
import dwo.gameserver.model.player.L2ShortCut;
import dwo.gameserver.model.player.TradeList;
import dwo.gameserver.network.game.components.SystemMessageId;
import dwo.gameserver.network.game.serverpackets.InventoryUpdate;
import dwo.gameserver.network.game.serverpackets.ItemList;
import dwo.gameserver.network.game.serverpackets.SystemMessage;
import dwo.gameserver.network.game.serverpackets.packet.ex.ExAdenaInvenCount;
import dwo.gameserver.network.game.serverpackets.packet.info.ExUserInfoInvenWeight;
import dwo.gameserver.util.database.DatabaseUtils;
import javolution.util.FastList;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.log4j.Level;

import java.sql.ResultSet;
import java.util.List;
import java.util.stream.Collectors;

public class PcInventory extends Inventory {
    // 
    public static final int ADENA_ID = 57;
    public static final int ANCIENT_ADENA_ID = 5575;
    public static final long MAX_ADENA = 99900000000L;

    // 
    public static final int CRYSTAL_R = 17371;

    private final L2PcInstance _owner;
    private final Object _lock;
    private L2ItemInstance _adena;
    private L2ItemInstance _ancientAdena;
    private int[] _blockItems;
    private int _questSlots;
    /**
     * Block modes:
     * <UL>
     * <LI>-1 - no block
     * <LI>0 - block items from _invItems, allow usage of other items
     * <LI>1 - allow usage of items from _invItems, block other items
     * </UL>
     */
    private int _blockMode = -1;

    public PcInventory(L2PcInstance owner) {
        _owner = owner;
        _lock = new Object();
    }

    public static int[][] restoreVisibleInventory(int objectId) {
        int[][] paperdoll = new int[33][4];
        ThreadConnection con = null;
        FiltredPreparedStatement statement = null;
        ResultSet invdata = null;
        try {
            con = L2DatabaseFactory.getInstance().getConnection();
            statement = con.prepareStatement(
                    "SELECT object_id,item_id,loc_data,enchant_level,skin_id FROM items WHERE owner_id=? AND loc='PAPERDOLL'");
            statement.setInt(1, objectId);
            invdata = statement.executeQuery();

            while (invdata.next()) {
                int slot = invdata.getInt("loc_data");
                paperdoll[slot][0] = invdata.getInt("object_id");
                paperdoll[slot][1] = invdata.getInt("item_id");
                paperdoll[slot][2] = invdata.getInt("enchant_level");
                paperdoll[slot][3] = invdata.getInt("skin_id");
            }
        } catch (Exception e) {
            _log.log(Level.ERROR, "Could not restore inventory: " + e.getMessage(), e);
        } finally {
            DatabaseUtils.closeDatabaseCSR(con, statement, invdata);
        }
        return paperdoll;
    }

    @Override
    public L2PcInstance getOwner() {
        return _owner;
    }

    @Override
    protected ItemLocation getBaseLocation() {
        return ItemLocation.INVENTORY;
    }

    /**
     * Adds item in inventory and checks _adena and _ancientAdena
     *
     * @param process   : String Identifier of process triggering this action
     * @param item      : L2ItemInstance to be added
     * @param actor     : L2PcInstance Player requesting the item add
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     * @return L2ItemInstance corresponding to the new item or the updated item in inventory
     */
    @Override
    public L2ItemInstance addItem(ProcessType process, L2ItemInstance item, L2PcInstance actor, Object reference) {
        item = super.addItem(process, item, actor, reference);

        if (item != null && item.getItemId() == ADENA_ID && !item.equals(_adena)) {
            _adena = item;
        }

        if (item != null && item.getItemId() == ANCIENT_ADENA_ID && !item.equals(_ancientAdena)) {
            _ancientAdena = item;
        }

        return item;
    }

    /**
     * Adds item in inventory and checks _adena and _ancientAdena
     *
     * @param process   : String Identifier of process triggering this action
     * @param itemId    : int Item Identifier of the item to be added
     * @param count     : int Quantity of items to be added
     * @param actor     : L2PcInstance Player requesting the item creation
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     * @return L2ItemInstance corresponding to the new item or the updated item in inventory
     */
    @Override
    public L2ItemInstance addItem(ProcessType process, int itemId, long count, L2PcInstance actor,
            Object reference) {
        L2ItemInstance item = super.addItem(process, itemId, count, actor, reference);
        if (item == null) {
            return null;
        }

        if (item.getItemId() == ADENA_ID && !item.equals(_adena)) {
            _adena = item;
        }

        if (item.getItemId() == ANCIENT_ADENA_ID && !item.equals(_ancientAdena)) {
            _ancientAdena = item;
        }
        if (actor != null) {
            // Send inventory update packet
            if (Config.FORCE_INVENTORY_UPDATE) {
                actor.sendPacket(new ItemList(actor, false));
            } else {
                InventoryUpdate playerIU = new InventoryUpdate();
                playerIU.addItem(item);
                actor.sendPacket(playerIU);
            }

            // Update current load as well
            actor.sendPacket(new ExUserInfoInvenWeight(actor));
            actor.sendPacket(new ExAdenaInvenCount(actor));
        }
        return item;
    }

    /**
     * Transfers item to another inventory and checks _adena and _ancientAdena
     *
     * @param process   : String Identifier of process triggering this action
     * @param objectId  : int Item Identifier of the item to be transfered
     * @param count     : int Quantity of items to be transfered
     * @param actor     : L2PcInstance Player requesting the item transfer
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     * @return L2ItemInstance corresponding to the new item or the updated item in inventory
     */
    @Override
    public L2ItemInstance transferItem(ProcessType process, int objectId, long count, ItemContainer target,
            L2PcInstance actor, Object reference) {
        L2ItemInstance item = super.transferItem(process, objectId, count, target, actor, reference);

        if (_adena != null && (_adena.getCount() <= 0 || _adena.getOwnerId() != getOwnerId())) {
            _adena = null;
        }

        if (_ancientAdena != null
                && (_ancientAdena.getCount() <= 0 || _ancientAdena.getOwnerId() != getOwnerId())) {
            _ancientAdena = null;
        }

        return item;
    }

    /**
     * Destroy item from inventory and checks _adena and _ancientAdena
     *
     * @param process   : String Identifier of process triggering this action
     * @param item      : L2ItemInstance to be destroyed
     * @param actor     : L2PcInstance Player requesting the item destroy
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
     */
    @Override
    public L2ItemInstance destroyItem(ProcessType process, L2ItemInstance item, L2PcInstance actor,
            Object reference) {
        return destroyItem(process, item, item.getCount(), actor, reference);
    }

    /**
     * Destroy item from inventory and checks _adena and _ancientAdena
     *
     * @param process   : String Identifier of process triggering this action
     * @param item      : L2ItemInstance to be destroyed
     * @param actor     : L2PcInstance Player requesting the item destroy
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
     */
    @Override
    public L2ItemInstance destroyItem(ProcessType process, L2ItemInstance item, long count, L2PcInstance actor,
            Object reference) {
        item = super.destroyItem(process, item, count, actor, reference);

        if (_adena != null && _adena.getCount() <= 0) {
            _adena = null;
        }

        if (_ancientAdena != null && _ancientAdena.getCount() <= 0) {
            _ancientAdena = null;
        }

        return item;
    }

    /**
     * Destroys item from inventory and checks _adena and _ancientAdena
     *
     * @param process   : String Identifier of process triggering this action
     * @param objectId  : int Item Instance identifier of the item to be destroyed
     * @param count     : int Quantity of items to be destroyed
     * @param actor     : L2PcInstance Player requesting the item destroy
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
     */
    @Override
    public L2ItemInstance destroyItem(ProcessType process, int objectId, long count, L2PcInstance actor,
            Object reference) {
        L2ItemInstance item = getItemByObjectId(objectId);
        if (item == null) {
            return null;
        }
        return destroyItem(process, item, count, actor, reference);
    }

    /**
     * Destroy item from inventory by using its <B>itemId</B> and checks _adena and _ancientAdena
     *
     * @param process   : String Identifier of process triggering this action
     * @param itemId    : int Item identifier of the item to be destroyed
     * @param count     : int Quantity of items to be destroyed
     * @param actor     : L2PcInstance Player requesting the item destroy
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
     */
    @Override
    public L2ItemInstance destroyItemByItemId(ProcessType process, int itemId, long count, L2PcInstance actor,
            Object reference) {
        L2ItemInstance item = getItemByItemId(itemId);
        if (item == null) {
            return null;
        }
        return destroyItem(process, item, count, actor, reference);
    }

    @Override
    public long getAdenaCount() {
        return _adena != null ? _adena.getCount() : 0;
    }

    @Override
    public boolean validateCapacity(long slots) {
        return validateCapacity(slots, false);
    }

    @Override
    public boolean validateWeight(long weight) {
        // Disable weight check for GMs.
        if (_owner.isGM() && _owner.getDietMode() && _owner.getAccessLevel().allowTransaction()) {
            return true;
        }
        return _totalWeight + weight <= _owner.getMaxLoad();
    }

    @Override
    protected ItemLocation getEquipLocation() {
        return ItemLocation.PAPERDOLL;
    }

    /**
     * Drop item from inventory and checks _adena and _ancientAdena
     *
     * @param process   : String Identifier of process triggering this action
     * @param item      : L2ItemInstance to be dropped
     * @param actor     : L2PcInstance Player requesting the item drop
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
     */
    @Override
    public L2ItemInstance dropItem(ProcessType process, L2ItemInstance item, L2PcInstance actor, Object reference) {
        item = super.dropItem(process, item, actor, reference);

        if (_adena != null && (_adena.getCount() <= 0 || _adena.getOwnerId() != getOwnerId())) {
            _adena = null;
        }

        if (_ancientAdena != null
                && (_ancientAdena.getCount() <= 0 || _ancientAdena.getOwnerId() != getOwnerId())) {
            _ancientAdena = null;
        }

        return item;
    }

    /**
     * Drop item from inventory by using its <B>objectID</B> and checks _adena and _ancientAdena
     *
     * @param process   : String Identifier of process triggering this action
     * @param objectId  : int Item Instance identifier of the item to be dropped
     * @param count     : int Quantity of items to be dropped
     * @param actor     : L2PcInstance Player requesting the item drop
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
     */
    @Override
    public L2ItemInstance dropItem(ProcessType process, int objectId, long count, L2PcInstance actor,
            Object reference) {
        L2ItemInstance item = super.dropItem(process, objectId, count, actor, reference);

        if (_adena != null && (_adena.getCount() <= 0 || _adena.getOwnerId() != getOwnerId())) {
            _adena = null;
        }

        if (_ancientAdena != null
                && (_ancientAdena.getCount() <= 0 || _ancientAdena.getOwnerId() != getOwnerId())) {
            _ancientAdena = null;
        }

        return item;
    }

    @Override
    protected void addItem(L2ItemInstance item) {
        if (item.isQuestItem()) {
            synchronized (_lock) {
                _questSlots++;
            }
        }
        super.addItem(item);
    }

    /**
     * <b>Overloaded</b>, when removes item from inventory, remove also owner shortcuts.
     *
     * @param item : L2ItemInstance to be removed from inventory
     */
    @Override
    protected boolean removeItem(L2ItemInstance item) {
        // Removes any reference to the item from Shortcut bar
        _owner.getShortcutController().removeShortcut(item.getObjectId(), L2ShortCut.ShortcutType.ITEM);

        // Removes active enchant Scroll
        if (item.equals(_owner.getActiveEnchantItem())) {
            _owner.setActiveEnchantItem(null);
        }

        if (item.getItemId() == ADENA_ID) {
            _adena = null;
        } else if (item.getItemId() == ANCIENT_ADENA_ID) {
            _ancientAdena = null;
        }

        if (item.isQuestItem()) {
            synchronized (_lock) {
                _questSlots--;
                if (_questSlots < 0) {
                    _questSlots = 0;
                    _log.log(Level.WARN, this + ": QuestInventory size < 0!");
                }
            }
        }
        return super.removeItem(item);
    }

    /**
     * Refresh the weight of equipment loaded
     */
    @Override
    public void refreshWeight() {
        super.refreshWeight();
        _owner.refreshOverloaded();
    }

    /**
     * Get back items in inventory from database
     */
    @Override
    public void restore() {
        super.restore();
        _adena = getItemByItemId(ADENA_ID);
        _ancientAdena = getItemByItemId(ANCIENT_ADENA_ID);
    }

    public L2ItemInstance getAdenaInstance() {
        return _adena;
    }

    public L2ItemInstance getAncientAdenaInstance() {
        return _ancientAdena;
    }

    public long getAncientAdena() {
        return _ancientAdena != null ? _ancientAdena.getCount() : 0;
    }

    /**
     * Returns the list of items in inventory available for transaction
     *
     * @return L2ItemInstance : items in inventory
     */
    public L2ItemInstance[] getUniqueItems(boolean allowAdena, boolean allowAncientAdena) {
        return getUniqueItems(allowAdena, allowAncientAdena, true);
    }

    public L2ItemInstance[] getUniqueItems(boolean allowAdena, boolean allowAncientAdena, boolean onlyAvailable) {
        FastList<L2ItemInstance> list = FastList.newInstance();
        for (L2ItemInstance item : _items) {
            if (item == null) {
                continue;
            }
            if (!allowAdena && item.getItemId() == ADENA_ID) {
                continue;
            }
            if (!allowAncientAdena && item.getItemId() == 5575) {
                continue;
            }

            boolean isDuplicate = false;
            for (L2ItemInstance litem : list) {
                if (litem.getItemId() == item.getItemId()) {
                    isDuplicate = true;
                    break;
                }
            }
            if (!isDuplicate && (!onlyAvailable || item.isSellable() && item.isAvailable(_owner, false, false))) {
                list.add(item);
            }
        }

        L2ItemInstance[] result = list.toArray(new L2ItemInstance[list.size()]);
        FastList.recycle(list);

        return result;
    }

    /**
     * Returns the list of items in inventory available for transaction
     * Allows an item to appear twice if and only if there is a difference in enchantment level.
     *
     * @return L2ItemInstance : items in inventory
     */
    public L2ItemInstance[] getUniqueItemsByEnchantLevel(boolean allowAdena, boolean allowAncientAdena,
            boolean onlyAvailable) {
        FastList<L2ItemInstance> list = FastList.newInstance();
        for (L2ItemInstance item : _items) {
            if (item == null) {
                continue;
            }
            if (!allowAdena && item.getItemId() == ADENA_ID) {
                continue;
            }
            if (!allowAncientAdena && item.getItemId() == 5575) {
                continue;
            }

            boolean isDuplicate = false;
            for (L2ItemInstance litem : list) {
                if (litem.getItemId() == item.getItemId() && litem.getEnchantLevel() == item.getEnchantLevel()) {
                    isDuplicate = true;
                    break;
                }
            }
            if (!isDuplicate && (!onlyAvailable || item.isAvailable(_owner, false, false))) {
                list.add(item);
            }
        }

        L2ItemInstance[] result = list.toArray(new L2ItemInstance[list.size()]);
        FastList.recycle(list);

        return result;
    }

    public L2ItemInstance[] getAllItemsByItemId(int itemId) {
        return getAllItemsByItemId(itemId, true);
    }

    /**
     * Returns the list of all items in inventory that have a given item id.
     *
     * @param itemId          : ID of item
     * @param includeEquipped : include equipped items
     * @return L2ItemInstance[] : matching items from inventory
     */
    public L2ItemInstance[] getAllItemsByItemId(int itemId, boolean includeEquipped) {
        FastList<L2ItemInstance> list = FastList.newInstance();
        for (L2ItemInstance item : _items) {
            if (item == null) {
                continue;
            }

            if (item.getItemId() == itemId && (includeEquipped || !item.isEquipped())) {
                list.add(item);
            }
        }

        L2ItemInstance[] result = list.toArray(new L2ItemInstance[list.size()]);
        FastList.recycle(list);

        return result;
    }

    /**
     * @see PcInventory#getAllItemsByItemId(int, int, boolean)
     */
    public L2ItemInstance[] getAllItemsByItemId(int itemId, int enchantment) {
        return getAllItemsByItemId(itemId, enchantment, true);
    }

    /**
     * Returns the list of all items in inventory that have a given item id AND a given enchantment level.
     *
     * @param itemId          : ID of item
     * @param enchantment     : enchant level of item
     * @param includeEquipped : include equipped items
     * @return L2ItemInstance[] : matching items from inventory
     */
    public L2ItemInstance[] getAllItemsByItemId(int itemId, int enchantment, boolean includeEquipped) {
        FastList<L2ItemInstance> list = FastList.newInstance();
        for (L2ItemInstance item : _items) {
            if (item == null) {
                continue;
            }

            if (item.getItemId() == itemId && item.getEnchantLevel() == enchantment
                    && (includeEquipped || !item.isEquipped())) {
                list.add(item);
            }
        }

        L2ItemInstance[] result = list.toArray(new L2ItemInstance[list.size()]);
        FastList.recycle(list);

        return result;
    }

    /**
     * @returns the list of items in inventory available for transaction
     */
    public L2ItemInstance[] getAvailableItems(boolean allowAdena, boolean allowNonTradeable, boolean feightable) {
        FastList<L2ItemInstance> list = FastList.newInstance();
        for (L2ItemInstance item : _items) {
            if (item == null) {
            } else if (feightable && item.getItemLocation() == ItemLocation.INVENTORY && item.isFreightable()
                    || item.isAvailable(_owner, allowAdena, allowNonTradeable)
                            && canManipulateWithItemId(item.getItemId())) {
                list.add(item);
            }
        }

        L2ItemInstance[] result = list.toArray(new L2ItemInstance[list.size()]);
        FastList.recycle(list);

        return result;
    }

    /**
     * @return all augmented items
     */
    public L2ItemInstance[] getAugmentedItems() {
        FastList<L2ItemInstance> list = FastList.newInstance();
        list.addAll(
                _items.stream().filter(item -> item != null && item.isAugmented()).collect(Collectors.toList()));

        L2ItemInstance[] result = list.toArray(new L2ItemInstance[list.size()]);
        FastList.recycle(list);

        return result;
    }

    /**
     * @return all element items
     */
    public L2ItemInstance[] getElementItems() {
        FastList<L2ItemInstance> list = FastList.newInstance();
        list.addAll(_items.stream().filter(item -> item != null && item.getElementals() != null)
                .collect(Collectors.toList()));

        L2ItemInstance[] result = list.toArray(new L2ItemInstance[list.size()]);
        FastList.recycle(list);

        return result;
    }

    /**
     * @param tradeList
     * @return the list of items in inventory available for transaction adjusted by tradeList
     */
    public TradeItem[] getAvailableItems(TradeList tradeList) {
        FastList<TradeItem> list = FastList.newInstance();
        _items.stream().filter(item -> item != null && item.isAvailable(_owner, false, false)).forEach(item -> {
            TradeItem adjItem = tradeList.adjustAvailableItem(item);
            if (adjItem != null) {
                list.add(adjItem);
            }
        });

        TradeItem[] result = list.toArray(new TradeItem[list.size()]);
        FastList.recycle(list);

        return result;
    }

    /**
     * Adjust TradeItem according his status in inventory
     *
     * @param item : L2ItemInstance to be adjusten
     * @return TradeItem representing adjusted item
     */
    public void adjustAvailableItem(TradeItem item) {
        boolean notAllEquipped = false;
        for (L2ItemInstance adjItem : getItemsByItemId(item.getItem().getItemId())) {
            if (adjItem.isEquipable()) {
                if (!adjItem.isEquipped()) {
                    notAllEquipped |= true;
                }
            } else {
                notAllEquipped |= true;
                break;
            }
        }
        if (notAllEquipped) {
            L2ItemInstance adjItem = getItemByItemId(item.getItem().getItemId());
            item.setObjectId(adjItem.getObjectId());
            item.setEnchantLevel(adjItem.getEnchantLevel());

            if (adjItem.getCount() < item.getCount()) {
                item.setCount(adjItem.getCount());
            }

            return;
        }

        item.setCount(0);
    }

    /**
     * Adds adena to PCInventory
     *
     * @param process   : String Identifier of process triggering this action
     * @param count     : int Quantity of adena to be added
     * @param actor     : L2PcInstance Player requesting the item add
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     */
    public void addAdena(ProcessType process, long count, L2PcInstance actor, Object reference) {
        if (count > 0) {
            addItem(process, ADENA_ID, count, actor, reference);
        }
    }

    /**
     * Removes adena to PCInventory
     *
     * @param process   : String Identifier of process triggering this action
     * @param count     : int Quantity of adena to be removed
     * @param actor     : L2PcInstance Player requesting the item add
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     * @return boolean : true if adena was reduced
     */
    public boolean reduceAdena(ProcessType process, long count, L2PcInstance actor, Object reference) {
        if (count > 0) {
            return destroyItemByItemId(process, ADENA_ID, count, actor, reference) != null;
        }
        return false;
    }

    /**
     * Adds specified amount of ancient adena to player inventory.
     *
     * @param process   : String Identifier of process triggering this action
     * @param count     : int Quantity of adena to be added
     * @param actor     : L2PcInstance Player requesting the item add
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     */
    public void addAncientAdena(ProcessType process, long count, L2PcInstance actor, Object reference) {
        if (count > 0) {
            addItem(process, ANCIENT_ADENA_ID, count, actor, reference);
        }
    }

    /**
     * Removes specified amount of ancient adena from player inventory.
     *
     * @param process   : String Identifier of process triggering this action
     * @param count     : int Quantity of adena to be removed
     * @param actor     : L2PcInstance Player requesting the item add
     * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
     * @return boolean : true if adena was reduced
     */
    public boolean reduceAncientAdena(ProcessType process, long count, L2PcInstance actor, Object reference) {
        if (count > 0) {
            return destroyItemByItemId(process, ANCIENT_ADENA_ID, count, actor, reference) != null;
        }
        return false;
    }

    public void addItem(ProcessType process, int itemId, long count, L2PcInstance actor, Object reference,
            boolean sendMessage) {
        if (addItem(process, itemId, count, actor, reference) != null && sendMessage) {
            // If item for reward is gold, send message of gold reward to client
            if (itemId == ADENA_ID) {
                SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.EARNED_S1_ADENA);
                smsg.addItemNumber(count);
                actor.sendPacket(smsg);
            }
            // Otherwise, send message of object reward to client
            else {
                if (count > 1) {
                    SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.EARNED_S2_S1_S);
                    smsg.addItemName(itemId);
                    smsg.addItemNumber(count);
                    actor.sendPacket(smsg);
                } else {
                    SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.EARNED_ITEM_S1);
                    smsg.addItemName(itemId);
                    actor.sendPacket(smsg);
                }
            }
        }
    }

    /**
     * @param itemList the items that needs to be validated.
     * @param sendMessage if {@code true} will send a message of inventory full.
     * @param sendSkillMessage if {@code true} will send a message of skill not available.
     * @return {@code true} if the inventory isn't full after taking new items and items weight add to current load doesn't exceed max weight load.
     */
    public boolean checkInventorySlotsAndWeight(List<L2Item> itemList, boolean sendMessage,
            boolean sendSkillMessage) {
        int lootWeight = 0;
        int requiredSlots = 0;
        if (itemList != null) {
            for (L2Item item : itemList) {
                //If the item is not stackable or is stackable and not present in inventory, will need a slot.
                if (!item.isStackable() || getInventoryItemCount(item.getItemId(), -1) <= 0) {
                    requiredSlots++;
                }
                lootWeight += item.getWeight();
            }
        }

        boolean inventoryStatusOK = validateCapacity(requiredSlots) && validateWeight(lootWeight);
        if (!inventoryStatusOK && sendMessage) {
            _owner.sendPacket(SystemMessageId.SLOTS_FULL);
            if (sendSkillMessage) {
                _owner.sendPacket(SystemMessageId.WEIGHT_EXCEEDED_SKILL_UNAVAILABLE);
            }
        }
        return inventoryStatusOK;
    }

    /**
     * If the item is not stackable or is stackable and not present in inventory, will need a slot.
     * @param item the item to validate.
     * @return {@code true} if there is enough room to add the item inventory.
     */
    public boolean validateCapacity(L2ItemInstance item) {
        int slots = 0;
        if (!item.isStackable() || getInventoryItemCount(item.getItemId(), -1) <= 0
                || item.getItemType() != L2EtcItemType.HERB) {
            slots++;
        }
        return validateCapacity(slots, item.isQuestItem());
    }

    /**
     * If the item is not stackable or is stackable and not present in inventory, will need a slot.
     * @param itemId the item Id for the item to validate.
     * @return {@code true} if there is enough room to add the item inventory.
     */
    public boolean validateCapacityByItemId(int itemId) {
        int slots = 0;
        L2ItemInstance invItem = getItemByItemId(itemId);
        if (invItem == null || !invItem.isStackable()) {
            slots++;
        }
        return validateCapacity(slots, ItemTable.getInstance().getTemplate(itemId).isQuestItem());
    }

    public boolean validateCapacity(long slots, boolean questItem) {
        return !questItem ? _items.size() - _questSlots + slots <= _owner.getInventoryLimit()
                : _questSlots + slots <= _owner.getQuestInventoryLimit();
    }

    /**
     * Set inventory block for specified IDs<br>
     * array reference is used for {@link PcInventory#_blockItems}
     *
     * @param items array of Ids to block/allow
     * @param mode  blocking mode {@link PcInventory#_blockMode}
     */
    public void setInventoryBlock(int[] items, int mode) {
        _blockMode = mode;
        _blockItems = items;

        _owner.sendPacket(new ItemList(_owner, false));
    }

    /**
     * Unblock blocked itemIds
     */
    public void unblock() {
        _blockMode = -1;
        _blockItems = null;

        _owner.sendPacket(new ItemList(_owner, false));
    }

    /**
     * Check if player inventory is in block mode.
     *
     * @return {@code true} if some itemIds blocked
     */
    public boolean hasInventoryBlock() {
        return _blockMode > -1 && _blockItems != null && _blockItems.length > 0;
    }

    /**
     * Block all player items
     */
    public void blockAllItems() {
        // temp fix, some id must be sended
        setInventoryBlock(new int[] { ItemTable.getInstance().getArraySize() + 2 }, 1);
    }

    /**
     * @return int block mode
     */
    public int getBlockMode() {
        return _blockMode;
    }

    /**
     * @return TIntArrayList with blocked item ids
     */
    public int[] getBlockItems() {
        return _blockItems;
    }

    /**
     * Check if player can use item by itemid
     *
     * @param itemId int
     * @return true if can use
     */
    public boolean canManipulateWithItemId(int itemId) {
        return !(_blockMode == 0 && ArrayUtils.contains(_blockItems, itemId)
                || _blockMode == 1 && !ArrayUtils.contains(_blockItems, itemId));
    }

    public int getSize(boolean quest) {
        return quest ? _questSlots : getSize() - _questSlots;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + '[' + _owner + ']';
    }

    /**
     * Apply skills of inventory items
     */
    public void applyItemSkills() {
        for (L2ItemInstance item : _items) {
            item.giveSkillsToOwner();
        }
    }
}