Better apple tree generation
[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 "mapblockobject.h"
33 #include "main.h" // For g_materials
34 #include "mapnode.h" // For content_t
35
36 #define QUANTITY_ITEM_MAX_COUNT 99
37
38 class ServerActiveObject;
39 class ServerEnvironment;
40 class Player;
41
42 class InventoryItem
43 {
44 public:
45         InventoryItem(u16 count);
46         virtual ~InventoryItem();
47         
48         static InventoryItem* deSerialize(std::istream &is);
49         
50         virtual const char* getName() const = 0;
51         // Shall write the name and the parameters
52         virtual void serialize(std::ostream &os) const = 0;
53         // Shall make an exact clone of the item
54         virtual InventoryItem* clone() = 0;
55 #ifndef SERVER
56         // Shall return an image to show in the GUI (or NULL)
57         virtual video::ITexture * getImage() { return NULL; }
58 #endif
59         // Shall return a text to show in the GUI
60         virtual std::string getText() { return ""; }
61         // Returns the string used for inventory
62         virtual std::string getItemString();
63         // Creates an object from the item, to be placed in the world.
64         virtual ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
65         // Gets amount of items that dropping one SAO will decrement
66         virtual u16 getDropCount() const { return getCount(); }
67
68         /*
69                 Quantity methods
70         */
71
72         // Shall return true if the item can be add()ed to the other
73         virtual bool addableTo(const InventoryItem *other) const
74         {
75                 return false;
76         }
77         
78         u16 getCount() const
79         {
80                 return m_count;
81         }
82         void setCount(u16 count)
83         {
84                 m_count = count;
85         }
86         // This should return something else for stackable items
87         virtual u16 freeSpace() const
88         {
89                 return 0;
90         }
91         void add(u16 count)
92         {
93                 assert(m_count + count <= QUANTITY_ITEM_MAX_COUNT);
94                 m_count += count;
95         }
96         void remove(u16 count)
97         {
98                 assert(m_count >= count);
99                 m_count -= count;
100         }
101
102         /*
103                 Other properties
104         */
105
106         // Whether it can be cooked
107         virtual bool isCookable() const {return false;}
108         // Time of cooking
109         virtual float getCookTime(){return 3.0;}
110         // Result of cooking (can randomize)
111         virtual InventoryItem *createCookResult() const {return NULL;}
112         
113         // Eat, press, activate, whatever.
114         // Called when item is right-clicked when lying on ground.
115         // If returns true, item shall be deleted.
116         virtual bool use(ServerEnvironment *env,
117                         Player *player){return false;}
118
119 protected:
120         u16 m_count;
121 };
122
123 class MaterialItem : public InventoryItem
124 {
125 public:
126         MaterialItem(content_t content, u16 count):
127                 InventoryItem(count)
128         {
129                 m_content = content;
130         }
131         /*
132                 Implementation interface
133         */
134         virtual const char* getName() const
135         {
136                 return "MaterialItem";
137         }
138         virtual void serialize(std::ostream &os) const
139         {
140                 //os.imbue(std::locale("C"));
141                 os<<"MaterialItem2";
142                 os<<" ";
143                 os<<(unsigned int)m_content;
144                 os<<" ";
145                 os<<m_count;
146         }
147         virtual InventoryItem* clone()
148         {
149                 return new MaterialItem(m_content, m_count);
150         }
151 #ifndef SERVER
152         video::ITexture * getImage()
153         {
154                 return content_features(m_content).inventory_texture;
155                 return NULL;
156         }
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         /*
186                 Special methods
187         */
188         content_t getMaterial()
189         {
190                 return m_content;
191         }
192 private:
193         content_t m_content;
194 };
195
196 //TODO: Remove
197 class MapBlockObjectItem : public InventoryItem
198 {
199 public:
200         MapBlockObjectItem(std::string inventorystring):
201                 InventoryItem(1)
202         {
203                 m_inventorystring = inventorystring;
204         }
205         
206         /*
207                 Implementation interface
208         */
209         virtual const char* getName() const
210         {
211                 return "MBOItem";
212         }
213         virtual void serialize(std::ostream &os) const
214         {
215                 std::string sane_string(m_inventorystring);
216                 str_replace_char(sane_string, '|', '?');
217                 os<<getName();
218                 os<<" ";
219                 os<<sane_string;
220                 os<<"|";
221         }
222         virtual InventoryItem* clone()
223         {
224                 return new MapBlockObjectItem(m_inventorystring);
225         }
226
227 #ifndef SERVER
228         video::ITexture * getImage();
229 #endif
230         std::string getText();
231
232         /*
233                 Special methods
234         */
235         std::string getInventoryString()
236         {
237                 return m_inventorystring;
238         }
239
240         MapBlockObject * createObject(v3f pos, f32 player_yaw, f32 player_pitch);
241
242 private:
243         std::string m_inventorystring;
244 };
245
246 /*
247         An item that is used as a mid-product when crafting.
248         Subnames:
249         - Stick
250 */
251 class CraftItem : public InventoryItem
252 {
253 public:
254         CraftItem(std::string subname, u16 count):
255                 InventoryItem(count)
256         {
257                 m_subname = subname;
258         }
259         /*
260                 Implementation interface
261         */
262         virtual const char* getName() const
263         {
264                 return "CraftItem";
265         }
266         virtual void serialize(std::ostream &os) const
267         {
268                 os<<getName();
269                 os<<" ";
270                 os<<m_subname;
271                 os<<" ";
272                 os<<m_count;
273         }
274         virtual InventoryItem* clone()
275         {
276                 return new CraftItem(m_subname, m_count);
277         }
278 #ifndef SERVER
279         video::ITexture * getImage();
280 #endif
281         std::string getText()
282         {
283                 std::ostringstream os;
284                 os<<m_count;
285                 return os.str();
286         }
287
288         ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
289         u16 getDropCount() const;
290
291         virtual bool addableTo(const InventoryItem *other) const
292         {
293                 if(std::string(other->getName()) != "CraftItem")
294                         return false;
295                 CraftItem *m = (CraftItem*)other;
296                 if(m->m_subname != m_subname)
297                         return false;
298                 return true;
299         }
300         u16 freeSpace() const
301         {
302                 if(m_count > QUANTITY_ITEM_MAX_COUNT)
303                         return 0;
304                 return QUANTITY_ITEM_MAX_COUNT - m_count;
305         }
306
307         /*
308                 Other properties
309         */
310
311         bool isCookable() const;
312         InventoryItem *createCookResult() const;
313
314         bool use(ServerEnvironment *env, Player *player);
315         
316         /*
317                 Special methods
318         */
319         std::string getSubName()
320         {
321                 return m_subname;
322         }
323 private:
324         std::string m_subname;
325 };
326
327 class ToolItem : public InventoryItem
328 {
329 public:
330         ToolItem(std::string toolname, u16 wear):
331                 InventoryItem(1)
332         {
333                 m_toolname = toolname;
334                 m_wear = wear;
335         }
336         /*
337                 Implementation interface
338         */
339         virtual const char* getName() const
340         {
341                 return "ToolItem";
342         }
343         virtual void serialize(std::ostream &os) const
344         {
345                 os<<getName();
346                 os<<" ";
347                 os<<m_toolname;
348                 os<<" ";
349                 os<<m_wear;
350         }
351         virtual InventoryItem* clone()
352         {
353                 return new ToolItem(m_toolname, m_wear);
354         }
355 #ifndef SERVER
356         video::ITexture * getImage()
357         {
358                 if(g_texturesource == NULL)
359                         return NULL;
360                 
361                 std::string basename;
362                 if(m_toolname == "WPick")
363                         basename = "tool_woodpick.png";
364                 else if(m_toolname == "STPick")
365                         basename = "tool_stonepick.png";
366                 else if(m_toolname == "SteelPick")
367                         basename = "tool_steelpick.png";
368                 else if(m_toolname == "MesePick")
369                         basename = "tool_mesepick.png";
370                 else if(m_toolname == "WShovel")
371                         basename = "tool_woodshovel.png";
372                 else if(m_toolname == "STShovel")
373                         basename = "tool_stoneshovel.png";
374                 else if(m_toolname == "SteelShovel")
375                         basename = "tool_steelshovel.png";
376                 else if(m_toolname == "WAxe")
377                         basename = "tool_woodaxe.png";
378                 else if(m_toolname == "STAxe")
379                         basename = "tool_stoneaxe.png";
380                 else if(m_toolname == "SteelAxe")
381                         basename = "tool_steelaxe.png";
382                 else if(m_toolname == "WSword")
383                         basename = "tool_woodsword.png";
384                 else if(m_toolname == "STSword")
385                         basename = "tool_stonesword.png";
386                 else if(m_toolname == "SteelSword")
387                         basename = "tool_steelsword.png";
388                 else
389                         basename = "cloud.png";
390                 
391                 /*
392                         Calculate a progress value with sane amount of
393                         maximum states
394                 */
395                 u32 maxprogress = 30;
396                 u32 toolprogress = (65535-m_wear)/(65535/maxprogress);
397                 
398                 float value_f = (float)toolprogress / (float)maxprogress;
399                 std::ostringstream os;
400                 os<<basename<<"^[progressbar"<<value_f;
401
402                 return g_texturesource->getTextureRaw(os.str());
403         }
404 #endif
405         std::string getText()
406         {
407                 return "";
408                 
409                 /*std::ostringstream os;
410                 u16 f = 4;
411                 u16 d = 65535/f;
412                 u16 i;
413                 for(i=0; i<(65535-m_wear)/d; i++)
414                         os<<'X';
415                 for(; i<f; i++)
416                         os<<'-';
417                 return os.str();*/
418                 
419                 /*std::ostringstream os;
420                 os<<m_toolname;
421                 os<<" ";
422                 os<<(m_wear/655);
423                 return os.str();*/
424         }
425         /*
426                 Special methods
427         */
428         std::string getToolName()
429         {
430                 return m_toolname;
431         }
432         u16 getWear()
433         {
434                 return m_wear;
435         }
436         // Returns true if weared out
437         bool addWear(u16 add)
438         {
439                 if(m_wear >= 65535 - add)
440                 {
441                         m_wear = 65535;
442                         return true;
443                 }
444                 else
445                 {
446                         m_wear += add;
447                         return false;
448                 }
449         }
450 private:
451         std::string m_toolname;
452         u16 m_wear;
453 };
454
455 class InventoryList
456 {
457 public:
458         InventoryList(std::string name, u32 size);
459         ~InventoryList();
460         void clearItems();
461         void serialize(std::ostream &os) const;
462         void deSerialize(std::istream &is);
463
464         InventoryList(const InventoryList &other);
465         InventoryList & operator = (const InventoryList &other);
466
467         const std::string &getName() const;
468         u32 getSize();
469         // Count used slots
470         u32 getUsedSlots();
471         u32 getFreeSlots();
472
473         /*bool getDirty(){ return m_dirty; }
474         void setDirty(bool dirty=true){ m_dirty = dirty; }*/
475         
476         // Get pointer to item
477         const InventoryItem * getItem(u32 i) const;
478         InventoryItem * getItem(u32 i);
479         // Returns old item (or NULL). Parameter can be NULL.
480         InventoryItem * changeItem(u32 i, InventoryItem *newitem);
481         // Delete item
482         void deleteItem(u32 i);
483
484         // Adds an item to a suitable place. Returns leftover item.
485         // If all went into the list, returns NULL.
486         InventoryItem * addItem(InventoryItem *newitem);
487
488         // If possible, adds item to given slot.
489         // If cannot be added at all, returns the item back.
490         // If can be added partly, decremented item is returned back.
491         // If can be added fully, NULL is returned.
492         InventoryItem * addItem(u32 i, InventoryItem *newitem);
493
494         // Checks whether the item could be added to the given slot
495         bool itemFits(const u32 i, const InventoryItem *newitem);
496
497         // Checks whether there is room for a given item
498         bool roomForItem(const InventoryItem *item);
499
500         // Checks whether there is room for a given item aftr it has been cooked
501         bool roomForCookedItem(const InventoryItem *item);
502
503         // Takes some items from a slot.
504         // If there are not enough, takes as many as it can.
505         // Returns NULL if couldn't take any.
506         InventoryItem * takeItem(u32 i, u32 count);
507
508         // Decrements amount of every material item
509         void decrementMaterials(u16 count);
510
511         void print(std::ostream &o);
512         
513 private:
514         core::array<InventoryItem*> m_items;
515         u32 m_size;
516         std::string m_name;
517         //bool m_dirty;
518 };
519
520 class Inventory
521 {
522 public:
523         ~Inventory();
524
525         void clear();
526
527         Inventory();
528         Inventory(const Inventory &other);
529         Inventory & operator = (const Inventory &other);
530         
531         void serialize(std::ostream &os) const;
532         void deSerialize(std::istream &is);
533
534         InventoryList * addList(const std::string &name, u32 size);
535         InventoryList * getList(const std::string &name);
536         const InventoryList * getList(const std::string &name) const;
537         bool deleteList(const std::string &name);
538         // A shorthand for adding items.
539         // Returns NULL if the item was fully added, leftover otherwise.
540         InventoryItem * addItem(const std::string &listname, InventoryItem *newitem)
541         {
542                 InventoryList *list = getList(listname);
543                 if(list == NULL)
544                         return newitem;
545                 return list->addItem(newitem);
546         }
547         
548 private:
549         // -1 if not found
550         const s32 getListIndex(const std::string &name) const;
551
552         core::array<InventoryList*> m_lists;
553 };
554
555 class Player;
556
557 struct InventoryContext
558 {
559         Player *current_player;
560         
561         InventoryContext():
562                 current_player(NULL)
563         {}
564 };
565
566 struct InventoryAction;
567
568 class InventoryManager
569 {
570 public:
571         InventoryManager(){}
572         virtual ~InventoryManager(){}
573         
574         /*
575                 Get a pointer to an inventory specified by id.
576                 id can be:
577                 - "current_player"
578                 - "nodemeta:X,Y,Z"
579         */
580         virtual Inventory* getInventory(InventoryContext *c, std::string id)
581                 {return NULL;}
582         // Used on the server by InventoryAction::apply and other stuff
583         virtual void inventoryModified(InventoryContext *c, std::string id)
584                 {}
585         // Used on the client
586         virtual void inventoryAction(InventoryAction *a)
587                 {}
588 };
589
590 #define IACTION_MOVE 0
591
592 struct InventoryAction
593 {
594         static InventoryAction * deSerialize(std::istream &is);
595         
596         virtual u16 getType() const = 0;
597         virtual void serialize(std::ostream &os) const = 0;
598         virtual void apply(InventoryContext *c, InventoryManager *mgr) = 0;
599 };
600
601 struct IMoveAction : public InventoryAction
602 {
603         // count=0 means "everything"
604         u16 count;
605         std::string from_inv;
606         std::string from_list;
607         s16 from_i;
608         std::string to_inv;
609         std::string to_list;
610         s16 to_i;
611         
612         IMoveAction()
613         {
614                 count = 0;
615                 from_i = -1;
616                 to_i = -1;
617         }
618         IMoveAction(std::istream &is)
619         {
620                 std::string ts;
621
622                 std::getline(is, ts, ' ');
623                 count = stoi(ts);
624
625                 std::getline(is, from_inv, ' ');
626
627                 std::getline(is, from_list, ' ');
628
629                 std::getline(is, ts, ' ');
630                 from_i = stoi(ts);
631
632                 std::getline(is, to_inv, ' ');
633
634                 std::getline(is, to_list, ' ');
635
636                 std::getline(is, ts, ' ');
637                 to_i = stoi(ts);
638         }
639
640         u16 getType() const
641         {
642                 return IACTION_MOVE;
643         }
644
645         void serialize(std::ostream &os) const
646         {
647                 os<<"Move ";
648                 os<<count<<" ";
649                 os<<from_inv<<" ";
650                 os<<from_list<<" ";
651                 os<<from_i<<" ";
652                 os<<to_inv<<" ";
653                 os<<to_list<<" ";
654                 os<<to_i;
655         }
656
657         void apply(InventoryContext *c, InventoryManager *mgr);
658 };
659
660 /*
661         Craft checking system
662 */
663
664 enum ItemSpecType
665 {
666         ITEM_NONE,
667         ITEM_MATERIAL,
668         ITEM_CRAFT,
669         ITEM_TOOL,
670         ITEM_MBO
671 };
672
673 struct ItemSpec
674 {
675         enum ItemSpecType type;
676         // Only other one of these is used
677         std::string name;
678         u16 num;
679
680         ItemSpec():
681                 type(ITEM_NONE)
682         {
683         }
684         ItemSpec(enum ItemSpecType a_type, std::string a_name):
685                 type(a_type),
686                 name(a_name),
687                 num(65535)
688         {
689         }
690         ItemSpec(enum ItemSpecType a_type, u16 a_num):
691                 type(a_type),
692                 name(""),
693                 num(a_num)
694         {
695         }
696
697         bool checkItem(const InventoryItem *item) const;
698 };
699
700 /*
701         items: a pointer to an array of 9 pointers to items
702         specs: a pointer to an array of 9 ItemSpecs
703 */
704 bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs);
705
706 #endif
707