]> git.lizzy.rs Git - minetest.git/blob - src/inventory.h
Random Lua tweaks/fixes
[minetest.git] / src / inventory.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
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 General Public License for more details.
14
15 You should have received a copy of the GNU 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.
18 */
19
20 #ifndef INVENTORY_HEADER
21 #define INVENTORY_HEADER
22
23 #include <iostream>
24 #include <sstream>
25 #include <string>
26 #include "common_irrlicht.h"
27 #include "debug.h"
28 #include "mapnode.h" // For content_t
29
30 #define QUANTITY_ITEM_MAX_COUNT 99
31
32 class ServerActiveObject;
33 class ServerEnvironment;
34 class ITextureSource;
35 class IGameDef;
36
37 class InventoryItem
38 {
39 public:
40         InventoryItem(IGameDef *gamedef, u16 count);
41         virtual ~InventoryItem();
42         
43         static InventoryItem* deSerialize(std::istream &is, IGameDef *gamedef);
44         
45         virtual const char* getName() const = 0;
46         // Shall write the name and the parameters
47         virtual void serialize(std::ostream &os) const = 0;
48         // Shall make an exact clone of the item
49         virtual InventoryItem* clone() = 0;
50         // Return the name of the image for this item
51         virtual std::string getImageBasename() const { return ""; }
52 #ifndef SERVER
53         // Shall return an image of the item (or NULL)
54         virtual video::ITexture * getImage() const
55                 { return NULL; }
56         // Shall return an image of the item without embellishments (or NULL)
57         virtual video::ITexture * getImageRaw() const
58                 { return getImage(); }
59 #endif
60         // Shall return a text to show in the GUI
61         virtual std::string getText() { return ""; }
62         // Returns the string used for inventory
63         virtual std::string getItemString();
64         // Creates an object from the item, to be placed in the world.
65         virtual ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
66         // Gets amount of items that dropping one SAO will decrement
67         virtual u16 getDropCount() const { return getCount(); }
68
69         /*
70                 Quantity methods
71         */
72
73         // Return true if the item can be add()ed to the other
74         virtual bool addableTo(const InventoryItem *other) const
75         { return false; }
76         // Return true if the other item contains this item
77         virtual bool isSubsetOf(const InventoryItem *other) const
78         { return false; }
79         // Remove the other item from this one if possible and return true
80         // Return false if not possible
81         virtual bool removeOther(const InventoryItem *other)
82         { return false; }
83         
84         u16 getCount() const
85         { return m_count; }
86         void setCount(u16 count)
87         { m_count = count; }
88
89         // This should return something else for stackable items
90         virtual u16 freeSpace() const
91         { return 0; }
92
93         void add(u16 count)
94         {
95                 assert(m_count + count <= QUANTITY_ITEM_MAX_COUNT);
96                 m_count += count;
97         }
98         void remove(u16 count)
99         {
100                 assert(m_count >= count);
101                 m_count -= count;
102         }
103
104         /*
105                 Other properties
106         */
107
108         // Whether it can be cooked
109         virtual bool isCookable() const {return false;}
110         // Result of cooking (can randomize)
111         virtual InventoryItem *createCookResult() const {return NULL;}
112         // Time of cooking
113         virtual float getCookTime() const {return 3.0;}
114         // Whether it can be burned (<0 = cannot be burned)
115         virtual float getBurnTime() const {return -1;}
116         
117         // Eat, press, activate, whatever.
118         // Called when item is right-clicked when lying on ground.
119         // If returns true, item shall be deleted.
120         virtual bool use(ServerEnvironment *env,
121                         ServerActiveObject *user){return false;}
122
123 protected:
124         IGameDef *m_gamedef;
125         u16 m_count;
126 };
127
128 class MaterialItem : public InventoryItem
129 {
130 public:
131         MaterialItem(IGameDef *gamedef, std::string nodename, u16 count);
132         // Legacy constructor
133         MaterialItem(IGameDef *gamedef, content_t content, u16 count);
134         /*
135                 Implementation interface
136         */
137         virtual const char* getName() const
138         {
139                 return "MaterialItem";
140         }
141         virtual void serialize(std::ostream &os) const
142         {
143                 os<<"NodeItem";
144                 os<<" \"";
145                 os<<m_nodename;
146                 os<<"\" ";
147                 os<<m_count;
148         }
149         virtual InventoryItem* clone()
150         {
151                 return new MaterialItem(m_gamedef, m_nodename, m_count);
152         }
153 #ifndef SERVER
154         video::ITexture * getImage() const;
155 #endif
156         std::string getText()
157         {
158                 std::ostringstream os;
159                 os<<m_count;
160                 return os.str();
161         }
162
163         virtual bool addableTo(const InventoryItem *other) const
164         {
165                 if(std::string(other->getName()) != "MaterialItem")
166                         return false;
167                 MaterialItem *m = (MaterialItem*)other;
168                 if(m->m_nodename != m_nodename)
169                         return false;
170                 return true;
171         }
172         virtual bool isSubsetOf(const InventoryItem *other) const
173         {
174                 if(std::string(other->getName()) != "MaterialItem")
175                         return false;
176                 MaterialItem *m = (MaterialItem*)other;
177                 if(m->m_nodename != m_nodename)
178                         return false;
179                 return m_count <= m->m_count;
180         }
181         virtual bool removeOther(const InventoryItem *other)
182         {
183                 if(!other->isSubsetOf(this))
184                         return false;
185                 MaterialItem *m = (MaterialItem*)other;
186                 m_count += m->m_count;
187                 return true;
188         }
189
190         u16 freeSpace() const
191         {
192                 if(m_count > QUANTITY_ITEM_MAX_COUNT)
193                         return 0;
194                 return QUANTITY_ITEM_MAX_COUNT - m_count;
195         }
196         /*
197                 Other properties
198         */
199         bool isCookable() const;
200         InventoryItem *createCookResult() const;
201         float getCookTime() const;
202         float getBurnTime() const;
203         /*
204                 Special properties (not part of virtual interface)
205         */
206         std::string getNodeName() const
207         { return m_nodename; }
208         content_t getMaterial() const;
209 private:
210         std::string m_nodename;
211 };
212
213 /*
214         An item that is used as a mid-product when crafting.
215         Subnames:
216         - Stick
217 */
218 class CraftItem : public InventoryItem
219 {
220 public:
221         CraftItem(IGameDef *gamedef, std::string subname, u16 count):
222                 InventoryItem(gamedef, count)
223         {
224                 m_subname = subname;
225         }
226         /*
227                 Implementation interface
228         */
229         virtual const char* getName() const
230         {
231                 return "CraftItem";
232         }
233         virtual void serialize(std::ostream &os) const
234         {
235                 os<<getName();
236                 os<<" \"";
237                 os<<m_subname;
238                 os<<"\" ";
239                 os<<m_count;
240         }
241         virtual InventoryItem* clone()
242         {
243                 return new CraftItem(m_gamedef, m_subname, m_count);
244         }
245 #ifndef SERVER
246         video::ITexture * getImage() const;
247 #endif
248         std::string getText()
249         {
250                 std::ostringstream os;
251                 os<<m_count;
252                 return os.str();
253         }
254
255         ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
256         u16 getDropCount() const;
257
258         virtual bool addableTo(const InventoryItem *other) const
259         {
260                 if(std::string(other->getName()) != "CraftItem")
261                         return false;
262                 CraftItem *m = (CraftItem*)other;
263                 if(m->m_subname != m_subname)
264                         return false;
265                 return true;
266         }
267         virtual bool isSubsetOf(const InventoryItem *other) const
268         {
269                 if(std::string(other->getName()) != "CraftItem")
270                         return false;
271                 CraftItem *m = (CraftItem*)other;
272                 if(m->m_subname != m_subname)
273                         return false;
274                 return m_count <= m->m_count;
275         }
276         virtual bool removeOther(const InventoryItem *other)
277         {
278                 if(!other->isSubsetOf(this))
279                         return false;
280                 CraftItem *m = (CraftItem*)other;
281                 m_count += m->m_count;
282                 return true;
283         }
284
285         u16 freeSpace() const
286         {
287                 if(m_count > QUANTITY_ITEM_MAX_COUNT)
288                         return 0;
289                 return QUANTITY_ITEM_MAX_COUNT - m_count;
290         }
291
292         /*
293                 Other properties
294         */
295
296         bool isCookable() const;
297         InventoryItem *createCookResult() const;
298         float getCookTime() const;
299         float getBurnTime() const;
300
301         bool use(ServerEnvironment *env, ServerActiveObject *user);
302         
303         /*
304                 Special methods
305         */
306         std::string getSubName()
307         {
308                 return m_subname;
309         }
310 private:
311         std::string m_subname;
312 };
313
314 class ToolItem : public InventoryItem
315 {
316 public:
317         ToolItem(IGameDef *gamedef, std::string toolname, u16 wear):
318                 InventoryItem(gamedef, 1)
319         {
320                 m_toolname = toolname;
321                 m_wear = wear;
322         }
323         /*
324                 Implementation interface
325         */
326         virtual const char* getName() const
327         {
328                 return "ToolItem";
329         }
330         virtual void serialize(std::ostream &os) const
331         {
332                 os<<getName();
333                 os<<" \"";
334                 os<<m_toolname;
335                 os<<"\" ";
336                 os<<m_wear;
337         }
338         virtual InventoryItem* clone()
339         {
340                 return new ToolItem(m_gamedef, m_toolname, m_wear);
341         }
342
343         std::string getImageBasename() const;
344 #ifndef SERVER
345         video::ITexture * getImage() const;
346         video::ITexture * getImageRaw() const;
347 #endif
348
349         std::string getText()
350         {
351                 return "";
352         }
353
354         virtual bool isSubsetOf(const InventoryItem *other) const
355         {
356                 if(std::string(other->getName()) != "ToolItem")
357                         return false;
358                 ToolItem *m = (ToolItem*)other;
359                 if(m->m_toolname != m_toolname)
360                         return false;
361                 return m_wear <= m->m_wear;
362         }
363         virtual bool removeOther(const InventoryItem *other)
364         {
365                 if(!other->isSubsetOf(this))
366                         return false;
367                 ToolItem *m = (ToolItem*)other;
368                 m_wear -= m->m_wear;
369                 return true;
370         }
371
372         /*
373                 Special methods
374         */
375         std::string getToolName()
376         {
377                 return m_toolname;
378         }
379         u16 getWear()
380         {
381                 return m_wear;
382         }
383         // Returns true if weared out
384         bool addWear(u16 add)
385         {
386                 if(m_wear >= 65535 - add)
387                 {
388                         m_wear = 65535;
389                         return true;
390                 }
391                 else
392                 {
393                         m_wear += add;
394                         return false;
395                 }
396         }
397 private:
398         std::string m_toolname;
399         u16 m_wear;
400 };
401
402 class InventoryList
403 {
404 public:
405         InventoryList(std::string name, u32 size);
406         ~InventoryList();
407         void clearItems();
408         void serialize(std::ostream &os) const;
409         void deSerialize(std::istream &is, IGameDef *gamedef);
410
411         InventoryList(const InventoryList &other);
412         InventoryList & operator = (const InventoryList &other);
413
414         const std::string &getName() const;
415         u32 getSize();
416         // Count used slots
417         u32 getUsedSlots();
418         u32 getFreeSlots();
419
420         /*bool getDirty(){ return m_dirty; }
421         void setDirty(bool dirty=true){ m_dirty = dirty; }*/
422         
423         // Get pointer to item
424         const InventoryItem * getItem(u32 i) const;
425         InventoryItem * getItem(u32 i);
426         // Returns old item (or NULL). Parameter can be NULL.
427         InventoryItem * changeItem(u32 i, InventoryItem *newitem);
428         // Delete item
429         void deleteItem(u32 i);
430
431         // Adds an item to a suitable place. Returns leftover item.
432         // If all went into the list, returns NULL.
433         InventoryItem * addItem(InventoryItem *newitem);
434
435         // If possible, adds item to given slot.
436         // If cannot be added at all, returns the item back.
437         // If can be added partly, decremented item is returned back.
438         // If can be added fully, NULL is returned.
439         InventoryItem * addItem(u32 i, InventoryItem *newitem);
440
441         // Checks whether the item could be added to the given slot
442         bool itemFits(const u32 i, const InventoryItem *newitem);
443
444         // Checks whether there is room for a given item
445         bool roomForItem(const InventoryItem *item);
446
447         // Checks whether there is room for a given item aftr it has been cooked
448         bool roomForCookedItem(const InventoryItem *item);
449
450         // Takes some items from a slot.
451         // If there are not enough, takes as many as it can.
452         // Returns NULL if couldn't take any.
453         InventoryItem * takeItem(u32 i, u32 count);
454
455         // Decrements amount of every material item
456         void decrementMaterials(u16 count);
457
458         void print(std::ostream &o);
459         
460 private:
461         core::array<InventoryItem*> m_items;
462         u32 m_size;
463         std::string m_name;
464         //bool m_dirty;
465 };
466
467 class Inventory
468 {
469 public:
470         ~Inventory();
471
472         void clear();
473
474         Inventory();
475         Inventory(const Inventory &other);
476         Inventory & operator = (const Inventory &other);
477         
478         void serialize(std::ostream &os) const;
479         void deSerialize(std::istream &is, IGameDef *gamedef);
480
481         InventoryList * addList(const std::string &name, u32 size);
482         InventoryList * getList(const std::string &name);
483         const InventoryList * getList(const std::string &name) const;
484         bool deleteList(const std::string &name);
485         // A shorthand for adding items.
486         // Returns NULL if the item was fully added, leftover otherwise.
487         InventoryItem * addItem(const std::string &listname, InventoryItem *newitem)
488         {
489                 InventoryList *list = getList(listname);
490                 if(list == NULL)
491                         return newitem;
492                 return list->addItem(newitem);
493         }
494         
495 private:
496         // -1 if not found
497         const s32 getListIndex(const std::string &name) const;
498
499         core::array<InventoryList*> m_lists;
500 };
501
502 class Player;
503
504 struct InventoryContext
505 {
506         Player *current_player;
507         
508         InventoryContext():
509                 current_player(NULL)
510         {}
511 };
512
513 struct InventoryAction;
514
515 class InventoryManager
516 {
517 public:
518         InventoryManager(){}
519         virtual ~InventoryManager(){}
520         
521         /*
522                 Get a pointer to an inventory specified by id.
523                 id can be:
524                 - "current_player"
525                 - "nodemeta:X,Y,Z"
526         */
527         virtual Inventory* getInventory(InventoryContext *c, std::string id)
528                 {return NULL;}
529         // Used on the server by InventoryAction::apply and other stuff
530         virtual void inventoryModified(InventoryContext *c, std::string id)
531                 {}
532         // Used on the client
533         virtual void inventoryAction(InventoryAction *a)
534                 {}
535 };
536
537 #define IACTION_MOVE 0
538
539 struct InventoryAction
540 {
541         static InventoryAction * deSerialize(std::istream &is);
542         
543         virtual u16 getType() const = 0;
544         virtual void serialize(std::ostream &os) const = 0;
545         virtual void apply(InventoryContext *c, InventoryManager *mgr) = 0;
546 };
547
548 struct IMoveAction : public InventoryAction
549 {
550         // count=0 means "everything"
551         u16 count;
552         std::string from_inv;
553         std::string from_list;
554         s16 from_i;
555         std::string to_inv;
556         std::string to_list;
557         s16 to_i;
558         
559         IMoveAction()
560         {
561                 count = 0;
562                 from_i = -1;
563                 to_i = -1;
564         }
565         
566         IMoveAction(std::istream &is);
567
568         u16 getType() const
569         {
570                 return IACTION_MOVE;
571         }
572
573         void serialize(std::ostream &os) const
574         {
575                 os<<"Move ";
576                 os<<count<<" ";
577                 os<<from_inv<<" ";
578                 os<<from_list<<" ";
579                 os<<from_i<<" ";
580                 os<<to_inv<<" ";
581                 os<<to_list<<" ";
582                 os<<to_i;
583         }
584
585         void apply(InventoryContext *c, InventoryManager *mgr);
586 };
587
588 /*
589         Craft checking system
590 */
591
592 enum ItemSpecType
593 {
594         ITEM_NONE,
595         ITEM_MATERIAL,
596         ITEM_CRAFT,
597         ITEM_TOOL,
598         ITEM_MBO
599 };
600
601 struct ItemSpec
602 {
603         enum ItemSpecType type;
604         // Only other one of these is used
605         std::string name;
606         u16 num;
607
608         ItemSpec():
609                 type(ITEM_NONE)
610         {
611         }
612         ItemSpec(enum ItemSpecType a_type, std::string a_name):
613                 type(a_type),
614                 name(a_name),
615                 num(65535)
616         {
617         }
618         ItemSpec(enum ItemSpecType a_type, u16 a_num):
619                 type(a_type),
620                 name(""),
621                 num(a_num)
622         {
623         }
624
625         bool checkItem(const InventoryItem *item) const;
626 };
627
628 /*
629         items: a pointer to an array of 9 pointers to items
630         specs: a pointer to an array of 9 ItemSpecs
631 */
632 bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs);
633
634 /*
635         items: a pointer to an array of 9 pointers to items
636         specs: a pointer to an array of 9 pointers to items
637 */
638 bool checkItemCombination(const InventoryItem * const * items,
639                 const InventoryItem * const * specs);
640
641 #endif
642