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