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