c202d5533125c860dbf15030c2da54840f592ec3
[oweals/minetest.git] / src / inventory.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010 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 /*
21 (c) 2010 Perttu Ahola <celeron55@gmail.com>
22 */
23
24 #ifndef INVENTORY_HEADER
25 #define INVENTORY_HEADER
26
27 #include <iostream>
28 #include <sstream>
29 #include <string>
30 #include "common_irrlicht.h"
31 #include "debug.h"
32 #include "main.h" // For g_materials
33 #include "mapnode.h" // For content_t
34
35 #define QUANTITY_ITEM_MAX_COUNT 99
36
37 class ServerActiveObject;
38 class ServerEnvironment;
39
40 class InventoryItem
41 {
42 public:
43         InventoryItem(u16 count);
44         virtual ~InventoryItem();
45         
46         static InventoryItem* deSerialize(std::istream &is);
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 #ifndef SERVER
54         // Return the name of the image for this item
55         virtual std::string getBasename() const { return ""; }
56         // Shall return an image of the item (or NULL)
57         virtual video::ITexture * getImage() const { return NULL; }
58         // Shall return an image of the item without embellishments (or NULL)
59         virtual video::ITexture * getImageRaw() const { return getImage(); }
60 #endif
61         // Shall return a text to show in the GUI
62         virtual std::string getText() { return ""; }
63         // Returns the string used for inventory
64         virtual std::string getItemString();
65         // Creates an object from the item, to be placed in the world.
66         virtual ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
67         // Gets amount of items that dropping one SAO will decrement
68         virtual u16 getDropCount() const { return getCount(); }
69
70         /*
71                 Quantity methods
72         */
73
74         // Shall return true if the item can be add()ed to the other
75         virtual bool addableTo(const InventoryItem *other) const
76         {
77                 return false;
78         }
79         
80         u16 getCount() const
81         {
82                 return m_count;
83         }
84         void setCount(u16 count)
85         {
86                 m_count = count;
87         }
88         // This should return something else for stackable items
89         virtual u16 freeSpace() const
90         {
91                 return 0;
92         }
93         void add(u16 count)
94         {
95                 assert(m_count + count <= QUANTITY_ITEM_MAX_COUNT);
96                 m_count += count;
97         }
98         void remove(u16 count)
99         {
100                 assert(m_count >= count);
101                 m_count -= count;
102         }
103
104         /*
105                 Other properties
106         */
107
108         // Whether it can be cooked
109         virtual bool isCookable() const {return false;}
110         // Time of cooking
111         virtual float getCookTime(){return 3.0;}
112         // Result of cooking (can randomize)
113         virtual InventoryItem *createCookResult() const {return NULL;}
114         
115         // Eat, press, activate, whatever.
116         // Called when item is right-clicked when lying on ground.
117         // If returns true, item shall be deleted.
118         virtual bool use(ServerEnvironment *env,
119                         ServerActiveObject *user){return false;}
120
121 protected:
122         u16 m_count;
123 };
124
125 class MaterialItem : public InventoryItem
126 {
127 public:
128         MaterialItem(content_t content, u16 count):
129                 InventoryItem(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_content, m_count);
152         }
153 #ifndef SERVER
154         video::ITexture * getImage() 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(std::string subname, u16 count):
203                 InventoryItem(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_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
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(std::string toolname, u16 wear):
279                 InventoryItem(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_toolname, m_wear);
302         }
303 #ifndef SERVER
304         std::string getBasename() const {
305                 if(m_toolname == "WPick")
306                         return "tool_woodpick.png";
307                 else if(m_toolname == "STPick")
308                         return "tool_stonepick.png";
309                 else if(m_toolname == "SteelPick")
310                         return "tool_steelpick.png";
311                 else if(m_toolname == "MesePick")
312                         return "tool_mesepick.png";
313                 else if(m_toolname == "WShovel")
314                         return "tool_woodshovel.png";
315                 else if(m_toolname == "STShovel")
316                         return "tool_stoneshovel.png";
317                 else if(m_toolname == "SteelShovel")
318                         return "tool_steelshovel.png";
319                 else if(m_toolname == "WAxe")
320                         return "tool_woodaxe.png";
321                 else if(m_toolname == "STAxe")
322                         return "tool_stoneaxe.png";
323                 else if(m_toolname == "SteelAxe")
324                         return "tool_steelaxe.png";
325                 else if(m_toolname == "WSword")
326                         return "tool_woodsword.png";
327                 else if(m_toolname == "STSword")
328                         return "tool_stonesword.png";
329                 else if(m_toolname == "SteelSword")
330                         return "tool_steelsword.png";
331                 else
332                         return "cloud.png";
333 }
334         
335         video::ITexture * getImage() const
336         {
337                 if(g_texturesource == NULL)
338                         return NULL;
339                 
340                 std::string basename = getBasename();
341                 
342                 /*
343                         Calculate a progress value with sane amount of
344                         maximum states
345                 */
346                 u32 maxprogress = 30;
347                 u32 toolprogress = (65535-m_wear)/(65535/maxprogress);
348                 
349                 float value_f = (float)toolprogress / (float)maxprogress;
350                 std::ostringstream os;
351                 os<<basename<<"^[progressbar"<<value_f;
352
353                 return g_texturesource->getTextureRaw(os.str());
354         }
355
356         video::ITexture * getImageRaw() const
357         {
358                 if(g_texturesource == NULL)
359                         return NULL;
360                 
361                 return g_texturesource->getTextureRaw(getBasename());
362         }
363 #endif
364         std::string getText()
365         {
366                 return "";
367                 
368                 /*std::ostringstream os;
369                 u16 f = 4;
370                 u16 d = 65535/f;
371                 u16 i;
372                 for(i=0; i<(65535-m_wear)/d; i++)
373                         os<<'X';
374                 for(; i<f; i++)
375                         os<<'-';
376                 return os.str();*/
377                 
378                 /*std::ostringstream os;
379                 os<<m_toolname;
380                 os<<" ";
381                 os<<(m_wear/655);
382                 return os.str();*/
383         }
384         /*
385                 Special methods
386         */
387         std::string getToolName()
388         {
389                 return m_toolname;
390         }
391         u16 getWear()
392         {
393                 return m_wear;
394         }
395         // Returns true if weared out
396         bool addWear(u16 add)
397         {
398                 if(m_wear >= 65535 - add)
399                 {
400                         m_wear = 65535;
401                         return true;
402                 }
403                 else
404                 {
405                         m_wear += add;
406                         return false;
407                 }
408         }
409 private:
410         std::string m_toolname;
411         u16 m_wear;
412 };
413
414 class InventoryList
415 {
416 public:
417         InventoryList(std::string name, u32 size);
418         ~InventoryList();
419         void clearItems();
420         void serialize(std::ostream &os) const;
421         void deSerialize(std::istream &is);
422
423         InventoryList(const InventoryList &other);
424         InventoryList & operator = (const InventoryList &other);
425
426         const std::string &getName() const;
427         u32 getSize();
428         // Count used slots
429         u32 getUsedSlots();
430         u32 getFreeSlots();
431
432         /*bool getDirty(){ return m_dirty; }
433         void setDirty(bool dirty=true){ m_dirty = dirty; }*/
434         
435         // Get pointer to item
436         const InventoryItem * getItem(u32 i) const;
437         InventoryItem * getItem(u32 i);
438         // Returns old item (or NULL). Parameter can be NULL.
439         InventoryItem * changeItem(u32 i, InventoryItem *newitem);
440         // Delete item
441         void deleteItem(u32 i);
442
443         // Adds an item to a suitable place. Returns leftover item.
444         // If all went into the list, returns NULL.
445         InventoryItem * addItem(InventoryItem *newitem);
446
447         // If possible, adds item to given slot.
448         // If cannot be added at all, returns the item back.
449         // If can be added partly, decremented item is returned back.
450         // If can be added fully, NULL is returned.
451         InventoryItem * addItem(u32 i, InventoryItem *newitem);
452
453         // Checks whether the item could be added to the given slot
454         bool itemFits(const u32 i, const InventoryItem *newitem);
455
456         // Checks whether there is room for a given item
457         bool roomForItem(const InventoryItem *item);
458
459         // Checks whether there is room for a given item aftr it has been cooked
460         bool roomForCookedItem(const InventoryItem *item);
461
462         // Takes some items from a slot.
463         // If there are not enough, takes as many as it can.
464         // Returns NULL if couldn't take any.
465         InventoryItem * takeItem(u32 i, u32 count);
466
467         // Decrements amount of every material item
468         void decrementMaterials(u16 count);
469
470         void print(std::ostream &o);
471         
472 private:
473         core::array<InventoryItem*> m_items;
474         u32 m_size;
475         std::string m_name;
476         //bool m_dirty;
477 };
478
479 class Inventory
480 {
481 public:
482         ~Inventory();
483
484         void clear();
485
486         Inventory();
487         Inventory(const Inventory &other);
488         Inventory & operator = (const Inventory &other);
489         
490         void serialize(std::ostream &os) const;
491         void deSerialize(std::istream &is);
492
493         InventoryList * addList(const std::string &name, u32 size);
494         InventoryList * getList(const std::string &name);
495         const InventoryList * getList(const std::string &name) const;
496         bool deleteList(const std::string &name);
497         // A shorthand for adding items.
498         // Returns NULL if the item was fully added, leftover otherwise.
499         InventoryItem * addItem(const std::string &listname, InventoryItem *newitem)
500         {
501                 InventoryList *list = getList(listname);
502                 if(list == NULL)
503                         return newitem;
504                 return list->addItem(newitem);
505         }
506         
507 private:
508         // -1 if not found
509         const s32 getListIndex(const std::string &name) const;
510
511         core::array<InventoryList*> m_lists;
512 };
513
514 class Player;
515
516 struct InventoryContext
517 {
518         Player *current_player;
519         
520         InventoryContext():
521                 current_player(NULL)
522         {}
523 };
524
525 struct InventoryAction;
526
527 class InventoryManager
528 {
529 public:
530         InventoryManager(){}
531         virtual ~InventoryManager(){}
532         
533         /*
534                 Get a pointer to an inventory specified by id.
535                 id can be:
536                 - "current_player"
537                 - "nodemeta:X,Y,Z"
538         */
539         virtual Inventory* getInventory(InventoryContext *c, std::string id)
540                 {return NULL;}
541         // Used on the server by InventoryAction::apply and other stuff
542         virtual void inventoryModified(InventoryContext *c, std::string id)
543                 {}
544         // Used on the client
545         virtual void inventoryAction(InventoryAction *a)
546                 {}
547 };
548
549 #define IACTION_MOVE 0
550
551 struct InventoryAction
552 {
553         static InventoryAction * deSerialize(std::istream &is);
554         
555         virtual u16 getType() const = 0;
556         virtual void serialize(std::ostream &os) const = 0;
557         virtual void apply(InventoryContext *c, InventoryManager *mgr) = 0;
558 };
559
560 struct IMoveAction : public InventoryAction
561 {
562         // count=0 means "everything"
563         u16 count;
564         std::string from_inv;
565         std::string from_list;
566         s16 from_i;
567         std::string to_inv;
568         std::string to_list;
569         s16 to_i;
570         
571         IMoveAction()
572         {
573                 count = 0;
574                 from_i = -1;
575                 to_i = -1;
576         }
577         IMoveAction(std::istream &is)
578         {
579                 std::string ts;
580
581                 std::getline(is, ts, ' ');
582                 count = stoi(ts);
583
584                 std::getline(is, from_inv, ' ');
585
586                 std::getline(is, from_list, ' ');
587
588                 std::getline(is, ts, ' ');
589                 from_i = stoi(ts);
590
591                 std::getline(is, to_inv, ' ');
592
593                 std::getline(is, to_list, ' ');
594
595                 std::getline(is, ts, ' ');
596                 to_i = stoi(ts);
597         }
598
599         u16 getType() const
600         {
601                 return IACTION_MOVE;
602         }
603
604         void serialize(std::ostream &os) const
605         {
606                 os<<"Move ";
607                 os<<count<<" ";
608                 os<<from_inv<<" ";
609                 os<<from_list<<" ";
610                 os<<from_i<<" ";
611                 os<<to_inv<<" ";
612                 os<<to_list<<" ";
613                 os<<to_i;
614         }
615
616         void apply(InventoryContext *c, InventoryManager *mgr);
617 };
618
619 /*
620         Craft checking system
621 */
622
623 enum ItemSpecType
624 {
625         ITEM_NONE,
626         ITEM_MATERIAL,
627         ITEM_CRAFT,
628         ITEM_TOOL,
629         ITEM_MBO
630 };
631
632 struct ItemSpec
633 {
634         enum ItemSpecType type;
635         // Only other one of these is used
636         std::string name;
637         u16 num;
638
639         ItemSpec():
640                 type(ITEM_NONE)
641         {
642         }
643         ItemSpec(enum ItemSpecType a_type, std::string a_name):
644                 type(a_type),
645                 name(a_name),
646                 num(65535)
647         {
648         }
649         ItemSpec(enum ItemSpecType a_type, u16 a_num):
650                 type(a_type),
651                 name(""),
652                 num(a_num)
653         {
654         }
655
656         bool checkItem(const InventoryItem *item) const;
657 };
658
659 /*
660         items: a pointer to an array of 9 pointers to items
661         specs: a pointer to an array of 9 ItemSpecs
662 */
663 bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs);
664
665 #endif
666