]> git.lizzy.rs Git - minetest.git/blob - src/inventory.cpp
added dedicated server build without irrlicht
[minetest.git] / src / inventory.cpp
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 #include "inventory.h"
25 #include "serialization.h"
26 #include "utility.h"
27 #include "debug.h"
28 #include <sstream>
29 #include "main.h"
30
31 /*
32         InventoryItem
33 */
34
35 InventoryItem::InventoryItem()
36 {
37 }
38
39 InventoryItem::~InventoryItem()
40 {
41 }
42
43 InventoryItem* InventoryItem::deSerialize(std::istream &is)
44 {
45         DSTACK(__FUNCTION_NAME);
46
47         //is.imbue(std::locale("C"));
48         // Read name
49         std::string name;
50         std::getline(is, name, ' ');
51         
52         if(name == "MaterialItem")
53         {
54                 // u16 reads directly as a number (u8 doesn't)
55                 u16 material;
56                 is>>material;
57                 u16 count;
58                 is>>count;
59                 if(material > 255)
60                         throw SerializationError("Too large material number");
61                 return new MaterialItem(material, count);
62         }
63         else if(name == "MBOItem")
64         {
65                 std::string inventorystring;
66                 std::getline(is, inventorystring, '|');
67                 return new MapBlockObjectItem(inventorystring);
68         }
69         else
70         {
71                 dstream<<"Unknown InventoryItem name=\""<<name<<"\""<<std::endl;
72                 throw SerializationError("Unknown InventoryItem name");
73         }
74 }
75
76 /*
77         MapBlockObjectItem
78 */
79
80 video::ITexture * MapBlockObjectItem::getImage()
81 {
82         if(m_inventorystring.substr(0,3) == "Rat")
83                 return g_device->getVideoDriver()->getTexture("../data/rat.png");
84         
85         if(m_inventorystring.substr(0,4) == "Sign")
86                 return g_device->getVideoDriver()->getTexture("../data/sign.png");
87
88         return NULL;
89 }
90 std::string MapBlockObjectItem::getText()
91 {
92         if(m_inventorystring.substr(0,3) == "Rat")
93                 return "";
94         
95         if(m_inventorystring.substr(0,4) == "Sign")
96                 return "";
97
98         return "obj";
99 }
100
101 MapBlockObject * MapBlockObjectItem::createObject
102                 (v3f pos, f32 player_yaw, f32 player_pitch)
103 {
104         std::istringstream is(m_inventorystring);
105         std::string name;
106         std::getline(is, name, ' ');
107         
108         if(name == "None")
109         {
110                 return NULL;
111         }
112         else if(name == "Sign")
113         {
114                 std::string text;
115                 std::getline(is, text, '|');
116                 SignObject *obj = new SignObject(NULL, -1, pos);
117                 obj->setText(text);
118                 obj->setYaw(-player_yaw);
119                 return obj;
120         }
121         else if(name == "Rat")
122         {
123                 RatObject *obj = new RatObject(NULL, -1, pos);
124                 return obj;
125         }
126         else
127         {
128                 return NULL;
129         }
130 }
131
132 /*
133         Inventory
134 */
135
136 Inventory::Inventory(u32 size)
137 {
138         m_size = size;
139         clearItems();
140 }
141
142 Inventory::~Inventory()
143 {
144         for(u32 i=0; i<m_items.size(); i++)
145         {
146                 delete m_items[i];
147         }
148 }
149
150 void Inventory::clearItems()
151 {
152         m_items.clear();
153         for(u32 i=0; i<m_size; i++)
154         {
155                 m_items.push_back(NULL);
156         }
157 }
158
159 void Inventory::serialize(std::ostream &os)
160 {
161         //os.imbue(std::locale("C"));
162         
163         for(u32 i=0; i<m_items.size(); i++)
164         {
165                 InventoryItem *item = m_items[i];
166                 if(item != NULL)
167                 {
168                         os<<"Item ";
169                         item->serialize(os);
170                 }
171                 else
172                 {
173                         os<<"Empty";
174                 }
175                 os<<"\n";
176         }
177
178         os<<"end\n";
179 }
180
181 void Inventory::deSerialize(std::istream &is)
182 {
183         //is.imbue(std::locale("C"));
184
185         clearItems();
186         u32 item_i = 0;
187
188         for(;;)
189         {
190                 std::string line;
191                 std::getline(is, line, '\n');
192
193                 std::istringstream iss(line);
194                 //iss.imbue(std::locale("C"));
195
196                 std::string name;
197                 std::getline(iss, name, ' ');
198
199                 if(name == "end")
200                 {
201                         break;
202                 }
203                 else if(name == "Item")
204                 {
205                         if(item_i > getSize() - 1)
206                                 throw SerializationError("too many items");
207                         InventoryItem *item = InventoryItem::deSerialize(iss);
208                         m_items[item_i++] = item;
209                 }
210                 else if(name == "Empty")
211                 {
212                         if(item_i > getSize() - 1)
213                                 throw SerializationError("too many items");
214                         m_items[item_i++] = NULL;
215                 }
216                 else
217                 {
218                         throw SerializationError("Unknown inventory identifier");
219                 }
220         }
221 }
222
223 Inventory & Inventory::operator = (Inventory &other)
224 {
225         m_size = other.m_size;
226         clearItems();
227         for(u32 i=0; i<other.m_items.size(); i++)
228         {
229                 InventoryItem *item = other.m_items[i];
230                 if(item != NULL)
231                 {
232                         m_items[i] = item->clone();
233                 }
234         }
235
236         return *this;
237 }
238
239 u32 Inventory::getSize()
240 {
241         return m_items.size();
242 }
243
244 u32 Inventory::getUsedSlots()
245 {
246         u32 num = 0;
247         for(u32 i=0; i<m_items.size(); i++)
248         {
249                 InventoryItem *item = m_items[i];
250                 if(item != NULL)
251                         num++;
252         }
253         return num;
254 }
255
256 InventoryItem * Inventory::getItem(u32 i)
257 {
258         if(i > m_items.size() - 1)
259                 return NULL;
260         return m_items[i];
261 }
262
263 InventoryItem * Inventory::changeItem(u32 i, InventoryItem *newitem)
264 {
265         assert(i < m_items.size());
266
267         InventoryItem *olditem = m_items[i];
268         m_items[i] = newitem;
269         return olditem;
270 }
271
272 void Inventory::deleteItem(u32 i)
273 {
274         assert(i < m_items.size());
275         InventoryItem *item = changeItem(i, NULL);
276         if(item)
277                 delete item;
278 }
279
280 bool Inventory::addItem(InventoryItem *newitem)
281 {
282         // If it is a MaterialItem, try to find an already existing one
283         // and just increment the counter
284         if(std::string("MaterialItem") == newitem->getName())
285         {
286                 u8 material = ((MaterialItem*)newitem)->getMaterial();
287                 u8 count = ((MaterialItem*)newitem)->getCount();
288                 for(u32 i=0; i<m_items.size(); i++)
289                 {
290                         InventoryItem *item2 = m_items[i];
291                         if(item2 == NULL)
292                                 continue;
293                         if(std::string("MaterialItem") != item2->getName())
294                                 continue;
295                         // Found one. Check if it is of the right material and has
296                         // free space
297                         MaterialItem *mitem2 = (MaterialItem*)item2;
298                         if(mitem2->getMaterial() != material)
299                                 continue;
300                         //TODO: Add all that can be added and add remaining part
301                         // to another place
302                         if(mitem2->freeSpace() < count)
303                                 continue;
304                         // Add to the counter
305                         mitem2->add(count);
306                         // Dump the parameter
307                         delete newitem;
308                         return true;
309                 }
310         }
311         // Else find an empty position
312         for(u32 i=0; i<m_items.size(); i++)
313         {
314                 InventoryItem *item = m_items[i];
315                 if(item != NULL)
316                         continue;
317                 m_items[i] = newitem;
318                 return true;
319         }
320         // Failed
321         return false;
322 }
323
324 void Inventory::print(std::ostream &o)
325 {
326         o<<"Player inventory:"<<std::endl;
327         for(u32 i=0; i<m_items.size(); i++)
328         {
329                 InventoryItem *item = m_items[i];
330                 if(item != NULL)
331                 {
332                         o<<i<<": ";
333                         item->serialize(o);
334                         o<<"\n";
335                 }
336         }
337 }
338         
339 //END