1 #pragma once 2 #ifndef CATA_SRC_INVENTORY_H 3 #define CATA_SRC_INVENTORY_H 4 5 #include <array> 6 #include <bitset> 7 #include <climits> 8 #include <cstddef> 9 #include <functional> 10 #include <iosfwd> 11 #include <limits> 12 #include <list> 13 #include <map> 14 #include <set> 15 #include <unordered_map> 16 #include <unordered_set> 17 #include <utility> 18 #include <vector> 19 20 #include "cata_utility.h" 21 #include "item.h" 22 #include "magic_enchantment.h" 23 #include "proficiency.h" 24 #include "type_id.h" 25 #include "units_fwd.h" 26 #include "visitable.h" 27 28 class Character; 29 class JsonIn; 30 class JsonOut; 31 class item_stack; 32 class map; 33 class npc; 34 struct tripoint; 35 36 using invstack = std::list<std::list<item> >; 37 using invslice = std::vector<std::list<item> *>; 38 using const_invslice = std::vector<const std::list<item> *>; 39 using indexed_invslice = std::vector< std::pair<std::list<item>*, int> >; 40 using itype_bin = std::unordered_map< itype_id, std::list<const item *> >; 41 using invlets_bitset = std::bitset<std::numeric_limits<char>::max()>; 42 43 /** 44 * Wrapper to handled a set of valid "inventory" letters. "inventory" can be any set of 45 * objects that the player can access via a single character (e.g. bionics). 46 * The class is (currently) derived from std::string for compatibility and because it's 47 * simpler. But it may be changed to derive from `std::set<int>` or similar to get the full 48 * range of possible characters. 49 */ 50 class invlet_wrapper : private std::string 51 { 52 public: invlet_wrapper(const char * chars)53 explicit invlet_wrapper( const char *chars ) : std::string( chars ) { } 54 55 bool valid( int invlet ) const; get_allowed_chars()56 std::string get_allowed_chars() const { 57 return *this; 58 } 59 60 using std::string::begin; 61 using std::string::end; 62 using std::string::rbegin; 63 using std::string::rend; 64 using std::string::size; 65 using std::string::length; 66 }; 67 68 const extern invlet_wrapper inv_chars; 69 70 // For each item id, store a set of "favorite" inventory letters. 71 // This class maintains a bidirectional mapping between invlet letters and item ids. 72 // Each invlet has at most one id and each id has any number of invlets. 73 class invlet_favorites 74 { 75 public: 76 invlet_favorites() = default; 77 explicit invlet_favorites( const std::unordered_map<itype_id, std::string> & ); 78 79 void set( char invlet, const itype_id & ); 80 void erase( char invlet ); 81 bool contains( char invlet, const itype_id & ) const; 82 std::string invlets_for( const itype_id & ) const; 83 84 // For serialization only 85 const std::unordered_map<itype_id, std::string> &get_invlets_by_id() const; 86 private: 87 std::unordered_map<itype_id, std::string> invlets_by_id; 88 std::array<itype_id, 256> ids_by_invlet; 89 }; 90 91 class inventory : public visitable 92 { 93 public: 94 95 invslice slice(); 96 const_invslice const_slice() const; 97 const std::list<item> &const_stack( int i ) const; 98 size_t size() const; 99 100 std::map<char, itype_id> assigned_invlet; 101 102 inventory(); 103 inventory( inventory && ) noexcept = default; 104 inventory( const inventory & ) = default; 105 inventory &operator=( inventory && ) = default; 106 inventory &operator=( const inventory & ) = default; 107 108 inventory &operator+= ( const inventory &rhs ); 109 inventory &operator+= ( const item &rhs ); 110 inventory &operator+= ( const std::list<item> &rhs ); 111 inventory &operator+= ( const std::vector<item> &rhs ); 112 inventory &operator+= ( const item_stack &rhs ); 113 inventory operator+ ( const inventory &rhs ); 114 inventory operator+ ( const item &rhs ); 115 inventory operator+ ( const std::list<item> &rhs ); 116 117 void unsort(); // flags the inventory as unsorted 118 void clear(); 119 void push_back( const std::list<item> &newits ); 120 // returns a reference to the added item 121 item &add_item( item newit, bool keep_invlet = false, bool assign_invlet = true, 122 bool should_stack = true ); 123 void add_item_keep_invlet( const item &newit ); 124 void push_back( const item &newit ); 125 126 // used by form_from_map, if tool was already provisioned returns nullptr 127 item *provide_pseudo_item( const itype_id &id, int battery ); 128 129 /* Check all items for proper stacking, rearranging as needed 130 * game pointer is not necessary, but if supplied, will ensure no overlap with 131 * the player's worn items / weapon 132 */ 133 void restack( Character &p ); 134 void form_from_zone( map &m, std::unordered_set<tripoint> &zone_pts, const Character *pl = nullptr, 135 bool assign_invlet = true ); 136 void form_from_map( const tripoint &origin, int range, const Character *pl = nullptr, 137 bool assign_invlet = true, 138 bool clear_path = true ); 139 void form_from_map( map &m, const tripoint &origin, int range, const Character *pl = nullptr, 140 bool assign_invlet = true, 141 bool clear_path = true ); 142 void form_from_map( map &m, std::vector<tripoint> pts, const Character *pl, 143 bool assign_invlet = true ); 144 /** 145 * Remove a specific item from the inventory. The item is compared 146 * by pointer. Contents of the item are removed as well. 147 * @param it A pointer to the item to be removed. The item *must* exists 148 * in this inventory. 149 * @return A copy of the removed item. 150 */ 151 item remove_item( const item *it ); 152 item remove_item( int position ); 153 /** 154 * Randomly select items until the volume quota is filled. 155 */ 156 std::list<item> remove_randomly_by_volume( const units::volume &volume ); 157 std::list<item> reduce_stack( int position, int quantity ); 158 159 const item &find_item( int position ) const; 160 item &find_item( int position ); 161 162 /** 163 * Returns the item position of the stack that contains the given item (compared by 164 * pointers). Returns INT_MIN if the item is not found. 165 * Note that this may lose some information, for example the returned position is the 166 * same when the given item points to the container and when it points to the item inside 167 * the container. All items that are part of the same stack have the same item position. 168 */ 169 int position_by_item( const item *it ) const; 170 int position_by_type( const itype_id &type ) const; 171 172 /** Return the item position of the item with given invlet, return INT_MIN if 173 * the inventory does not have such an item with that invlet. Don't use this on npcs inventory. */ 174 int invlet_to_position( char invlet ) const; 175 176 // Below, "amount" refers to quantity 177 // "charges" refers to charges 178 std::list<item> use_amount( const itype_id &it, int quantity, 179 const std::function<bool( const item & )> &filter = return_true<item> ); 180 181 int leak_level( const flag_id &flag ) const; // level of leaked bad stuff from items 182 183 // NPC/AI functions 184 int worst_item_value( npc *p ) const; 185 bool has_enough_painkiller( int pain ) const; 186 item *most_appropriate_painkiller( int pain ); 187 188 void rust_iron_items(); 189 190 units::mass weight() const; 191 units::mass weight_without( const std::map<const item *, int> & ) const; 192 units::volume volume() const; 193 units::volume volume_without( const std::map<const item *, int> & ) const; 194 195 // dumps contents into dest (does not delete contents) 196 void dump( std::vector<item *> &dest ); 197 198 // vector rather than list because it's NOT an item stack 199 // returns all items that need processing 200 std::vector<item *> active_items(); 201 202 void json_load_invcache( JsonIn &jsin ); 203 void json_load_items( JsonIn &jsin ); 204 205 void json_save_invcache( JsonOut &json ) const; 206 void json_save_items( JsonOut &json ) const; 207 208 // Assigns an invlet if any remain. If none do, will assign ` if force is 209 // true, empty (invlet = 0) otherwise. 210 void assign_empty_invlet( item &it, const Character &p, bool force = false ); 211 // Assigns the item with the given invlet, and updates the favorite invlet cache. Does not check for uniqueness 212 void reassign_item( item &it, char invlet, bool remove_old = true ); 213 // Removes invalid invlets, and assigns new ones if assign_invlet is true. Does not update the invlet cache. 214 void update_invlet( item &it, bool assign_invlet = true ); 215 216 invlets_bitset allocated_invlets() const; 217 218 /** 219 * Returns visitable items binned by their itype. 220 * May not contain items that wouldn't be visited by @ref visitable methods. 221 */ 222 const itype_bin &get_binned_items() const; 223 224 void update_cache_with_item( item &newit ); 225 226 void copy_invlet_of( const inventory &other ); 227 228 // gets a singular enchantment that is an amalgamation of all items that have active enchantments 229 enchantment get_active_enchantment_cache( const Character &owner ) const; 230 231 int count_item( const itype_id &item_type ) const; 232 233 book_proficiency_bonuses get_book_proficiency_bonuses() const; 234 235 // inherited from `visitable` 236 bool has_quality( const quality_id &qual, int level = 1, int qty = 1 ) const override; 237 VisitResponse visit_items( const std::function<VisitResponse( item *, item * )> &func ) const 238 override; 239 std::list<item> remove_items_with( const std::function<bool( const item & )> &filter, 240 int count = INT_MAX ) override; 241 int charges_of( const itype_id &what, int limit = INT_MAX, 242 const std::function<bool( const item & )> &filter = return_true<item>, 243 const std::function<void( int )> &visitor = nullptr ) const override; 244 int amount_of( const itype_id &what, bool pseudo = true, 245 int limit = INT_MAX, 246 const std::function<bool( const item & )> &filter = return_true<item> ) const override; 247 248 private: 249 invlet_favorites invlet_cache; 250 char find_usable_cached_invlet( const itype_id &item_type ); 251 252 invstack items; 253 254 // tracker for provide_pseudo_item to prevent duplicate tools/liquids 255 std::set<itype_id> provisioned_pseudo_tools; 256 257 mutable bool binned = false; 258 /** 259 * Items binned by their type. 260 * That is, item_bin["carrot"] is a list of pointers to all carrots in inventory. 261 * `mutable` because this is a pure cache that doesn't affect the contained items. 262 */ 263 mutable itype_bin binned_items; 264 }; 265 266 #endif // CATA_SRC_INVENTORY_H 267