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