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