From 45c769b20e3b59446b58e182988547e6fe8507e0 Mon Sep 17 00:00:00 2001
From: Andrei Karas <akaras@inbox.ru>
Date: Thu, 7 Jan 2016 14:48:13 +0300
Subject: Move invetory into inventory directory.

---
 src/CMakeLists.txt                        |   4 +-
 src/Makefile.am                           |   4 +-
 src/actions/commands.cpp                  |   3 +-
 src/gui/shortcut/dropshortcut.cpp         |   3 +-
 src/gui/shortcut/itemshortcut.cpp         |   3 +-
 src/gui/windows/buyingstoreselldialog.cpp |   3 +-
 src/gui/windows/inventorywindow.h         |   2 +-
 src/gui/windows/ministatuswindow.cpp      |   3 +-
 src/gui/windows/outfitwindow.cpp          |   3 +-
 src/gui/windows/shopwindow.cpp            |   3 +-
 src/inventory.cpp                         | 462 ------------------------------
 src/inventory.h                           | 203 -------------
 src/net/ea/buysellrecv.cpp                |   3 +-
 src/net/eathena/buyingstorerecv.cpp       |   3 +-
 src/net/eathena/traderecv.cpp             |   3 +-
 src/net/inventoryhandler.h                |   2 +-
 src/net/tmwa/traderecv.cpp                |   3 +-
 src/resources/inventory/inventory.cpp     | 462 ++++++++++++++++++++++++++++++
 src/resources/inventory/inventory.h       | 203 +++++++++++++
 19 files changed, 693 insertions(+), 682 deletions(-)
 delete mode 100644 src/inventory.cpp
 delete mode 100644 src/inventory.h
 create mode 100644 src/resources/inventory/inventory.cpp
 create mode 100644 src/resources/inventory/inventory.h

(limited to 'src')

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6ba5429fa..48468b421 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -947,8 +947,8 @@ SET(SRCS
     particle/imageparticle.h
     resources/sprite/imagesprite.cpp
     resources/sprite/imagesprite.h
-    inventory.cpp
-    inventory.h
+    resources/inventory/inventory.cpp
+    resources/inventory/inventory.h
     resources/item/item.cpp
     resources/item/item.h
     itemcolormanager.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index cf4280eca..00ad71036 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -717,8 +717,8 @@ manaplus_SOURCES += main.cpp \
 	      client.h \
 	      resources/sprite/imagesprite.cpp \
 	      resources/sprite/imagesprite.h \
-	      inventory.cpp \
-	      inventory.h \
+	      resources/inventory/inventory.cpp \
+	      resources/inventory/inventory.h \
 	      textcommand.cpp \
 	      textcommand.h \
 	      resources/item/item.cpp \
diff --git a/src/actions/commands.cpp b/src/actions/commands.cpp
index 84001d989..95be13364 100644
--- a/src/actions/commands.cpp
+++ b/src/actions/commands.cpp
@@ -23,7 +23,6 @@
 #include "actormanager.h"
 #include "configuration.h"
 #include "game.h"
-#include "inventory.h"
 #include "party.h"
 
 #include "actions/actiondef.h"
@@ -64,6 +63,8 @@
 #include "resources/iteminfo.h"
 #include "resources/chatobject.h"
 
+#include "resources/inventory/inventory.h"
+
 #include "resources/item/item.h"
 
 #include "utils/chatutils.h"
diff --git a/src/gui/shortcut/dropshortcut.cpp b/src/gui/shortcut/dropshortcut.cpp
index d0d85a253..380ff6a35 100644
--- a/src/gui/shortcut/dropshortcut.cpp
+++ b/src/gui/shortcut/dropshortcut.cpp
@@ -22,12 +22,13 @@
 
 #include "gui/shortcut/dropshortcut.h"
 
-#include "inventory.h"
 #include "settings.h"
 
 #include "being/localplayer.h"
 #include "being/playerinfo.h"
 
+#include "resources/inventory/inventory.h"
+
 #include "resources/item/item.h"
 
 #include "net/packetlimiter.h"
diff --git a/src/gui/shortcut/itemshortcut.cpp b/src/gui/shortcut/itemshortcut.cpp
index d4c7874cf..7166fddf5 100644
--- a/src/gui/shortcut/itemshortcut.cpp
+++ b/src/gui/shortcut/itemshortcut.cpp
@@ -23,7 +23,6 @@
 #include "gui/shortcut/itemshortcut.h"
 
 #include "configuration.h"
-#include "inventory.h"
 #include "spellmanager.h"
 
 #include "being/playerinfo.h"
@@ -34,6 +33,8 @@
 
 #include "gui/windows/skilldialog.h"
 
+#include "resources/inventory/inventory.h"
+
 #include "resources/item/item.h"
 
 #include "debug.h"
diff --git a/src/gui/windows/buyingstoreselldialog.cpp b/src/gui/windows/buyingstoreselldialog.cpp
index b9aad7e54..205734248 100644
--- a/src/gui/windows/buyingstoreselldialog.cpp
+++ b/src/gui/windows/buyingstoreselldialog.cpp
@@ -23,7 +23,6 @@
 #include "gui/windows/buyingstoreselldialog.h"
 
 #include "actormanager.h"
-#include "inventory.h"
 
 #include "being/playerinfo.h"
 
@@ -33,6 +32,8 @@
 
 #include "net/buyingstorehandler.h"
 
+#include "resources/inventory/inventory.h"
+
 #include "resources/item/shopitem.h"
 
 #include "debug.h"
diff --git a/src/gui/windows/inventorywindow.h b/src/gui/windows/inventorywindow.h
index 64e8cceb4..6c02e4304 100644
--- a/src/gui/windows/inventorywindow.h
+++ b/src/gui/windows/inventorywindow.h
@@ -23,7 +23,7 @@
 #ifndef GUI_WINDOWS_INVENTORYWINDOW_H
 #define GUI_WINDOWS_INVENTORYWINDOW_H
 
-#include "inventory.h"
+#include "resources/inventory/inventory.h"
 
 #include "gui/widgets/window.h"
 
diff --git a/src/gui/windows/ministatuswindow.cpp b/src/gui/windows/ministatuswindow.cpp
index 98a45effc..3ca9b8e35 100644
--- a/src/gui/windows/ministatuswindow.cpp
+++ b/src/gui/windows/ministatuswindow.cpp
@@ -23,7 +23,6 @@
 #include "gui/windows/ministatuswindow.h"
 
 #include "configuration.h"
-#include "inventory.h"
 
 #include "being/localplayer.h"
 #include "being/playerinfo.h"
@@ -42,6 +41,8 @@
 
 #include "net/playerhandler.h"
 
+#include "resources/inventory/inventory.h"
+
 #include "resources/sprite/animatedsprite.h"
 
 #include "utils/delete2.h"
diff --git a/src/gui/windows/outfitwindow.cpp b/src/gui/windows/outfitwindow.cpp
index 8034ef032..73cc5101d 100644
--- a/src/gui/windows/outfitwindow.cpp
+++ b/src/gui/windows/outfitwindow.cpp
@@ -25,7 +25,6 @@
 #include "configuration.h"
 #include "dragdrop.h"
 #include "game.h"
-#include "inventory.h"
 
 #include "being/playerinfo.h"
 
@@ -48,6 +47,8 @@
 
 #include "utils/gettext.h"
 
+#include "resources/inventory/inventory.h"
+
 #include <sstream>
 
 #include "debug.h"
diff --git a/src/gui/windows/shopwindow.cpp b/src/gui/windows/shopwindow.cpp
index c6388c50e..7c75c4f92 100644
--- a/src/gui/windows/shopwindow.cpp
+++ b/src/gui/windows/shopwindow.cpp
@@ -60,7 +60,6 @@
 #include "soundmanager.h"
 #endif
 #include "configuration.h"
-#include "inventory.h"
 #include "settings.h"
 
 #include "being/localplayer.h"
@@ -86,6 +85,8 @@
 #include "resources/iteminfo.h"
 #endif
 
+#include "resources/inventory/inventory.h"
+
 #include "resources/item/shopitem.h"
 
 #include <sys/stat.h>
diff --git a/src/inventory.cpp b/src/inventory.cpp
deleted file mode 100644
index 82674ef0f..000000000
--- a/src/inventory.cpp
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- *  The ManaPlus Client
- *  Copyright (C) 2004-2009  The Mana World Development Team
- *  Copyright (C) 2009-2010  The Mana Developers
- *  Copyright (C) 2011-2016  The ManaPlus Developers
- *
- *  This file is part of The ManaPlus Client.
- *
- *  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 2 of the License, or
- *  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/>.
- */
-
-#include "inventory.h"
-
-#include "logger.h"
-
-#include "being/playerinfo.h"
-
-#include "net/inventoryhandler.h"
-
-#include "resources/iteminfo.h"
-
-#include "resources/item/item.h"
-
-#include "listeners/inventorylistener.h"
-
-#include "utils/delete2.h"
-#include "utils/gettext.h"
-#include "utils/stringutils.h"
-
-#include <algorithm>
-
-#include "debug.h"
-
-namespace
-{
-    struct SlotUsed final
-    {
-        bool operator()(const Item *const item) const
-        {
-            return item && item->mId >= 0 && item->mQuantity > 0;
-        }
-        typedef Item *argument_type;
-    };
-}  // namespace
-
-Inventory::Inventory(const InventoryTypeT type, const int size1) :
-    mInventoryListeners(),
-    mVirtualRemove(),
-    mType(type),
-    mSize(size1 == -1 ? static_cast<unsigned>(
-          inventoryHandler->getSize(type))
-          : static_cast<unsigned>(size1)),
-    mItems(new Item*[mSize]),
-    mUsed(0)
-{
-    std::fill_n(mItems, mSize, static_cast<Item*>(nullptr));
-}
-
-Inventory::~Inventory()
-{
-    for (unsigned i = 0; i < mSize; i++)
-        delete mItems[i];
-
-    delete [] mItems;
-    mItems = nullptr;
-}
-
-Item *Inventory::getItem(const int index) const
-{
-    if (index < 0 || index >= static_cast<int>(mSize) || !mItems[index]
-        || mItems[index]->mQuantity <= 0)
-    {
-        return nullptr;
-    }
-
-    return mItems[index];
-}
-
-Item *Inventory::findItem(const int itemId,
-                          const ItemColor color) const
-{
-    for (unsigned i = 0; i < mSize; i++)
-    {
-        Item *const item = mItems[i];
-        if (item && item->mId == itemId)
-        {
-            if (color == ItemColor_zero ||
-                item->mColor == color ||
-                (color == ItemColor_one &&
-                item->mColor <= ItemColor_one))
-            {
-                return item;
-            }
-        }
-    }
-
-    return nullptr;
-}
-
-int Inventory::addItem(const int id,
-                       const int type,
-                       const int quantity,
-                       const uint8_t refine,
-                       const ItemColor color,
-                       const Identified identified,
-                       const Damaged damaged,
-                       const Favorite favorite,
-                       const Equipm equipment,
-                       const Equipped equipped)
-{
-    const int slot = getFreeSlot();
-    setItem(slot, id, type, quantity, refine, color,
-        identified, damaged, favorite, equipment, equipped);
-    return slot;
-}
-
-void Inventory::setItem(const int index,
-                        const int id,
-                        const int type,
-                        const int quantity,
-                        const uint8_t refine,
-                        const ItemColor color,
-                        const Identified identified,
-                        const Damaged damaged,
-                        const Favorite favorite,
-                        const Equipm equipment,
-                        const Equipped equipped)
-{
-    if (index < 0 || index >= static_cast<int>(mSize))
-    {
-        logger->log("Warning: invalid inventory index: %d", index);
-        return;
-    }
-
-    Item *const item1 = mItems[index];
-    if (!item1 && id > 0)
-    {
-        Item *const item = new Item(id, type, quantity, refine, color,
-            identified, damaged, favorite, equipment, equipped);
-        item->setInvIndex(index);
-        mItems[index] = item;
-        mUsed++;
-        distributeSlotsChangedEvent();
-    }
-    else if (id > 0 && item1)
-    {
-        item1->setId(id, color);
-        item1->setQuantity(quantity);
-        item1->setRefine(refine);
-        item1->setEquipment(equipment);
-        item1->setIdentified(identified);
-        item1->setDamaged(damaged);
-        item1->setFavorite(favorite);
-    }
-    else if (item1)
-    {
-        removeItemAt(index);
-    }
-}
-
-void Inventory::setCards(const int index,
-                         const int *const cards,
-                         const int size) const
-{
-    if (index < 0 || index >= static_cast<int>(mSize))
-    {
-        logger->log("Warning: invalid inventory index: %d", index);
-        return;
-    }
-
-    Item *const item1 = mItems[index];
-    item1->setCards(cards, size);
-}
-
-void Inventory::clear()
-{
-    for (unsigned i = 0; i < mSize; i++)
-        removeItemAt(i);
-}
-
-void Inventory::removeItem(const int id)
-{
-    for (unsigned i = 0; i < mSize; i++)
-    {
-        const Item *const item = mItems[i];
-        if (item && item->mId == id)
-            removeItemAt(i);
-    }
-}
-
-void Inventory::removeItemAt(const int index)
-{
-    if (!mItems[index])
-        return;
-    delete2(mItems[index]);
-    mUsed--;
-    if (mUsed < 0)  // Already at 0, no need to distribute event
-        mUsed = 0;
-    else
-        distributeSlotsChangedEvent();
-}
-
-bool Inventory::contains(const Item *const item) const
-{
-    if (!item)
-        return false;
-
-    const int id = item->mId;
-    for (unsigned i = 0; i < mSize; i++)
-    {
-        const Item *const item1 = mItems[i];
-        if (item1 && item1->mId == id)
-            return true;
-    }
-
-    return false;
-}
-
-int Inventory::getFreeSlot() const
-{
-    Item **const i = std::find_if(mItems, mItems + mSize,
-        std::not1(SlotUsed()));
-    return (i == mItems + mSize) ? -1
-        : static_cast<int>(i - mItems);
-}
-
-int Inventory::getLastUsedSlot() const
-{
-    for (int i = mSize - 1; i >= 0; i--)
-    {
-        if (SlotUsed()(mItems[i]))
-            return i;
-    }
-
-    return -1;
-}
-
-void Inventory::addInventoyListener(InventoryListener* const listener)
-{
-    mInventoryListeners.push_back(listener);
-}
-
-void Inventory::removeInventoyListener(InventoryListener* const listener)
-{
-    mInventoryListeners.remove(listener);
-}
-
-void Inventory::distributeSlotsChangedEvent()
-{
-    FOR_EACH (InventoryListenerList::const_iterator, i, mInventoryListeners)
-        (*i)->slotsChanged(this);
-}
-
-const Item *Inventory::findItemBySprite(std::string spritePath,
-                                        const GenderT gender,
-                                        const BeingTypeId race) const
-{
-    spritePath = removeSpriteIndex(spritePath);
-
-    const std::string spritePathShort = extractNameFromSprite(spritePath);
-    int partialIndex = -1;
-
-    for (unsigned i = 0; i < mSize; i++)
-    {
-        const Item *const item = mItems[i];
-        if (item)
-        {
-            std::string path = item->getInfo().getSprite(gender, race);
-            if (!path.empty())
-            {
-                path = removeSpriteIndex(path);
-                if (spritePath == path)
-                    return item;
-
-                path = extractNameFromSprite(path);
-                if (spritePathShort == path)
-                    partialIndex = i;
-            }
-        }
-    }
-    if (partialIndex != -1)
-        return mItems[partialIndex];
-
-    return nullptr;
-}
-
-std::string Inventory::getName() const
-{
-    switch (mType)
-    {
-        case InventoryType::Inventory:
-#ifdef EATHENA_SUPPORT
-        case InventoryType::Vending:
-#endif
-        case InventoryType::TypeEnd:
-        default:
-        {
-            // TRANSLATORS: inventory type name
-            return N_("Inventory");
-        }
-        case InventoryType::Storage:
-        {
-            // TRANSLATORS: inventory type name
-            return N_("Storage");
-        }
-        case InventoryType::Npc:
-        {
-            // TRANSLATORS: inventory type name
-            return N_("Npc");
-        }
-#ifdef EATHENA_SUPPORT
-        case InventoryType::Cart:
-        {
-            // TRANSLATORS: inventory type name
-            return N_("Cart");
-        }
-        case InventoryType::Mail:
-        {
-            // TRANSLATORS: inventory type name
-            return N_("Mail");
-        }
-#endif
-        case InventoryType::Trade:
-        {
-            // TRANSLATORS: inventory type name
-            return N_("Trade");
-        }
-    }
-}
-
-void Inventory::resize(const unsigned int newSize)
-{
-    clear();
-    if (mSize == newSize)
-        return;
-
-    for (unsigned i = 0; i < mSize; i++)
-        delete mItems[i];
-    delete [] mItems;
-
-    mSize = newSize;
-    mItems = new Item*[static_cast<size_t>(mSize)];
-    std::fill_n(mItems, mSize, static_cast<Item*>(nullptr));
-}
-
-int Inventory::findIndexByTag(const int tag) const
-{
-    for (unsigned i = 0; i < mSize; i++)
-    {
-        const Item *const item = mItems[i];
-        if (item && item->mTag == tag)
-            return i;
-    }
-
-    return -1;
-}
-
-bool Inventory::addVirtualItem(const Item *const item,
-                               int index)
-{
-    if (item && !PlayerInfo::isItemProtected(item->getId()))
-    {
-        if (index >= 0 && index < static_cast<int>(mSize))
-        {
-            if (mItems[index] != nullptr)
-                return false;
-            setItem(index,
-                item->getId(),
-                item->getType(),
-                1,
-                1,
-                item->getColor(),
-                item->getIdentified(),
-                item->getDamaged(),
-                item->getFavorite(),
-                Equipm_false,
-                Equipped_false);
-        }
-        else
-        {
-            index = addItem(item->getId(),
-                item->getType(),
-                1,
-                1,
-                item->getColor(),
-                item->getIdentified(),
-                item->getDamaged(),
-                item->getFavorite(),
-                Equipm_false,
-                Equipped_false);
-        }
-        if (index == -1)
-            return false;
-
-        Item *const item2 = getItem(index);
-        if (item2)
-            item2->setTag(item->getInvIndex());
-        return true;
-    }
-    return false;
-}
-
-void Inventory::virtualRemove(Item *const item,
-                              const int amount)
-{
-    if (!item || item->mQuantity < amount)
-        return;
-
-    const int index = item->getInvIndex();
-    const IntMapCIter it = mVirtualRemove.find(index);
-    if (it == mVirtualRemove.end())
-        mVirtualRemove[index] = amount;
-    else
-        mVirtualRemove[index] += amount;
-    item->mQuantity -= amount;
-}
-
-void Inventory::restoreVirtuals()
-{
-    const int sz = static_cast<int>(mSize);
-
-    logger->log("Inventory::restoreVirtuals 1");
-    FOR_EACH (IntMapCIter, it, mVirtualRemove)
-    {
-        logger->log("Inventory::restoreVirtuals 2");
-        const int index = (*it).first;
-        if (index < 0 || index >= sz)
-            continue;
-        Item *const item = mItems[index];
-        if (!item)
-            continue;
-        item->mQuantity += (*it).second;
-    }
-    mVirtualRemove.clear();
-}
-
-void Inventory::virtualRestore(const Item *const item,
-                               const int amount)
-{
-    const int index = item->getTag();
-    const IntMapCIter it = mVirtualRemove.find(index);
-    if (it != mVirtualRemove.end())
-    {
-        mVirtualRemove[index] -= amount;
-        if (mVirtualRemove[index] < 0)
-            mVirtualRemove.erase(index);
-        if (index < 0 || index >= static_cast<int>(mSize) || !mItems[index])
-            return;
-        mItems[index]->mQuantity += amount;
-    }
-}
diff --git a/src/inventory.h b/src/inventory.h
deleted file mode 100644
index 0775655fc..000000000
--- a/src/inventory.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- *  The ManaPlus Client
- *  Copyright (C) 2004-2009  The Mana World Development Team
- *  Copyright (C) 2009-2010  The Mana Developers
- *  Copyright (C) 2011-2016  The ManaPlus Developers
- *
- *  This file is part of The ManaPlus Client.
- *
- *  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 2 of the License, or
- *  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/>.
- */
-
-#ifndef INVENTORY_H
-#define INVENTORY_H
-
-#include "enums/inventorytype.h"
-
-#include "enums/simpletypes/beingtypeid.h"
-#include "enums/simpletypes/damaged.h"
-#include "enums/simpletypes/equipm.h"
-#include "enums/simpletypes/equipped.h"
-#include "enums/simpletypes/favorite.h"
-#include "enums/simpletypes/identified.h"
-#include "enums/simpletypes/itemcolor.h"
-
-#include "enums/being/gender.h"
-
-#include "utils/intmap.h"
-
-#include <list>
-#include <string>
-
-#include "localconsts.h"
-
-class InventoryListener;
-class Item;
-
-class Inventory final
-{
-    public:
-        A_DELETE_COPY(Inventory)
-
-        static const int NO_SLOT_INDEX = -1; /**< Slot has no index. */
-
-        /**
-         * Constructor.
-         *
-         * @param size the number of items that fit in the inventory
-         */
-        explicit Inventory(const InventoryTypeT type,
-                           const int size = -1);
-
-        /**
-         * Destructor.
-         */
-        ~Inventory();
-
-        /**
-         * Returns the size that this instance is configured for.
-         */
-        unsigned getSize() const A_WARN_UNUSED
-        { return mSize; }
-
-        /**
-         * Returns the item at the specified index.
-         */
-        Item *getItem(const int index) const A_WARN_UNUSED;
-
-        /**
-         * Searches for the specified item by it's id.
-         *
-         * @param itemId The id of the item to be searched.
-         * @param color The color of the item to be searched.
-         * @return Item found on success, NULL on failure.
-         */
-        Item *findItem(const int itemId,
-                       const ItemColor color) const A_WARN_UNUSED;
-
-        /**
-         * Adds a new item in a free slot.
-         */
-        int addItem(const int id,
-                    const int type,
-                    const int quantity,
-                    const uint8_t refine,
-                    const ItemColor color,
-                    const Identified identified,
-                    const Damaged damaged,
-                    const Favorite favorite,
-                    const Equipm equipment,
-                    const Equipped equipped);
-
-        /**
-         * Sets the item at the given position.
-         */
-        void setItem(const int index,
-                     const int id,
-                     const int type,
-                     const int quantity,
-                     const uint8_t refine,
-                     const ItemColor color,
-                     const Identified identified,
-                     const Damaged damaged,
-                     const Favorite favorite,
-                     const Equipm equipment,
-                     const Equipped equipped);
-
-        void setCards(const int index,
-                      const int *const cards,
-                      const int size) const;
-
-        /**
-         * Remove a item from the inventory.
-         */
-        void removeItem(const int id);
-
-        /**
-         * Remove the item at the specified index from the inventory.
-         */
-        void removeItemAt(const int index);
-
-        /**
-         * Checks if the given item is in the inventory.
-         */
-        bool contains(const Item *const item) const A_WARN_UNUSED;
-
-        /**
-         * Returns id of next free slot or -1 if all occupied.
-         */
-        int getFreeSlot() const A_WARN_UNUSED;
-
-        /**
-         * Reset all item slots.
-         */
-        void clear();
-
-        /**
-         * Get the number of slots filled with an item
-         */
-        int getNumberOfSlotsUsed() const A_WARN_UNUSED
-        { return mUsed; }
-
-        /**
-         * Returns the index of the last occupied slot or 0 if none occupied.
-         */
-        int getLastUsedSlot() const A_WARN_UNUSED;
-
-        void addInventoyListener(InventoryListener *const listener);
-
-        void removeInventoyListener(InventoryListener *const listener);
-
-        InventoryTypeT getType() const A_WARN_UNUSED
-        { return mType; }
-
-        bool isMainInventory() const A_WARN_UNUSED
-        { return mType == InventoryType::Inventory; }
-
-        const Item *findItemBySprite(std::string spritePath,
-                                     const GenderT gender,
-                                     const BeingTypeId race)
-                                     const A_WARN_UNUSED;
-
-        std::string getName() const A_WARN_UNUSED;
-
-        void resize(const unsigned int newSize);
-
-        int findIndexByTag(const int tag) const;
-
-        bool addVirtualItem(const Item *const item,
-                            int index);
-
-        void virtualRemove(Item *const item,
-                           const int amount);
-
-        void virtualRestore(const Item *const item,
-                            const int amount);
-
-        void restoreVirtuals();
-
-    protected:
-        typedef std::list<InventoryListener*> InventoryListenerList;
-        InventoryListenerList mInventoryListeners;
-
-        void distributeSlotsChangedEvent();
-
-        IntMap mVirtualRemove;
-        InventoryTypeT mType;
-        unsigned mSize; /**< The max number of inventory items */
-        Item **mItems;  /**< The holder of items */
-        int mUsed;      /**< THe number of slots in use */
-};
-
-#endif  // INVENTORY_H
diff --git a/src/net/ea/buysellrecv.cpp b/src/net/ea/buysellrecv.cpp
index 11bec98fb..c4596f3ca 100644
--- a/src/net/ea/buysellrecv.cpp
+++ b/src/net/ea/buysellrecv.cpp
@@ -22,7 +22,6 @@
 
 #include "net/ea/buysellrecv.h"
 
-#include "inventory.h"
 #include "notifymanager.h"
 
 #include "being/playerinfo.h"
@@ -39,6 +38,8 @@
 
 #include "net/messagein.h"
 
+#include "resources/inventory/inventory.h"
+
 #include "resources/item/item.h"
 
 #include "debug.h"
diff --git a/src/net/eathena/buyingstorerecv.cpp b/src/net/eathena/buyingstorerecv.cpp
index e1be1b261..cdb38c04b 100644
--- a/src/net/eathena/buyingstorerecv.cpp
+++ b/src/net/eathena/buyingstorerecv.cpp
@@ -21,7 +21,6 @@
 #include "net/eathena/buyingstorerecv.h"
 
 #include "actormanager.h"
-#include "inventory.h"
 #include "notifymanager.h"
 
 #include "being/localplayer.h"
@@ -41,6 +40,8 @@
 
 #include "net/messagein.h"
 
+#include "resources/inventory/inventory.h"
+
 #include "resources/item/item.h"
 
 #include "debug.h"
diff --git a/src/net/eathena/traderecv.cpp b/src/net/eathena/traderecv.cpp
index 59e63009d..97dc6affd 100644
--- a/src/net/eathena/traderecv.cpp
+++ b/src/net/eathena/traderecv.cpp
@@ -22,7 +22,6 @@
 
 #include "net/eathena/traderecv.h"
 
-#include "inventory.h"
 #include "itemcolormanager.h"
 #include "notifymanager.h"
 
@@ -36,6 +35,8 @@
 
 #include "net/ea/traderecv.h"
 
+#include "resources/inventory/inventory.h"
+
 #include "resources/item/item.h"
 
 #include "debug.h"
diff --git a/src/net/inventoryhandler.h b/src/net/inventoryhandler.h
index 4b052a4fb..2c18d4ead 100644
--- a/src/net/inventoryhandler.h
+++ b/src/net/inventoryhandler.h
@@ -23,7 +23,7 @@
 #ifndef NET_INVENTORYHANDLER_H
 #define NET_INVENTORYHANDLER_H
 
-#include "inventory.h"
+#include "resources/inventory/inventory.h"
 
 namespace Net
 {
diff --git a/src/net/tmwa/traderecv.cpp b/src/net/tmwa/traderecv.cpp
index cc5a27014..48020eca3 100644
--- a/src/net/tmwa/traderecv.cpp
+++ b/src/net/tmwa/traderecv.cpp
@@ -22,7 +22,6 @@
 
 #include "net/tmwa/traderecv.h"
 
-#include "inventory.h"
 #include "notifymanager.h"
 
 #include "being/playerinfo.h"
@@ -40,6 +39,8 @@
 
 #include "net/ea/traderecv.h"
 
+#include "resources/inventory/inventory.h"
+
 #include "resources/item/item.h"
 
 #include "utils/stringutils.h"
diff --git a/src/resources/inventory/inventory.cpp b/src/resources/inventory/inventory.cpp
new file mode 100644
index 000000000..ad44245a1
--- /dev/null
+++ b/src/resources/inventory/inventory.cpp
@@ -0,0 +1,462 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2004-2009  The Mana World Development Team
+ *  Copyright (C) 2009-2010  The Mana Developers
+ *  Copyright (C) 2011-2016  The ManaPlus Developers
+ *
+ *  This file is part of The ManaPlus Client.
+ *
+ *  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 2 of the License, or
+ *  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/>.
+ */
+
+#include "resources/inventory/inventory.h"
+
+#include "logger.h"
+
+#include "being/playerinfo.h"
+
+#include "net/inventoryhandler.h"
+
+#include "resources/iteminfo.h"
+
+#include "resources/item/item.h"
+
+#include "listeners/inventorylistener.h"
+
+#include "utils/delete2.h"
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+
+#include <algorithm>
+
+#include "debug.h"
+
+namespace
+{
+    struct SlotUsed final
+    {
+        bool operator()(const Item *const item) const
+        {
+            return item && item->mId >= 0 && item->mQuantity > 0;
+        }
+        typedef Item *argument_type;
+    };
+}  // namespace
+
+Inventory::Inventory(const InventoryTypeT type, const int size1) :
+    mInventoryListeners(),
+    mVirtualRemove(),
+    mType(type),
+    mSize(size1 == -1 ? static_cast<unsigned>(
+          inventoryHandler->getSize(type))
+          : static_cast<unsigned>(size1)),
+    mItems(new Item*[mSize]),
+    mUsed(0)
+{
+    std::fill_n(mItems, mSize, static_cast<Item*>(nullptr));
+}
+
+Inventory::~Inventory()
+{
+    for (unsigned i = 0; i < mSize; i++)
+        delete mItems[i];
+
+    delete [] mItems;
+    mItems = nullptr;
+}
+
+Item *Inventory::getItem(const int index) const
+{
+    if (index < 0 || index >= static_cast<int>(mSize) || !mItems[index]
+        || mItems[index]->mQuantity <= 0)
+    {
+        return nullptr;
+    }
+
+    return mItems[index];
+}
+
+Item *Inventory::findItem(const int itemId,
+                          const ItemColor color) const
+{
+    for (unsigned i = 0; i < mSize; i++)
+    {
+        Item *const item = mItems[i];
+        if (item && item->mId == itemId)
+        {
+            if (color == ItemColor_zero ||
+                item->mColor == color ||
+                (color == ItemColor_one &&
+                item->mColor <= ItemColor_one))
+            {
+                return item;
+            }
+        }
+    }
+
+    return nullptr;
+}
+
+int Inventory::addItem(const int id,
+                       const int type,
+                       const int quantity,
+                       const uint8_t refine,
+                       const ItemColor color,
+                       const Identified identified,
+                       const Damaged damaged,
+                       const Favorite favorite,
+                       const Equipm equipment,
+                       const Equipped equipped)
+{
+    const int slot = getFreeSlot();
+    setItem(slot, id, type, quantity, refine, color,
+        identified, damaged, favorite, equipment, equipped);
+    return slot;
+}
+
+void Inventory::setItem(const int index,
+                        const int id,
+                        const int type,
+                        const int quantity,
+                        const uint8_t refine,
+                        const ItemColor color,
+                        const Identified identified,
+                        const Damaged damaged,
+                        const Favorite favorite,
+                        const Equipm equipment,
+                        const Equipped equipped)
+{
+    if (index < 0 || index >= static_cast<int>(mSize))
+    {
+        logger->log("Warning: invalid inventory index: %d", index);
+        return;
+    }
+
+    Item *const item1 = mItems[index];
+    if (!item1 && id > 0)
+    {
+        Item *const item = new Item(id, type, quantity, refine, color,
+            identified, damaged, favorite, equipment, equipped);
+        item->setInvIndex(index);
+        mItems[index] = item;
+        mUsed++;
+        distributeSlotsChangedEvent();
+    }
+    else if (id > 0 && item1)
+    {
+        item1->setId(id, color);
+        item1->setQuantity(quantity);
+        item1->setRefine(refine);
+        item1->setEquipment(equipment);
+        item1->setIdentified(identified);
+        item1->setDamaged(damaged);
+        item1->setFavorite(favorite);
+    }
+    else if (item1)
+    {
+        removeItemAt(index);
+    }
+}
+
+void Inventory::setCards(const int index,
+                         const int *const cards,
+                         const int size) const
+{
+    if (index < 0 || index >= static_cast<int>(mSize))
+    {
+        logger->log("Warning: invalid inventory index: %d", index);
+        return;
+    }
+
+    Item *const item1 = mItems[index];
+    item1->setCards(cards, size);
+}
+
+void Inventory::clear()
+{
+    for (unsigned i = 0; i < mSize; i++)
+        removeItemAt(i);
+}
+
+void Inventory::removeItem(const int id)
+{
+    for (unsigned i = 0; i < mSize; i++)
+    {
+        const Item *const item = mItems[i];
+        if (item && item->mId == id)
+            removeItemAt(i);
+    }
+}
+
+void Inventory::removeItemAt(const int index)
+{
+    if (!mItems[index])
+        return;
+    delete2(mItems[index]);
+    mUsed--;
+    if (mUsed < 0)  // Already at 0, no need to distribute event
+        mUsed = 0;
+    else
+        distributeSlotsChangedEvent();
+}
+
+bool Inventory::contains(const Item *const item) const
+{
+    if (!item)
+        return false;
+
+    const int id = item->mId;
+    for (unsigned i = 0; i < mSize; i++)
+    {
+        const Item *const item1 = mItems[i];
+        if (item1 && item1->mId == id)
+            return true;
+    }
+
+    return false;
+}
+
+int Inventory::getFreeSlot() const
+{
+    Item **const i = std::find_if(mItems, mItems + mSize,
+        std::not1(SlotUsed()));
+    return (i == mItems + mSize) ? -1
+        : static_cast<int>(i - mItems);
+}
+
+int Inventory::getLastUsedSlot() const
+{
+    for (int i = mSize - 1; i >= 0; i--)
+    {
+        if (SlotUsed()(mItems[i]))
+            return i;
+    }
+
+    return -1;
+}
+
+void Inventory::addInventoyListener(InventoryListener* const listener)
+{
+    mInventoryListeners.push_back(listener);
+}
+
+void Inventory::removeInventoyListener(InventoryListener* const listener)
+{
+    mInventoryListeners.remove(listener);
+}
+
+void Inventory::distributeSlotsChangedEvent()
+{
+    FOR_EACH (InventoryListenerList::const_iterator, i, mInventoryListeners)
+        (*i)->slotsChanged(this);
+}
+
+const Item *Inventory::findItemBySprite(std::string spritePath,
+                                        const GenderT gender,
+                                        const BeingTypeId race) const
+{
+    spritePath = removeSpriteIndex(spritePath);
+
+    const std::string spritePathShort = extractNameFromSprite(spritePath);
+    int partialIndex = -1;
+
+    for (unsigned i = 0; i < mSize; i++)
+    {
+        const Item *const item = mItems[i];
+        if (item)
+        {
+            std::string path = item->getInfo().getSprite(gender, race);
+            if (!path.empty())
+            {
+                path = removeSpriteIndex(path);
+                if (spritePath == path)
+                    return item;
+
+                path = extractNameFromSprite(path);
+                if (spritePathShort == path)
+                    partialIndex = i;
+            }
+        }
+    }
+    if (partialIndex != -1)
+        return mItems[partialIndex];
+
+    return nullptr;
+}
+
+std::string Inventory::getName() const
+{
+    switch (mType)
+    {
+        case InventoryType::Inventory:
+#ifdef EATHENA_SUPPORT
+        case InventoryType::Vending:
+#endif
+        case InventoryType::TypeEnd:
+        default:
+        {
+            // TRANSLATORS: inventory type name
+            return N_("Inventory");
+        }
+        case InventoryType::Storage:
+        {
+            // TRANSLATORS: inventory type name
+            return N_("Storage");
+        }
+        case InventoryType::Npc:
+        {
+            // TRANSLATORS: inventory type name
+            return N_("Npc");
+        }
+#ifdef EATHENA_SUPPORT
+        case InventoryType::Cart:
+        {
+            // TRANSLATORS: inventory type name
+            return N_("Cart");
+        }
+        case InventoryType::Mail:
+        {
+            // TRANSLATORS: inventory type name
+            return N_("Mail");
+        }
+#endif
+        case InventoryType::Trade:
+        {
+            // TRANSLATORS: inventory type name
+            return N_("Trade");
+        }
+    }
+}
+
+void Inventory::resize(const unsigned int newSize)
+{
+    clear();
+    if (mSize == newSize)
+        return;
+
+    for (unsigned i = 0; i < mSize; i++)
+        delete mItems[i];
+    delete [] mItems;
+
+    mSize = newSize;
+    mItems = new Item*[static_cast<size_t>(mSize)];
+    std::fill_n(mItems, mSize, static_cast<Item*>(nullptr));
+}
+
+int Inventory::findIndexByTag(const int tag) const
+{
+    for (unsigned i = 0; i < mSize; i++)
+    {
+        const Item *const item = mItems[i];
+        if (item && item->mTag == tag)
+            return i;
+    }
+
+    return -1;
+}
+
+bool Inventory::addVirtualItem(const Item *const item,
+                               int index)
+{
+    if (item && !PlayerInfo::isItemProtected(item->getId()))
+    {
+        if (index >= 0 && index < static_cast<int>(mSize))
+        {
+            if (mItems[index] != nullptr)
+                return false;
+            setItem(index,
+                item->getId(),
+                item->getType(),
+                1,
+                1,
+                item->getColor(),
+                item->getIdentified(),
+                item->getDamaged(),
+                item->getFavorite(),
+                Equipm_false,
+                Equipped_false);
+        }
+        else
+        {
+            index = addItem(item->getId(),
+                item->getType(),
+                1,
+                1,
+                item->getColor(),
+                item->getIdentified(),
+                item->getDamaged(),
+                item->getFavorite(),
+                Equipm_false,
+                Equipped_false);
+        }
+        if (index == -1)
+            return false;
+
+        Item *const item2 = getItem(index);
+        if (item2)
+            item2->setTag(item->getInvIndex());
+        return true;
+    }
+    return false;
+}
+
+void Inventory::virtualRemove(Item *const item,
+                              const int amount)
+{
+    if (!item || item->mQuantity < amount)
+        return;
+
+    const int index = item->getInvIndex();
+    const IntMapCIter it = mVirtualRemove.find(index);
+    if (it == mVirtualRemove.end())
+        mVirtualRemove[index] = amount;
+    else
+        mVirtualRemove[index] += amount;
+    item->mQuantity -= amount;
+}
+
+void Inventory::restoreVirtuals()
+{
+    const int sz = static_cast<int>(mSize);
+
+    logger->log("Inventory::restoreVirtuals 1");
+    FOR_EACH (IntMapCIter, it, mVirtualRemove)
+    {
+        logger->log("Inventory::restoreVirtuals 2");
+        const int index = (*it).first;
+        if (index < 0 || index >= sz)
+            continue;
+        Item *const item = mItems[index];
+        if (!item)
+            continue;
+        item->mQuantity += (*it).second;
+    }
+    mVirtualRemove.clear();
+}
+
+void Inventory::virtualRestore(const Item *const item,
+                               const int amount)
+{
+    const int index = item->getTag();
+    const IntMapCIter it = mVirtualRemove.find(index);
+    if (it != mVirtualRemove.end())
+    {
+        mVirtualRemove[index] -= amount;
+        if (mVirtualRemove[index] < 0)
+            mVirtualRemove.erase(index);
+        if (index < 0 || index >= static_cast<int>(mSize) || !mItems[index])
+            return;
+        mItems[index]->mQuantity += amount;
+    }
+}
diff --git a/src/resources/inventory/inventory.h b/src/resources/inventory/inventory.h
new file mode 100644
index 000000000..501141ed8
--- /dev/null
+++ b/src/resources/inventory/inventory.h
@@ -0,0 +1,203 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2004-2009  The Mana World Development Team
+ *  Copyright (C) 2009-2010  The Mana Developers
+ *  Copyright (C) 2011-2016  The ManaPlus Developers
+ *
+ *  This file is part of The ManaPlus Client.
+ *
+ *  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 2 of the License, or
+ *  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/>.
+ */
+
+#ifndef RESOURCES_INVENTORY_INVENTORY_H
+#define RESOURCES_INVENTORY_INVENTORY_H
+
+#include "enums/inventorytype.h"
+
+#include "enums/simpletypes/beingtypeid.h"
+#include "enums/simpletypes/damaged.h"
+#include "enums/simpletypes/equipm.h"
+#include "enums/simpletypes/equipped.h"
+#include "enums/simpletypes/favorite.h"
+#include "enums/simpletypes/identified.h"
+#include "enums/simpletypes/itemcolor.h"
+
+#include "enums/being/gender.h"
+
+#include "utils/intmap.h"
+
+#include <list>
+#include <string>
+
+#include "localconsts.h"
+
+class InventoryListener;
+class Item;
+
+class Inventory final
+{
+    public:
+        A_DELETE_COPY(Inventory)
+
+        static const int NO_SLOT_INDEX = -1; /**< Slot has no index. */
+
+        /**
+         * Constructor.
+         *
+         * @param size the number of items that fit in the inventory
+         */
+        explicit Inventory(const InventoryTypeT type,
+                           const int size = -1);
+
+        /**
+         * Destructor.
+         */
+        ~Inventory();
+
+        /**
+         * Returns the size that this instance is configured for.
+         */
+        unsigned getSize() const A_WARN_UNUSED
+        { return mSize; }
+
+        /**
+         * Returns the item at the specified index.
+         */
+        Item *getItem(const int index) const A_WARN_UNUSED;
+
+        /**
+         * Searches for the specified item by it's id.
+         *
+         * @param itemId The id of the item to be searched.
+         * @param color The color of the item to be searched.
+         * @return Item found on success, NULL on failure.
+         */
+        Item *findItem(const int itemId,
+                       const ItemColor color) const A_WARN_UNUSED;
+
+        /**
+         * Adds a new item in a free slot.
+         */
+        int addItem(const int id,
+                    const int type,
+                    const int quantity,
+                    const uint8_t refine,
+                    const ItemColor color,
+                    const Identified identified,
+                    const Damaged damaged,
+                    const Favorite favorite,
+                    const Equipm equipment,
+                    const Equipped equipped);
+
+        /**
+         * Sets the item at the given position.
+         */
+        void setItem(const int index,
+                     const int id,
+                     const int type,
+                     const int quantity,
+                     const uint8_t refine,
+                     const ItemColor color,
+                     const Identified identified,
+                     const Damaged damaged,
+                     const Favorite favorite,
+                     const Equipm equipment,
+                     const Equipped equipped);
+
+        void setCards(const int index,
+                      const int *const cards,
+                      const int size) const;
+
+        /**
+         * Remove a item from the inventory.
+         */
+        void removeItem(const int id);
+
+        /**
+         * Remove the item at the specified index from the inventory.
+         */
+        void removeItemAt(const int index);
+
+        /**
+         * Checks if the given item is in the inventory.
+         */
+        bool contains(const Item *const item) const A_WARN_UNUSED;
+
+        /**
+         * Returns id of next free slot or -1 if all occupied.
+         */
+        int getFreeSlot() const A_WARN_UNUSED;
+
+        /**
+         * Reset all item slots.
+         */
+        void clear();
+
+        /**
+         * Get the number of slots filled with an item
+         */
+        int getNumberOfSlotsUsed() const A_WARN_UNUSED
+        { return mUsed; }
+
+        /**
+         * Returns the index of the last occupied slot or 0 if none occupied.
+         */
+        int getLastUsedSlot() const A_WARN_UNUSED;
+
+        void addInventoyListener(InventoryListener *const listener);
+
+        void removeInventoyListener(InventoryListener *const listener);
+
+        InventoryTypeT getType() const A_WARN_UNUSED
+        { return mType; }
+
+        bool isMainInventory() const A_WARN_UNUSED
+        { return mType == InventoryType::Inventory; }
+
+        const Item *findItemBySprite(std::string spritePath,
+                                     const GenderT gender,
+                                     const BeingTypeId race)
+                                     const A_WARN_UNUSED;
+
+        std::string getName() const A_WARN_UNUSED;
+
+        void resize(const unsigned int newSize);
+
+        int findIndexByTag(const int tag) const;
+
+        bool addVirtualItem(const Item *const item,
+                            int index);
+
+        void virtualRemove(Item *const item,
+                           const int amount);
+
+        void virtualRestore(const Item *const item,
+                            const int amount);
+
+        void restoreVirtuals();
+
+    protected:
+        typedef std::list<InventoryListener*> InventoryListenerList;
+        InventoryListenerList mInventoryListeners;
+
+        void distributeSlotsChangedEvent();
+
+        IntMap mVirtualRemove;
+        InventoryTypeT mType;
+        unsigned mSize; /**< The max number of inventory items */
+        Item **mItems;  /**< The holder of items */
+        int mUsed;      /**< THe number of slots in use */
+};
+
+#endif  // RESOURCES_INVENTORY_INVENTORY_H
-- 
cgit v1.2.3-70-g09d2