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