X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Finventory.h;h=8b31de3a8ae39ee563764fd09991e89ef11fad51;hb=2351c9561265d4136f78ce3dd73c0c77acfed711;hp=dc5b04ff7cc4bfa9053e2427b379fc842b2abc9f;hpb=1320d07068f25ff23ea27e120983c006f75bec24;p=minetest.git diff --git a/src/inventory.h b/src/inventory.h index dc5b04ff7..8b31de3a8 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -1,482 +1,290 @@ /* -Minetest-c55 -Copyright (C) 2010 celeron55, Perttu Ahola +Minetest +Copyright (C) 2010-2013 celeron55, Perttu Ahola 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 +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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. +GNU Lesser General Public License for more details. -You should have received a copy of the GNU General Public License along +You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* -(c) 2010 Perttu Ahola -*/ - -#ifndef INVENTORY_HEADER -#define INVENTORY_HEADER +#pragma once -#include -#include +#include "itemdef.h" +#include "irrlichttypes.h" +#include "itemstackmetadata.h" +#include +#include #include -#include "common_irrlicht.h" -#include "debug.h" -#include "main.h" // For g_materials -#include "mapnode.h" // For content_t +#include +#include -#define QUANTITY_ITEM_MAX_COUNT 99 +struct ToolCapabilities; -class ServerActiveObject; -class ServerEnvironment; - -class InventoryItem +struct ItemStack { -public: - InventoryItem(u16 count); - virtual ~InventoryItem(); - - static InventoryItem* deSerialize(std::istream &is); - - virtual const char* getName() const = 0; - // Shall write the name and the parameters - virtual void serialize(std::ostream &os) const = 0; - // Shall make an exact clone of the item - virtual InventoryItem* clone() = 0; -#ifndef SERVER - // Return the name of the image for this item - virtual std::string getBasename() const { return ""; } - // Shall return an image of the item (or NULL) - virtual video::ITexture * getImage() const { return NULL; } - // Shall return an image of the item without embellishments (or NULL) - virtual video::ITexture * getImageRaw() const { return getImage(); } -#endif - // Shall return a text to show in the GUI - virtual std::string getText() { return ""; } - // Returns the string used for inventory - virtual std::string getItemString(); - // Creates an object from the item, to be placed in the world. - virtual ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos); - // Gets amount of items that dropping one SAO will decrement - virtual u16 getDropCount() const { return getCount(); } + ItemStack() = default; - /* - Quantity methods - */ + ItemStack(const std::string &name_, u16 count_, + u16 wear, IItemDefManager *itemdef); - // Shall return true if the item can be add()ed to the other - virtual bool addableTo(const InventoryItem *other) const - { - return false; - } - - u16 getCount() const - { - return m_count; - } - void setCount(u16 count) - { - m_count = count; - } - // This should return something else for stackable items - virtual u16 freeSpace() const - { - return 0; - } - void add(u16 count) - { - assert(m_count + count <= QUANTITY_ITEM_MAX_COUNT); - m_count += count; - } - void remove(u16 count) - { - assert(m_count >= count); - m_count -= count; - } + ~ItemStack() = default; - /* - Other properties - */ + // Serialization + void serialize(std::ostream &os, bool serialize_meta = true) const; + // Deserialization. Pass itemdef unless you don't want aliases resolved. + void deSerialize(std::istream &is, IItemDefManager *itemdef = NULL); + void deSerialize(const std::string &s, IItemDefManager *itemdef = NULL); - // Whether it can be cooked - virtual bool isCookable() const {return false;} - // Time of cooking - virtual float getCookTime(){return 3.0;} - // Result of cooking (can randomize) - virtual InventoryItem *createCookResult() const {return NULL;} - - // Eat, press, activate, whatever. - // Called when item is right-clicked when lying on ground. - // If returns true, item shall be deleted. - virtual bool use(ServerEnvironment *env, - ServerActiveObject *user){return false;} - -protected: - u16 m_count; -}; + // Returns the string used for inventory + std::string getItemString(bool include_meta = true) const; + // Returns the tooltip + std::string getDescription(IItemDefManager *itemdef) const; + std::string getShortDescription(IItemDefManager *itemdef) const; -class MaterialItem : public InventoryItem -{ -public: - MaterialItem(content_t content, u16 count): - InventoryItem(count) - { - m_content = content; - } /* - Implementation interface + Quantity methods */ - virtual const char* getName() const - { - return "MaterialItem"; - } - virtual void serialize(std::ostream &os) const + + bool empty() const { - //os.imbue(std::locale("C")); - os<<"MaterialItem2"; - os<<" "; - os<<(unsigned int)m_content; - os<<" "; - os<= n); // Pre-condition + count -= n; + if(count == 0) + clear(); // reset name, wear and metadata too } - virtual bool addableTo(const InventoryItem *other) const + // Maximum size of a stack + u16 getStackMax(IItemDefManager *itemdef) const { - if(std::string(other->getName()) != "MaterialItem") - return false; - MaterialItem *m = (MaterialItem*)other; - if(m->getMaterial() != m_content) - return false; - return true; + return itemdef->get(name).stack_max; } - u16 freeSpace() const + + // Number of items that can be added to this stack + u16 freeSpace(IItemDefManager *itemdef) const { - if(m_count > QUANTITY_ITEM_MAX_COUNT) + u16 max = getStackMax(itemdef); + if (count >= max) return 0; - return QUANTITY_ITEM_MAX_COUNT - m_count; - } - /* - Other properties - */ - bool isCookable() const; - InventoryItem *createCookResult() const; - /* - Special methods - */ - content_t getMaterial() - { - return m_content; + return max - count; } -private: - content_t m_content; -}; -/* - An item that is used as a mid-product when crafting. - Subnames: - - Stick -*/ -class CraftItem : public InventoryItem -{ -public: - CraftItem(std::string subname, u16 count): - InventoryItem(count) - { - m_subname = subname; - } - /* - Implementation interface - */ - virtual const char* getName() const - { - return "CraftItem"; - } - virtual void serialize(std::ostream &os) const + // Returns false if item is not known and cannot be used + bool isKnown(IItemDefManager *itemdef) const { - os<isKnown(name); } - virtual InventoryItem* clone() + + // Returns a pointer to the item definition struct, + // or a fallback one (name="unknown") if the item is unknown. + const ItemDefinition& getDefinition( + IItemDefManager *itemdef) const { - return new CraftItem(m_subname, m_count); + return itemdef->get(name); } -#ifndef SERVER - video::ITexture * getImage() const; -#endif - std::string getText() + + // Get tool digging properties, or those of the hand if not a tool + const ToolCapabilities& getToolCapabilities( + IItemDefManager *itemdef) const { - std::ostringstream os; - os<get(name).tool_capabilities; - ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos); - u16 getDropCount() const; + if (item_cap == NULL) + // Fall back to the hand's tool capabilities + item_cap = itemdef->get("").tool_capabilities; - virtual bool addableTo(const InventoryItem *other) const - { - if(std::string(other->getName()) != "CraftItem") - return false; - CraftItem *m = (CraftItem*)other; - if(m->m_subname != m_subname) - return false; - return true; + assert(item_cap != NULL); + return metadata.getToolCapabilities(*item_cap); // Check for override } - u16 freeSpace() const + + // Wear out (only tools) + // Returns true if the item is (was) a tool + bool addWear(s32 amount, IItemDefManager *itemdef) { - if(m_count > QUANTITY_ITEM_MAX_COUNT) - return 0; - return QUANTITY_ITEM_MAX_COUNT - m_count; + if(getDefinition(itemdef).type == ITEM_TOOL) + { + if(amount > 65535 - wear) + clear(); + else if(amount < -wear) + wear = 0; + else + wear += amount; + return true; + } + + return false; } - /* - Other properties - */ + // If possible, adds newitem to this item. + // If cannot be added at all, returns the item back. + // If can be added partly, decremented item is returned back. + // If can be added fully, empty item is returned. + ItemStack addItem(ItemStack newitem, IItemDefManager *itemdef); - bool isCookable() const; - InventoryItem *createCookResult() const; + // Checks whether newitem could be added. + // If restitem is non-NULL, it receives the part of newitem that + // would be left over after adding. + bool itemFits(ItemStack newitem, + ItemStack *restitem, // may be NULL + IItemDefManager *itemdef) const; - bool use(ServerEnvironment *env, ServerActiveObject *user); - - /* - Special methods - */ - std::string getSubName() - { - return m_subname; - } -private: - std::string m_subname; -}; + // Takes some items. + // If there are not enough, takes as many as it can. + // Returns empty item if couldn't take any. + ItemStack takeItem(u32 takecount); -class ToolItem : public InventoryItem -{ -public: - ToolItem(std::string toolname, u16 wear): - InventoryItem(1) - { - m_toolname = toolname; - m_wear = wear; - } - /* - Implementation interface - */ - virtual const char* getName() const - { - return "ToolItem"; - } - virtual void serialize(std::ostream &os) const - { - os<getTextureRaw(os.str()); - } + // Similar to takeItem, but keeps this ItemStack intact. + ItemStack peekItem(u32 peekcount) const; - video::ITexture * getImageRaw() const + bool operator ==(const ItemStack &s) const { - if(g_texturesource == NULL) - return NULL; - - return g_texturesource->getTextureRaw(getBasename()); + return (this->name == s.name && + this->count == s.count && + this->wear == s.wear && + this->metadata == s.metadata); } -#endif - std::string getText() + + bool operator !=(const ItemStack &s) const { - return ""; - - /*std::ostringstream os; - u16 f = 4; - u16 d = 65535/f; - u16 i; - for(i=0; i<(65535-m_wear)/d; i++) - os<<'X'; - for(; i= 65535 - add) - { - m_wear = 65535; - return true; - } - else - { - m_wear += add; - return false; - } - } -private: - std::string m_toolname; - u16 m_wear; + std::string name = ""; + u16 count = 0; + u16 wear = 0; + ItemStackMetadata metadata; }; class InventoryList { public: - InventoryList(std::string name, u32 size); - ~InventoryList(); + InventoryList(const std::string &name, u32 size, IItemDefManager *itemdef); + ~InventoryList() = default; void clearItems(); - void serialize(std::ostream &os) const; + void setSize(u32 newsize); + void setWidth(u32 newWidth); + void setName(const std::string &name); + void serialize(std::ostream &os, bool incremental) const; void deSerialize(std::istream &is); - InventoryList(const InventoryList &other); + InventoryList(const InventoryList &other) { *this = other; } InventoryList & operator = (const InventoryList &other); + bool operator == (const InventoryList &other) const; + bool operator != (const InventoryList &other) const + { + return !(*this == other); + } - const std::string &getName() const; - u32 getSize(); + const std::string &getName() const { return m_name; } + u32 getSize() const { return static_cast(m_items.size()); } + u32 getWidth() const { return m_width; } // Count used slots - u32 getUsedSlots(); - u32 getFreeSlots(); - - /*bool getDirty(){ return m_dirty; } - void setDirty(bool dirty=true){ m_dirty = dirty; }*/ - - // Get pointer to item - const InventoryItem * getItem(u32 i) const; - InventoryItem * getItem(u32 i); - // Returns old item (or NULL). Parameter can be NULL. - InventoryItem * changeItem(u32 i, InventoryItem *newitem); + u32 getUsedSlots() const; + + // Get reference to item + const ItemStack &getItem(u32 i) const + { + assert(i < m_size); // Pre-condition + return m_items[i]; + } + ItemStack &getItem(u32 i) + { + assert(i < m_size); // Pre-condition + return m_items[i]; + } + // Get reference to all items + const std::vector &getItems() const { return m_items; } + // Returns old item. Parameter can be an empty item. + ItemStack changeItem(u32 i, const ItemStack &newitem); // Delete item void deleteItem(u32 i); - // Adds an item to a suitable place. Returns leftover item. - // If all went into the list, returns NULL. - InventoryItem * addItem(InventoryItem *newitem); + // Adds an item to a suitable place. Returns leftover item (possibly empty). + ItemStack addItem(const ItemStack &newitem); // If possible, adds item to given slot. // If cannot be added at all, returns the item back. // If can be added partly, decremented item is returned back. - // If can be added fully, NULL is returned. - InventoryItem * addItem(u32 i, InventoryItem *newitem); + // If can be added fully, empty item is returned. + ItemStack addItem(u32 i, const ItemStack &newitem); // Checks whether the item could be added to the given slot - bool itemFits(const u32 i, const InventoryItem *newitem); + // If restitem is non-NULL, it receives the part of newitem that + // would be left over after adding. + bool itemFits(const u32 i, const ItemStack &newitem, + ItemStack *restitem = NULL) const; // Checks whether there is room for a given item - bool roomForItem(const InventoryItem *item); + bool roomForItem(const ItemStack &item) const; + + // Checks whether the given count of the given item + // exists in this inventory list. + // If match_meta is false, only the items' names are compared. + bool containsItem(const ItemStack &item, bool match_meta) const; - // Checks whether there is room for a given item aftr it has been cooked - bool roomForCookedItem(const InventoryItem *item); + // Removes the given count of the given item name from + // this inventory list. Walks the list in reverse order. + // If not as many items exist as requested, removes as + // many as possible. + // Returns the items that were actually removed. + ItemStack removeItem(const ItemStack &item); // Takes some items from a slot. // If there are not enough, takes as many as it can. - // Returns NULL if couldn't take any. - InventoryItem * takeItem(u32 i, u32 count); + // Returns empty item if couldn't take any. + ItemStack takeItem(u32 i, u32 takecount); - // Decrements amount of every material item - void decrementMaterials(u16 count); + // Move an item to a different list (or a different stack in the same list) + // count is the maximum number of items to move (0 for everything) + // returns number of moved items + u32 moveItem(u32 i, InventoryList *dest, u32 dest_i, + u32 count = 0, bool swap_if_needed = true, bool *did_swap = NULL); + + // like moveItem, but without a fixed destination index + // also with optional rollback recording + void moveItemSomewhere(u32 i, InventoryList *dest, u32 count); + + inline bool checkModified() const { return m_dirty; } + inline void setModified(bool dirty = true) { m_dirty = dirty; } - void print(std::ostream &o); - private: - core::array m_items; - u32 m_size; + std::vector m_items; std::string m_name; - //bool m_dirty; + u32 m_size; // always the same as m_items.size() + u32 m_width = 0; + IItemDefManager *m_itemdef; + bool m_dirty = true; }; class Inventory @@ -486,184 +294,60 @@ class Inventory void clear(); - Inventory(); + Inventory(IItemDefManager *itemdef); Inventory(const Inventory &other); Inventory & operator = (const Inventory &other); - - void serialize(std::ostream &os) const; + bool operator == (const Inventory &other) const; + bool operator != (const Inventory &other) const + { + return !(*this == other); + } + + // Never ever serialize to disk using "incremental"! + void serialize(std::ostream &os, bool incremental = false) const; void deSerialize(std::istream &is); + // Creates a new list if none exists or truncates existing lists InventoryList * addList(const std::string &name, u32 size); InventoryList * getList(const std::string &name); const InventoryList * getList(const std::string &name) const; + const std::vector &getLists() const { return m_lists; } bool deleteList(const std::string &name); - // A shorthand for adding items. - // Returns NULL if the item was fully added, leftover otherwise. - InventoryItem * addItem(const std::string &listname, InventoryItem *newitem) + // A shorthand for adding items. Returns leftover item (possibly empty). + ItemStack addItem(const std::string &listname, const ItemStack &newitem) { InventoryList *list = getList(listname); if(list == NULL) return newitem; return list->addItem(newitem); } - -private: - // -1 if not found - const s32 getListIndex(const std::string &name) const; - - core::array m_lists; -}; - -class Player; - -struct InventoryContext -{ - Player *current_player; - - InventoryContext(): - current_player(NULL) - {} -}; - -struct InventoryAction; -class InventoryManager -{ -public: - InventoryManager(){} - virtual ~InventoryManager(){} - - /* - Get a pointer to an inventory specified by id. - id can be: - - "current_player" - - "nodemeta:X,Y,Z" - */ - virtual Inventory* getInventory(InventoryContext *c, std::string id) - {return NULL;} - // Used on the server by InventoryAction::apply and other stuff - virtual void inventoryModified(InventoryContext *c, std::string id) - {} - // Used on the client - virtual void inventoryAction(InventoryAction *a) - {} -}; - -#define IACTION_MOVE 0 - -struct InventoryAction -{ - static InventoryAction * deSerialize(std::istream &is); - - virtual u16 getType() const = 0; - virtual void serialize(std::ostream &os) const = 0; - virtual void apply(InventoryContext *c, InventoryManager *mgr) = 0; -}; - -struct IMoveAction : public InventoryAction -{ - // count=0 means "everything" - u16 count; - std::string from_inv; - std::string from_list; - s16 from_i; - std::string to_inv; - std::string to_list; - s16 to_i; - - IMoveAction() + inline bool checkModified() const { - count = 0; - from_i = -1; - to_i = -1; - } - IMoveAction(std::istream &is) - { - std::string ts; - - std::getline(is, ts, ' '); - count = stoi(ts); - - std::getline(is, from_inv, ' '); - - std::getline(is, from_list, ' '); - - std::getline(is, ts, ' '); - from_i = stoi(ts); - - std::getline(is, to_inv, ' '); - - std::getline(is, to_list, ' '); - - std::getline(is, ts, ' '); - to_i = stoi(ts); - } + if (m_dirty) + return true; - u16 getType() const - { - return IACTION_MOVE; - } + for (const auto &list : m_lists) + if (list->checkModified()) + return true; - void serialize(std::ostream &os) const - { - os<<"Move "; - os<setModified(dirty); + } } +private: + // -1 if not found + s32 getListIndex(const std::string &name) const; - bool checkItem(const InventoryItem *item) const; + std::vector m_lists; + IItemDefManager *m_itemdef; + bool m_dirty = true; }; - -/* - items: a pointer to an array of 9 pointers to items - specs: a pointer to an array of 9 ItemSpecs -*/ -bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs); - -#endif -