Update no games message to give more context (#14695)
[minetest.git] / src / inventory.h
blob9f7265b76d626afa2ed7a9f58bd0566b787ebddf
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #pragma once
22 #include "itemdef.h"
23 #include "irrlichttypes.h"
24 #include "itemstackmetadata.h"
25 #include <istream>
26 #include <ostream>
27 #include <string>
28 #include <vector>
29 #include <cassert>
31 struct ToolCapabilities;
33 struct ItemStack
35 ItemStack() = default;
37 ItemStack(const std::string &name_, u16 count_,
38 u16 wear, IItemDefManager *itemdef);
40 ~ItemStack() = default;
42 // Serialization
43 void serialize(std::ostream &os, bool serialize_meta = true) const;
44 // Deserialization. Pass itemdef unless you don't want aliases resolved.
45 void deSerialize(std::istream &is, IItemDefManager *itemdef = NULL);
46 void deSerialize(const std::string &s, IItemDefManager *itemdef = NULL);
48 // Returns the string used for inventory
49 std::string getItemString(bool include_meta = true) const;
50 // Returns the tooltip
51 std::string getDescription(const IItemDefManager *itemdef) const;
52 std::string getShortDescription(const IItemDefManager *itemdef) const;
54 std::string getInventoryImage(const IItemDefManager *itemdef) const;
55 std::string getInventoryOverlay(const IItemDefManager *itemdef) const;
56 std::string getWieldImage(const IItemDefManager *itemdef) const;
57 std::string getWieldOverlay(const IItemDefManager *itemdef) const;
58 v3f getWieldScale(const IItemDefManager *itemdef) const;
61 Quantity methods
64 bool empty() const
66 return count == 0;
69 void clear()
71 name = "";
72 count = 0;
73 wear = 0;
74 metadata.clear();
77 void add(u16 n)
79 count += n;
82 void remove(u16 n)
84 assert(count >= n); // Pre-condition
85 count -= n;
86 if(count == 0)
87 clear(); // reset name, wear and metadata too
90 // Maximum size of a stack
91 u16 getStackMax(const IItemDefManager *itemdef) const
93 return itemdef->get(name).stack_max;
96 // Number of items that can be added to this stack
97 u16 freeSpace(const IItemDefManager *itemdef) const
99 u16 max = getStackMax(itemdef);
100 if (count >= max)
101 return 0;
102 return max - count;
105 // Returns false if item is not known and cannot be used
106 bool isKnown(const IItemDefManager *itemdef) const
108 return itemdef->isKnown(name);
111 // Returns a pointer to the item definition struct,
112 // or a fallback one (name="unknown") if the item is unknown.
113 const ItemDefinition& getDefinition(
114 const IItemDefManager *itemdef) const
116 return itemdef->get(name);
119 // Get tool digging properties, or those of the hand if not a tool
120 const ToolCapabilities& getToolCapabilities(
121 const IItemDefManager *itemdef) const
123 const ToolCapabilities *item_cap =
124 itemdef->get(name).tool_capabilities;
126 if (item_cap == NULL)
127 // Fall back to the hand's tool capabilities
128 item_cap = itemdef->get("").tool_capabilities;
130 assert(item_cap != NULL);
131 return metadata.getToolCapabilities(*item_cap); // Check for override
134 const std::optional<WearBarParams> &getWearBarParams(
135 const IItemDefManager *itemdef) const
137 auto &meta_override = metadata.getWearBarParamOverride();
138 if (meta_override.has_value())
139 return meta_override;
140 return itemdef->get(name).wear_bar_params;
143 // Wear out (only tools)
144 // Returns true if the item is (was) a tool
145 bool addWear(s32 amount, const IItemDefManager *itemdef)
147 if(getDefinition(itemdef).type == ITEM_TOOL)
149 if(amount > 65535 - wear)
150 clear();
151 else if(amount < -wear)
152 wear = 0;
153 else
154 wear += amount;
155 return true;
158 return false;
161 // If possible, adds newitem to this item.
162 // If cannot be added at all, returns the item back.
163 // If can be added partly, decremented item is returned back.
164 // If can be added fully, empty item is returned.
165 ItemStack addItem(ItemStack newitem, IItemDefManager *itemdef);
167 // Checks whether newitem could be added.
168 // If restitem is non-NULL, it receives the part of newitem that
169 // would be left over after adding.
170 bool itemFits(ItemStack newitem,
171 ItemStack *restitem, // may be NULL
172 IItemDefManager *itemdef) const;
174 // Checks if another itemstack would stack with this one.
175 // Does not check if the item actually fits in the stack.
176 bool stacksWith(const ItemStack &other) const;
178 // Takes some items.
179 // If there are not enough, takes as many as it can.
180 // Returns empty item if couldn't take any.
181 ItemStack takeItem(u32 takecount);
183 // Similar to takeItem, but keeps this ItemStack intact.
184 ItemStack peekItem(u32 peekcount) const;
186 bool operator ==(const ItemStack &s) const
188 return (this->name == s.name &&
189 this->count == s.count &&
190 this->wear == s.wear &&
191 this->metadata == s.metadata);
194 bool operator !=(const ItemStack &s) const
196 return !(*this == s);
200 Properties
202 std::string name = "";
203 u16 count = 0;
204 u16 wear = 0;
205 ItemStackMetadata metadata;
208 class InventoryList
210 public:
211 InventoryList(const std::string &name, u32 size, IItemDefManager *itemdef);
212 ~InventoryList() = default;
213 void clearItems();
214 void setSize(u32 newsize);
215 void setWidth(u32 newWidth);
216 void setName(const std::string &name);
217 void serialize(std::ostream &os, bool incremental) const;
218 void deSerialize(std::istream &is);
220 InventoryList(const InventoryList &other) { *this = other; }
221 InventoryList & operator = (const InventoryList &other);
222 bool operator == (const InventoryList &other) const;
223 bool operator != (const InventoryList &other) const
225 return !(*this == other);
228 const std::string &getName() const { return m_name; }
229 u32 getSize() const { return static_cast<u32>(m_items.size()); }
230 u32 getWidth() const { return m_width; }
231 // Count used slots
232 u32 getUsedSlots() const;
234 // Get reference to item
235 const ItemStack &getItem(u32 i) const
237 assert(i < m_size); // Pre-condition
238 return m_items[i];
240 ItemStack &getItem(u32 i)
242 assert(i < m_size); // Pre-condition
243 return m_items[i];
245 // Get reference to all items
246 const std::vector<ItemStack> &getItems() const { return m_items; }
247 // Returns old item. Parameter can be an empty item.
248 ItemStack changeItem(u32 i, const ItemStack &newitem);
249 // Delete item
250 void deleteItem(u32 i);
252 // Adds an item to a suitable place. Returns leftover item (possibly empty).
253 ItemStack addItem(const ItemStack &newitem);
255 // If possible, adds item to given slot.
256 // If cannot be added at all, returns the item back.
257 // If can be added partly, decremented item is returned back.
258 // If can be added fully, empty item is returned.
259 ItemStack addItem(u32 i, const ItemStack &newitem);
261 // Checks whether the item could be added to the given slot
262 // If restitem is non-NULL, it receives the part of newitem that
263 // would be left over after adding.
264 bool itemFits(const u32 i, const ItemStack &newitem,
265 ItemStack *restitem = NULL) const;
267 // Checks whether there is room for a given item
268 bool roomForItem(const ItemStack &item) const;
270 // Checks whether the given count of the given item
271 // exists in this inventory list.
272 // If match_meta is false, only the items' names are compared.
273 bool containsItem(const ItemStack &item, bool match_meta) const;
275 // Removes the given count of the given item name from
276 // this inventory list. Walks the list in reverse order.
277 // If not as many items exist as requested, removes as
278 // many as possible.
279 // Returns the items that were actually removed.
280 ItemStack removeItem(const ItemStack &item);
282 // Takes some items from a slot.
283 // If there are not enough, takes as many as it can.
284 // Returns empty item if couldn't take any.
285 ItemStack takeItem(u32 i, u32 takecount);
287 // Move an item to a different list (or a different stack in the same list)
288 // count is the maximum number of items to move (0 for everything)
289 // returns the moved stack
290 ItemStack moveItem(u32 i, InventoryList *dest, u32 dest_i,
291 u32 count = 0, bool swap_if_needed = true, bool *did_swap = NULL);
293 // like moveItem, but without a fixed destination index
294 // also with optional rollback recording
295 void moveItemSomewhere(u32 i, InventoryList *dest, u32 count);
297 inline bool checkModified() const { return m_dirty; }
298 inline void setModified(bool dirty = true) { m_dirty = dirty; }
300 // Problem: C++ keeps references to InventoryList and ItemStack indices
301 // until a better solution is found, this serves as a guard to prevent side-effects
302 struct ResizeUnlocker {
303 void operator()(InventoryList *invlist)
305 invlist->m_resize_locks -= 1;
308 using ResizeLocked = std::unique_ptr<InventoryList, ResizeUnlocker>;
310 void checkResizeLock();
312 inline ResizeLocked resizeLock()
314 m_resize_locks += 1;
315 return ResizeLocked(this);
318 private:
319 std::vector<ItemStack> m_items;
320 std::string m_name;
321 u32 m_size; // always the same as m_items.size()
322 u32 m_width = 0;
323 IItemDefManager *m_itemdef;
324 bool m_dirty = true;
325 int m_resize_locks = 0; // Lua callback sanity
328 class Inventory
330 public:
331 ~Inventory();
333 void clear();
335 Inventory(IItemDefManager *itemdef);
336 Inventory(const Inventory &other);
337 Inventory & operator = (const Inventory &other);
338 bool operator == (const Inventory &other) const;
339 bool operator != (const Inventory &other) const
341 return !(*this == other);
344 // Never ever serialize to disk using "incremental"!
345 void serialize(std::ostream &os, bool incremental = false) const;
346 void deSerialize(std::istream &is);
348 // Creates a new list if none exists or truncates existing lists
349 InventoryList * addList(const std::string &name, u32 size);
350 InventoryList * getList(const std::string &name);
351 const InventoryList * getList(const std::string &name) const;
352 const std::vector<InventoryList *> &getLists() const { return m_lists; }
353 bool deleteList(const std::string &name);
354 // A shorthand for adding items. Returns leftover item (possibly empty).
355 ItemStack addItem(const std::string &listname, const ItemStack &newitem)
357 InventoryList *list = getList(listname);
358 if(list == NULL)
359 return newitem;
360 return list->addItem(newitem);
363 inline bool checkModified() const
365 if (m_dirty)
366 return true;
368 for (const auto &list : m_lists)
369 if (list->checkModified())
370 return true;
372 return false;
375 inline void setModified(bool dirty = true)
377 m_dirty = dirty;
378 // Set all as handled
379 if (!dirty) {
380 for (const auto &list : m_lists)
381 list->setModified(dirty);
384 private:
385 // -1 if not found
386 s32 getListIndex(const std::string &name) const;
388 std::vector<InventoryList*> m_lists;
389 IItemDefManager *m_itemdef;
390 bool m_dirty = true;