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