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