Move tool stuff to tool.{h,cpp}
[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 getImageBasename() 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
304         std::string getImageBasename() const;
305
306 #ifndef SERVER
307         video::ITexture * getImage() const
308         {
309                 if(g_texturesource == NULL)
310                         return NULL;
311                 
312                 std::string basename = getImageBasename();
313                 
314                 /*
315                         Calculate a progress value with sane amount of
316                         maximum states
317                 */
318                 u32 maxprogress = 30;
319                 u32 toolprogress = (65535-m_wear)/(65535/maxprogress);
320                 
321                 float value_f = (float)toolprogress / (float)maxprogress;
322                 std::ostringstream os;
323                 os<<basename<<"^[progressbar"<<value_f;
324
325                 return g_texturesource->getTextureRaw(os.str());
326         }
327
328         video::ITexture * getImageRaw() const
329         {
330                 if(g_texturesource == NULL)
331                         return NULL;
332                 
333                 return g_texturesource->getTextureRaw(getImageBasename());
334         }
335 #endif
336         std::string getText()
337         {
338                 return "";
339                 
340                 /*std::ostringstream os;
341                 u16 f = 4;
342                 u16 d = 65535/f;
343                 u16 i;
344                 for(i=0; i<(65535-m_wear)/d; i++)
345                         os<<'X';
346                 for(; i<f; i++)
347                         os<<'-';
348                 return os.str();*/
349                 
350                 /*std::ostringstream os;
351                 os<<m_toolname;
352                 os<<" ";
353                 os<<(m_wear/655);
354                 return os.str();*/
355         }
356         /*
357                 Special methods
358         */
359         std::string getToolName()
360         {
361                 return m_toolname;
362         }
363         u16 getWear()
364         {
365                 return m_wear;
366         }
367         // Returns true if weared out
368         bool addWear(u16 add)
369         {
370                 if(m_wear >= 65535 - add)
371                 {
372                         m_wear = 65535;
373                         return true;
374                 }
375                 else
376                 {
377                         m_wear += add;
378                         return false;
379                 }
380         }
381 private:
382         std::string m_toolname;
383         u16 m_wear;
384 };
385
386 class InventoryList
387 {
388 public:
389         InventoryList(std::string name, u32 size);
390         ~InventoryList();
391         void clearItems();
392         void serialize(std::ostream &os) const;
393         void deSerialize(std::istream &is);
394
395         InventoryList(const InventoryList &other);
396         InventoryList & operator = (const InventoryList &other);
397
398         const std::string &getName() const;
399         u32 getSize();
400         // Count used slots
401         u32 getUsedSlots();
402         u32 getFreeSlots();
403
404         /*bool getDirty(){ return m_dirty; }
405         void setDirty(bool dirty=true){ m_dirty = dirty; }*/
406         
407         // Get pointer to item
408         const InventoryItem * getItem(u32 i) const;
409         InventoryItem * getItem(u32 i);
410         // Returns old item (or NULL). Parameter can be NULL.
411         InventoryItem * changeItem(u32 i, InventoryItem *newitem);
412         // Delete item
413         void deleteItem(u32 i);
414
415         // Adds an item to a suitable place. Returns leftover item.
416         // If all went into the list, returns NULL.
417         InventoryItem * addItem(InventoryItem *newitem);
418
419         // If possible, adds item to given slot.
420         // If cannot be added at all, returns the item back.
421         // If can be added partly, decremented item is returned back.
422         // If can be added fully, NULL is returned.
423         InventoryItem * addItem(u32 i, InventoryItem *newitem);
424
425         // Checks whether the item could be added to the given slot
426         bool itemFits(const u32 i, const InventoryItem *newitem);
427
428         // Checks whether there is room for a given item
429         bool roomForItem(const InventoryItem *item);
430
431         // Checks whether there is room for a given item aftr it has been cooked
432         bool roomForCookedItem(const InventoryItem *item);
433
434         // Takes some items from a slot.
435         // If there are not enough, takes as many as it can.
436         // Returns NULL if couldn't take any.
437         InventoryItem * takeItem(u32 i, u32 count);
438
439         // Decrements amount of every material item
440         void decrementMaterials(u16 count);
441
442         void print(std::ostream &o);
443         
444 private:
445         core::array<InventoryItem*> m_items;
446         u32 m_size;
447         std::string m_name;
448         //bool m_dirty;
449 };
450
451 class Inventory
452 {
453 public:
454         ~Inventory();
455
456         void clear();
457
458         Inventory();
459         Inventory(const Inventory &other);
460         Inventory & operator = (const Inventory &other);
461         
462         void serialize(std::ostream &os) const;
463         void deSerialize(std::istream &is);
464
465         InventoryList * addList(const std::string &name, u32 size);
466         InventoryList * getList(const std::string &name);
467         const InventoryList * getList(const std::string &name) const;
468         bool deleteList(const std::string &name);
469         // A shorthand for adding items.
470         // Returns NULL if the item was fully added, leftover otherwise.
471         InventoryItem * addItem(const std::string &listname, InventoryItem *newitem)
472         {
473                 InventoryList *list = getList(listname);
474                 if(list == NULL)
475                         return newitem;
476                 return list->addItem(newitem);
477         }
478         
479 private:
480         // -1 if not found
481         const s32 getListIndex(const std::string &name) const;
482
483         core::array<InventoryList*> m_lists;
484 };
485
486 class Player;
487
488 struct InventoryContext
489 {
490         Player *current_player;
491         
492         InventoryContext():
493                 current_player(NULL)
494         {}
495 };
496
497 struct InventoryAction;
498
499 class InventoryManager
500 {
501 public:
502         InventoryManager(){}
503         virtual ~InventoryManager(){}
504         
505         /*
506                 Get a pointer to an inventory specified by id.
507                 id can be:
508                 - "current_player"
509                 - "nodemeta:X,Y,Z"
510         */
511         virtual Inventory* getInventory(InventoryContext *c, std::string id)
512                 {return NULL;}
513         // Used on the server by InventoryAction::apply and other stuff
514         virtual void inventoryModified(InventoryContext *c, std::string id)
515                 {}
516         // Used on the client
517         virtual void inventoryAction(InventoryAction *a)
518                 {}
519 };
520
521 #define IACTION_MOVE 0
522
523 struct InventoryAction
524 {
525         static InventoryAction * deSerialize(std::istream &is);
526         
527         virtual u16 getType() const = 0;
528         virtual void serialize(std::ostream &os) const = 0;
529         virtual void apply(InventoryContext *c, InventoryManager *mgr) = 0;
530 };
531
532 struct IMoveAction : public InventoryAction
533 {
534         // count=0 means "everything"
535         u16 count;
536         std::string from_inv;
537         std::string from_list;
538         s16 from_i;
539         std::string to_inv;
540         std::string to_list;
541         s16 to_i;
542         
543         IMoveAction()
544         {
545                 count = 0;
546                 from_i = -1;
547                 to_i = -1;
548         }
549         IMoveAction(std::istream &is)
550         {
551                 std::string ts;
552
553                 std::getline(is, ts, ' ');
554                 count = stoi(ts);
555
556                 std::getline(is, from_inv, ' ');
557
558                 std::getline(is, from_list, ' ');
559
560                 std::getline(is, ts, ' ');
561                 from_i = stoi(ts);
562
563                 std::getline(is, to_inv, ' ');
564
565                 std::getline(is, to_list, ' ');
566
567                 std::getline(is, ts, ' ');
568                 to_i = stoi(ts);
569         }
570
571         u16 getType() const
572         {
573                 return IACTION_MOVE;
574         }
575
576         void serialize(std::ostream &os) const
577         {
578                 os<<"Move ";
579                 os<<count<<" ";
580                 os<<from_inv<<" ";
581                 os<<from_list<<" ";
582                 os<<from_i<<" ";
583                 os<<to_inv<<" ";
584                 os<<to_list<<" ";
585                 os<<to_i;
586         }
587
588         void apply(InventoryContext *c, InventoryManager *mgr);
589 };
590
591 /*
592         Craft checking system
593 */
594
595 enum ItemSpecType
596 {
597         ITEM_NONE,
598         ITEM_MATERIAL,
599         ITEM_CRAFT,
600         ITEM_TOOL,
601         ITEM_MBO
602 };
603
604 struct ItemSpec
605 {
606         enum ItemSpecType type;
607         // Only other one of these is used
608         std::string name;
609         u16 num;
610
611         ItemSpec():
612                 type(ITEM_NONE)
613         {
614         }
615         ItemSpec(enum ItemSpecType a_type, std::string a_name):
616                 type(a_type),
617                 name(a_name),
618                 num(65535)
619         {
620         }
621         ItemSpec(enum ItemSpecType a_type, u16 a_num):
622                 type(a_type),
623                 name(""),
624                 num(a_num)
625         {
626         }
627
628         bool checkItem(const InventoryItem *item) const;
629 };
630
631 /*
632         items: a pointer to an array of 9 pointers to items
633         specs: a pointer to an array of 9 ItemSpecs
634 */
635 bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs);
636
637 #endif
638