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