8627e18d089ebebae0b3aecb6e463dcd548be84b
[oweals/minetest.git] / src / content_nodemeta.cpp
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 #include "content_nodemeta.h"
21 #include "inventory.h"
22 #include "content_mapnode.h"
23
24 /*
25         SignNodeMetadata
26 */
27
28 // Prototype
29 SignNodeMetadata proto_SignNodeMetadata("");
30
31 SignNodeMetadata::SignNodeMetadata(std::string text):
32         m_text(text)
33 {
34         NodeMetadata::registerType(typeId(), create);
35 }
36 u16 SignNodeMetadata::typeId() const
37 {
38         return CONTENT_SIGN_WALL;
39 }
40 NodeMetadata* SignNodeMetadata::create(std::istream &is)
41 {
42         std::string text = deSerializeString(is);
43         return new SignNodeMetadata(text);
44 }
45 NodeMetadata* SignNodeMetadata::clone()
46 {
47         return new SignNodeMetadata(m_text);
48 }
49 void SignNodeMetadata::serializeBody(std::ostream &os)
50 {
51         os<<serializeString(m_text);
52 }
53 std::string SignNodeMetadata::infoText()
54 {
55         return std::string("\"")+m_text+"\"";
56 }
57
58 /*
59         ChestNodeMetadata
60 */
61
62 // Prototype
63 ChestNodeMetadata proto_ChestNodeMetadata;
64
65 ChestNodeMetadata::ChestNodeMetadata()
66 {
67         NodeMetadata::registerType(typeId(), create);
68         
69         m_inventory = new Inventory();
70         m_inventory->addList("0", 8*4);
71 }
72 ChestNodeMetadata::~ChestNodeMetadata()
73 {
74         delete m_inventory;
75 }
76 u16 ChestNodeMetadata::typeId() const
77 {
78         return CONTENT_CHEST;
79 }
80 NodeMetadata* ChestNodeMetadata::create(std::istream &is)
81 {
82         ChestNodeMetadata *d = new ChestNodeMetadata();
83         d->m_inventory->deSerialize(is);
84         return d;
85 }
86 NodeMetadata* ChestNodeMetadata::clone()
87 {
88         ChestNodeMetadata *d = new ChestNodeMetadata();
89         *d->m_inventory = *m_inventory;
90         return d;
91 }
92 void ChestNodeMetadata::serializeBody(std::ostream &os)
93 {
94         m_inventory->serialize(os);
95 }
96 std::string ChestNodeMetadata::infoText()
97 {
98         return "Chest";
99 }
100 bool ChestNodeMetadata::nodeRemovalDisabled()
101 {
102         /*
103                 Disable removal if chest contains something
104         */
105         InventoryList *list = m_inventory->getList("0");
106         if(list == NULL)
107                 return false;
108         if(list->getUsedSlots() == 0)
109                 return false;
110         return true;
111 }
112
113 /*
114         FurnaceNodeMetadata
115 */
116
117 // Prototype
118 FurnaceNodeMetadata proto_FurnaceNodeMetadata;
119
120 FurnaceNodeMetadata::FurnaceNodeMetadata()
121 {
122         NodeMetadata::registerType(typeId(), create);
123         
124         m_inventory = new Inventory();
125         m_inventory->addList("fuel", 1);
126         m_inventory->addList("src", 1);
127         m_inventory->addList("dst", 4);
128
129         m_step_accumulator = 0;
130         m_fuel_totaltime = 0;
131         m_fuel_time = 0;
132         m_src_totaltime = 0;
133         m_src_time = 0;
134 }
135 FurnaceNodeMetadata::~FurnaceNodeMetadata()
136 {
137         delete m_inventory;
138 }
139 u16 FurnaceNodeMetadata::typeId() const
140 {
141         return CONTENT_FURNACE;
142 }
143 NodeMetadata* FurnaceNodeMetadata::clone()
144 {
145         FurnaceNodeMetadata *d = new FurnaceNodeMetadata();
146         *d->m_inventory = *m_inventory;
147         return d;
148 }
149 NodeMetadata* FurnaceNodeMetadata::create(std::istream &is)
150 {
151         FurnaceNodeMetadata *d = new FurnaceNodeMetadata();
152
153         d->m_inventory->deSerialize(is);
154
155         int temp;
156         is>>temp;
157         d->m_fuel_totaltime = (float)temp/10;
158         is>>temp;
159         d->m_fuel_time = (float)temp/10;
160
161         return d;
162 }
163 void FurnaceNodeMetadata::serializeBody(std::ostream &os)
164 {
165         m_inventory->serialize(os);
166         os<<itos(m_fuel_totaltime*10)<<" ";
167         os<<itos(m_fuel_time*10)<<" ";
168 }
169 std::string FurnaceNodeMetadata::infoText()
170 {
171         //return "Furnace";
172         if(m_fuel_time >= m_fuel_totaltime)
173         {
174                 InventoryList *src_list = m_inventory->getList("src");
175                 assert(src_list);
176                 InventoryItem *src_item = src_list->getItem(0);
177
178                 if(src_item)
179                         return "Furnace is out of fuel";
180                 else
181                         return "Furnace is inactive";
182         }
183         else
184         {
185                 std::string s = "Furnace is active (";
186                 s += itos(m_fuel_time/m_fuel_totaltime*100);
187                 s += "%)";
188                 return s;
189         }
190 }
191 void FurnaceNodeMetadata::inventoryModified()
192 {
193         dstream<<"Furnace inventory modification callback"<<std::endl;
194 }
195 bool FurnaceNodeMetadata::step(float dtime)
196 {
197         if(dtime > 60.0)
198                 dstream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
199         // Update at a fixed frequency
200         const float interval = 2.0;
201         m_step_accumulator += dtime;
202         bool changed = false;
203         while(m_step_accumulator > interval)
204         {
205                 m_step_accumulator -= interval;
206                 dtime = interval;
207
208                 //dstream<<"Furnace step dtime="<<dtime<<std::endl;
209                 
210                 InventoryList *dst_list = m_inventory->getList("dst");
211                 assert(dst_list);
212
213                 InventoryList *src_list = m_inventory->getList("src");
214                 assert(src_list);
215                 InventoryItem *src_item = src_list->getItem(0);
216                 
217                 // Start only if there are free slots in dst, so that it can
218                 // accomodate any result item
219                 if(dst_list->getFreeSlots() > 0 && src_item && src_item->isCookable())
220                 {
221                         m_src_totaltime = 3;
222                 }
223                 else
224                 {
225                         m_src_time = 0;
226                         m_src_totaltime = 0;
227                 }
228                 
229                 /*
230                         If fuel is burning, increment the burn counters.
231                         If item finishes cooking, move it to result.
232                 */
233                 if(m_fuel_time < m_fuel_totaltime)
234                 {
235                         //dstream<<"Furnace is active"<<std::endl;
236                         m_fuel_time += dtime;
237                         m_src_time += dtime;
238                         if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001
239                                         && src_item)
240                         {
241                                 InventoryItem *cookresult = src_item->createCookResult();
242                                 dst_list->addItem(cookresult);
243                                 src_list->decrementMaterials(1);
244                                 m_src_time = 0;
245                                 m_src_totaltime = 0;
246                         }
247                         changed = true;
248                         continue;
249                 }
250                 
251                 /*
252                         If there is no source item or source item is not cookable, stop loop.
253                 */
254                 if(src_item == NULL || m_src_totaltime < 0.001)
255                 {
256                         m_step_accumulator = 0;
257                         break;
258                 }
259                 
260                 //dstream<<"Furnace is out of fuel"<<std::endl;
261
262                 InventoryList *fuel_list = m_inventory->getList("fuel");
263                 assert(fuel_list);
264                 InventoryItem *fuel_item = fuel_list->getItem(0);
265
266                 if(ItemSpec(ITEM_MATERIAL, CONTENT_TREE).checkItem(fuel_item))
267                 {
268                         m_fuel_totaltime = 30;
269                         m_fuel_time = 0;
270                         fuel_list->decrementMaterials(1);
271                         changed = true;
272                 }
273                 else if(ItemSpec(ITEM_MATERIAL, CONTENT_WOOD).checkItem(fuel_item))
274                 {
275                         m_fuel_totaltime = 30/4;
276                         m_fuel_time = 0;
277                         fuel_list->decrementMaterials(1);
278                         changed = true;
279                 }
280                 else if(ItemSpec(ITEM_CRAFT, "Stick").checkItem(fuel_item))
281                 {
282                         m_fuel_totaltime = 30/4/4;
283                         m_fuel_time = 0;
284                         fuel_list->decrementMaterials(1);
285                         changed = true;
286                 }
287                 else if(ItemSpec(ITEM_CRAFT, "lump_of_coal").checkItem(fuel_item))
288                 {
289                         m_fuel_totaltime = 40;
290                         m_fuel_time = 0;
291                         fuel_list->decrementMaterials(1);
292                         changed = true;
293                 }
294                 else
295                 {
296                         //dstream<<"No fuel found"<<std::endl;
297                         // No fuel, stop loop.
298                         m_step_accumulator = 0;
299                         break;
300                 }
301         }
302         return changed;
303 }
304
305