]> git.lizzy.rs Git - minetest.git/blob - src/inventory.h
Improved MaterialItem (stores nodename)
[minetest.git] / src / inventory.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 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 #ifndef INVENTORY_HEADER
21 #define INVENTORY_HEADER
22
23 #include <iostream>
24 #include <sstream>
25 #include <string>
26 #include "common_irrlicht.h"
27 #include "debug.h"
28 #include "mapnode.h" // For content_t
29
30 #define QUANTITY_ITEM_MAX_COUNT 99
31
32 class ServerActiveObject;
33 class ServerEnvironment;
34 class ITextureSource;
35 class IGameDef;
36
37 class InventoryItem
38 {
39 public:
40         InventoryItem(IGameDef *gamedef, u16 count);
41         virtual ~InventoryItem();
42         
43         static InventoryItem* deSerialize(std::istream &is, IGameDef *gamedef);
44         
45         virtual const char* getName() const = 0;
46         // Shall write the name and the parameters
47         virtual void serialize(std::ostream &os) const = 0;
48         // Shall make an exact clone of the item
49         virtual InventoryItem* clone() = 0;
50         // Return the name of the image for this item
51         virtual std::string getImageBasename() const { return ""; }
52 #ifndef SERVER
53         // Shall return an image of the item (or NULL)
54         virtual video::ITexture * getImage(ITextureSource *tsrc) const
55                 { return NULL; }
56         // Shall return an image of the item without embellishments (or NULL)
57         virtual video::ITexture * getImageRaw(ITextureSource *tsrc) const
58                 { return getImage(tsrc); }
59 #endif
60         // Shall return a text to show in the GUI
61         virtual std::string getText() { return ""; }
62         // Returns the string used for inventory
63         virtual std::string getItemString();
64         // Creates an object from the item, to be placed in the world.
65         virtual ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
66         // Gets amount of items that dropping one SAO will decrement
67         virtual u16 getDropCount() const { return getCount(); }
68
69         /*
70                 Quantity methods
71         */
72
73         // Shall return true if the item can be add()ed to the other
74         virtual bool addableTo(const InventoryItem *other) const
75         {
76                 return false;
77         }
78         
79         u16 getCount() const
80         {
81                 return m_count;
82         }
83         void setCount(u16 count)
84         {
85                 m_count = count;
86         }
87         // This should return something else for stackable items
88         virtual u16 freeSpace() const
89         {
90                 return 0;
91         }
92         void add(u16 count)
93         {
94                 assert(m_count + count <= QUANTITY_ITEM_MAX_COUNT);
95                 m_count += count;
96         }
97         void remove(u16 count)
98         {
99                 assert(m_count >= count);
100                 m_count -= count;
101         }
102
103         /*
104                 Other properties
105         */
106
107         // Whether it can be cooked
108         virtual bool isCookable() const {return false;}
109         // Result of cooking (can randomize)
110         virtual InventoryItem *createCookResult() const {return NULL;}
111         // Time of cooking
112         virtual float getCookTime() const {return 3.0;}
113         // Whether it can be burned (<0 = cannot be burned)
114         virtual float getBurnTime() const {return -1;}
115         
116         // Eat, press, activate, whatever.
117         // Called when item is right-clicked when lying on ground.
118         // If returns true, item shall be deleted.
119         virtual bool use(ServerEnvironment *env,
120                         ServerActiveObject *user){return false;}
121
122 protected:
123         IGameDef *m_gamedef;
124         u16 m_count;
125 };
126
127 class MaterialItem : public InventoryItem
128 {
129 public:
130         MaterialItem(IGameDef *gamedef, std::string nodename, u16 count);
131         // Legacy constructor
132         MaterialItem(IGameDef *gamedef, content_t content, u16 count);
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                 std::string nodename = m_nodename;
143                 if(nodename == "")
144                         nodename = "unknown_block";
145                         
146                 os<<"MaterialItem3";
147                 os<<" \"";
148                 os<<nodename;
149                 os<<"\" ";
150                 os<<m_count;
151
152                 // Old
153                 /*os<<"MaterialItem2";
154                 os<<" ";
155                 os<<(unsigned int)m_content;
156                 os<<" ";
157                 os<<m_count;*/
158         }
159         virtual InventoryItem* clone()
160         {
161                 return new MaterialItem(m_gamedef, m_nodename, m_count);
162         }
163 #ifndef SERVER
164         video::ITexture * getImage(ITextureSource *tsrc) const;
165 #endif
166         std::string getText()
167         {
168                 std::ostringstream os;
169                 os<<m_count;
170                 return os.str();
171         }
172
173         virtual bool addableTo(const InventoryItem *other) const
174         {
175                 if(std::string(other->getName()) != "MaterialItem")
176                         return false;
177                 MaterialItem *m = (MaterialItem*)other;
178                 if(m->m_nodename != m_nodename)
179                         return false;
180                 return true;
181         }
182         u16 freeSpace() const
183         {
184                 if(m_count > QUANTITY_ITEM_MAX_COUNT)
185                         return 0;
186                 return QUANTITY_ITEM_MAX_COUNT - m_count;
187         }
188         /*
189                 Other properties
190         */
191         bool isCookable() const;
192         InventoryItem *createCookResult() const;
193         float getCookTime() const;
194         float getBurnTime() const;
195         /*
196                 Special properties (not part of virtual interface)
197         */
198         std::string getNodeName() const
199         { return m_nodename; }
200         content_t getMaterial() const;
201 private:
202         std::string m_nodename;
203 };
204
205 /*
206         An item that is used as a mid-product when crafting.
207         Subnames:
208         - Stick
209 */
210 class CraftItem : public InventoryItem
211 {
212 public:
213         CraftItem(IGameDef *gamedef, std::string subname, u16 count):
214                 InventoryItem(gamedef, count)
215         {
216                 m_subname = subname;
217         }
218         /*
219                 Implementation interface
220         */
221         virtual const char* getName() const
222         {
223                 return "CraftItem";
224         }
225         virtual void serialize(std::ostream &os) const
226         {
227                 os<<getName();
228                 os<<" ";
229                 os<<m_subname;
230                 os<<" ";
231                 os<<m_count;
232         }
233         virtual InventoryItem* clone()
234         {
235                 return new CraftItem(m_gamedef, m_subname, m_count);
236         }
237 #ifndef SERVER
238         video::ITexture * getImage(ITextureSource *tsrc) const;
239 #endif
240         std::string getText()
241         {
242                 std::ostringstream os;
243                 os<<m_count;
244                 return os.str();
245         }
246
247         ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
248         u16 getDropCount() const;
249
250         virtual bool addableTo(const InventoryItem *other) const
251         {
252                 if(std::string(other->getName()) != "CraftItem")
253                         return false;
254                 CraftItem *m = (CraftItem*)other;
255                 if(m->m_subname != m_subname)
256                         return false;
257                 return true;
258         }
259         u16 freeSpace() const
260         {
261                 if(m_count > QUANTITY_ITEM_MAX_COUNT)
262                         return 0;
263                 return QUANTITY_ITEM_MAX_COUNT - m_count;
264         }
265
266         /*
267                 Other properties
268         */
269
270         bool isCookable() const;
271         InventoryItem *createCookResult() const;
272         float getCookTime() const;
273         float getBurnTime() const;
274
275         bool use(ServerEnvironment *env, ServerActiveObject *user);
276         
277         /*
278                 Special methods
279         */
280         std::string getSubName()
281         {
282                 return m_subname;
283         }
284 private:
285         std::string m_subname;
286 };
287
288 class ToolItem : public InventoryItem
289 {
290 public:
291         ToolItem(IGameDef *gamedef, std::string toolname, u16 wear):
292                 InventoryItem(gamedef, 1)
293         {
294                 m_toolname = toolname;
295                 m_wear = wear;
296         }
297         /*
298                 Implementation interface
299         */
300         virtual const char* getName() const
301         {
302                 return "ToolItem";
303         }
304         virtual void serialize(std::ostream &os) const
305         {
306                 os<<getName();
307                 os<<" ";
308                 os<<m_toolname;
309                 os<<" ";
310                 os<<m_wear;
311         }
312         virtual InventoryItem* clone()
313         {
314                 return new ToolItem(m_gamedef, m_toolname, m_wear);
315         }
316
317         std::string getImageBasename() const;
318 #ifndef SERVER
319         video::ITexture * getImage(ITextureSource *tsrc) const;
320         video::ITexture * getImageRaw(ITextureSource *tsrc) const;
321 #endif
322
323         std::string getText()
324         {
325                 return "";
326                 
327                 /*std::ostringstream os;
328                 u16 f = 4;
329                 u16 d = 65535/f;
330                 u16 i;
331                 for(i=0; i<(65535-m_wear)/d; i++)
332                         os<<'X';
333                 for(; i<f; i++)
334                         os<<'-';
335                 return os.str();*/
336                 
337                 /*std::ostringstream os;
338                 os<<m_toolname;
339                 os<<" ";
340                 os<<(m_wear/655);
341                 return os.str();*/
342         }
343         /*
344                 Special methods
345         */
346         std::string getToolName()
347         {
348                 return m_toolname;
349         }
350         u16 getWear()
351         {
352                 return m_wear;
353         }
354         // Returns true if weared out
355         bool addWear(u16 add)
356         {
357                 if(m_wear >= 65535 - add)
358                 {
359                         m_wear = 65535;
360                         return true;
361                 }
362                 else
363                 {
364                         m_wear += add;
365                         return false;
366                 }
367         }
368 private:
369         std::string m_toolname;
370         u16 m_wear;
371 };
372
373 class InventoryList
374 {
375 public:
376         InventoryList(std::string name, u32 size);
377         ~InventoryList();
378         void clearItems();
379         void serialize(std::ostream &os) const;
380         void deSerialize(std::istream &is, IGameDef *gamedef);
381
382         InventoryList(const InventoryList &other);
383         InventoryList & operator = (const InventoryList &other);
384
385         const std::string &getName() const;
386         u32 getSize();
387         // Count used slots
388         u32 getUsedSlots();
389         u32 getFreeSlots();
390
391         /*bool getDirty(){ return m_dirty; }
392         void setDirty(bool dirty=true){ m_dirty = dirty; }*/
393         
394         // Get pointer to item
395         const InventoryItem * getItem(u32 i) const;
396         InventoryItem * getItem(u32 i);
397         // Returns old item (or NULL). Parameter can be NULL.
398         InventoryItem * changeItem(u32 i, InventoryItem *newitem);
399         // Delete item
400         void deleteItem(u32 i);
401
402         // Adds an item to a suitable place. Returns leftover item.
403         // If all went into the list, returns NULL.
404         InventoryItem * addItem(InventoryItem *newitem);
405
406         // If possible, adds item to given slot.
407         // If cannot be added at all, returns the item back.
408         // If can be added partly, decremented item is returned back.
409         // If can be added fully, NULL is returned.
410         InventoryItem * addItem(u32 i, InventoryItem *newitem);
411
412         // Checks whether the item could be added to the given slot
413         bool itemFits(const u32 i, const InventoryItem *newitem);
414
415         // Checks whether there is room for a given item
416         bool roomForItem(const InventoryItem *item);
417
418         // Checks whether there is room for a given item aftr it has been cooked
419         bool roomForCookedItem(const InventoryItem *item);
420
421         // Takes some items from a slot.
422         // If there are not enough, takes as many as it can.
423         // Returns NULL if couldn't take any.
424         InventoryItem * takeItem(u32 i, u32 count);
425
426         // Decrements amount of every material item
427         void decrementMaterials(u16 count);
428
429         void print(std::ostream &o);
430         
431 private:
432         core::array<InventoryItem*> m_items;
433         u32 m_size;
434         std::string m_name;
435         //bool m_dirty;
436 };
437
438 class Inventory
439 {
440 public:
441         ~Inventory();
442
443         void clear();
444
445         Inventory();
446         Inventory(const Inventory &other);
447         Inventory & operator = (const Inventory &other);
448         
449         void serialize(std::ostream &os) const;
450         void deSerialize(std::istream &is, IGameDef *gamedef);
451
452         InventoryList * addList(const std::string &name, u32 size);
453         InventoryList * getList(const std::string &name);
454         const InventoryList * getList(const std::string &name) const;
455         bool deleteList(const std::string &name);
456         // A shorthand for adding items.
457         // Returns NULL if the item was fully added, leftover otherwise.
458         InventoryItem * addItem(const std::string &listname, InventoryItem *newitem)
459         {
460                 InventoryList *list = getList(listname);
461                 if(list == NULL)
462                         return newitem;
463                 return list->addItem(newitem);
464         }
465         
466 private:
467         // -1 if not found
468         const s32 getListIndex(const std::string &name) const;
469
470         core::array<InventoryList*> m_lists;
471 };
472
473 class Player;
474
475 struct InventoryContext
476 {
477         Player *current_player;
478         
479         InventoryContext():
480                 current_player(NULL)
481         {}
482 };
483
484 struct InventoryAction;
485
486 class InventoryManager
487 {
488 public:
489         InventoryManager(){}
490         virtual ~InventoryManager(){}
491         
492         /*
493                 Get a pointer to an inventory specified by id.
494                 id can be:
495                 - "current_player"
496                 - "nodemeta:X,Y,Z"
497         */
498         virtual Inventory* getInventory(InventoryContext *c, std::string id)
499                 {return NULL;}
500         // Used on the server by InventoryAction::apply and other stuff
501         virtual void inventoryModified(InventoryContext *c, std::string id)
502                 {}
503         // Used on the client
504         virtual void inventoryAction(InventoryAction *a)
505                 {}
506 };
507
508 #define IACTION_MOVE 0
509
510 struct InventoryAction
511 {
512         static InventoryAction * deSerialize(std::istream &is);
513         
514         virtual u16 getType() const = 0;
515         virtual void serialize(std::ostream &os) const = 0;
516         virtual void apply(InventoryContext *c, InventoryManager *mgr) = 0;
517 };
518
519 struct IMoveAction : public InventoryAction
520 {
521         // count=0 means "everything"
522         u16 count;
523         std::string from_inv;
524         std::string from_list;
525         s16 from_i;
526         std::string to_inv;
527         std::string to_list;
528         s16 to_i;
529         
530         IMoveAction()
531         {
532                 count = 0;
533                 from_i = -1;
534                 to_i = -1;
535         }
536         
537         IMoveAction(std::istream &is);
538
539         u16 getType() const
540         {
541                 return IACTION_MOVE;
542         }
543
544         void serialize(std::ostream &os) const
545         {
546                 os<<"Move ";
547                 os<<count<<" ";
548                 os<<from_inv<<" ";
549                 os<<from_list<<" ";
550                 os<<from_i<<" ";
551                 os<<to_inv<<" ";
552                 os<<to_list<<" ";
553                 os<<to_i;
554         }
555
556         void apply(InventoryContext *c, InventoryManager *mgr);
557 };
558
559 /*
560         Craft checking system
561 */
562
563 enum ItemSpecType
564 {
565         ITEM_NONE,
566         ITEM_MATERIAL,
567         ITEM_CRAFT,
568         ITEM_TOOL,
569         ITEM_MBO
570 };
571
572 struct ItemSpec
573 {
574         enum ItemSpecType type;
575         // Only other one of these is used
576         std::string name;
577         u16 num;
578
579         ItemSpec():
580                 type(ITEM_NONE)
581         {
582         }
583         ItemSpec(enum ItemSpecType a_type, std::string a_name):
584                 type(a_type),
585                 name(a_name),
586                 num(65535)
587         {
588         }
589         ItemSpec(enum ItemSpecType a_type, u16 a_num):
590                 type(a_type),
591                 name(""),
592                 num(a_num)
593         {
594         }
595
596         bool checkItem(const InventoryItem *item) const;
597 };
598
599 /*
600         items: a pointer to an array of 9 pointers to items
601         specs: a pointer to an array of 9 ItemSpecs
602 */
603 bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs);
604
605 #endif
606