]> git.lizzy.rs Git - dragonfireclient.git/blob - src/serverobject.cpp
fixed problem with vc++ build crashing at startup
[dragonfireclient.git] / src / serverobject.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 "serverobject.h"
21 #include <fstream>
22 #include "environment.h"
23 #include "inventory.h"
24 #include "collision.h"
25
26 core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
27
28 ServerActiveObject::ServerActiveObject(ServerEnvironment *env, u16 id, v3f pos):
29         ActiveObject(id),
30         m_known_by_count(0),
31         m_removed(false),
32         m_static_exists(false),
33         m_static_block(1337,1337,1337),
34         m_env(env),
35         m_base_position(pos)
36 {
37 }
38
39 ServerActiveObject::~ServerActiveObject()
40 {
41 }
42
43 ServerActiveObject* ServerActiveObject::create(u8 type,
44                 ServerEnvironment *env, u16 id, v3f pos,
45                 const std::string &data)
46 {
47         // Find factory function
48         core::map<u16, Factory>::Node *n;
49         n = m_types.find(type);
50         if(n == NULL)
51         {
52                 // If factory is not found, just return.
53                 dstream<<"WARNING: ServerActiveObject: No factory for type="
54                                 <<type<<std::endl;
55                 return NULL;
56         }
57
58         Factory f = n->getValue();
59         ServerActiveObject *object = (*f)(env, id, pos, data);
60         return object;
61 }
62
63 void ServerActiveObject::registerType(u16 type, Factory f)
64 {
65         core::map<u16, Factory>::Node *n;
66         n = m_types.find(type);
67         if(n)
68                 return;
69         m_types.insert(type, f);
70 }
71
72
73 /*
74         TestSAO
75 */
76
77 // Prototype
78 TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0));
79
80 TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos):
81         ServerActiveObject(env, id, pos),
82         m_timer1(0),
83         m_age(0)
84 {
85         ServerActiveObject::registerType(getType(), create);
86 }
87
88 ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos,
89                 const std::string &data)
90 {
91         return new TestSAO(env, id, pos);
92 }
93
94 void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
95                 bool send_recommended)
96 {
97         m_age += dtime;
98         if(m_age > 10)
99         {
100                 m_removed = true;
101                 return;
102         }
103
104         m_base_position.Y += dtime * BS * 2;
105         if(m_base_position.Y > 8*BS)
106                 m_base_position.Y = 2*BS;
107
108         if(send_recommended == false)
109                 return;
110
111         m_timer1 -= dtime;
112         if(m_timer1 < 0.0)
113         {
114                 m_timer1 += 0.125;
115                 //dstream<<"TestSAO: id="<<getId()<<" sending data"<<std::endl;
116
117                 std::string data;
118
119                 data += itos(0); // 0 = position
120                 data += " ";
121                 data += itos(m_base_position.X);
122                 data += " ";
123                 data += itos(m_base_position.Y);
124                 data += " ";
125                 data += itos(m_base_position.Z);
126
127                 ActiveObjectMessage aom(getId(), false, data);
128                 messages.push_back(aom);
129         }
130 }
131
132
133 /*
134         ItemSAO
135 */
136
137 // Prototype
138 ItemSAO proto_ItemSAO(NULL, 0, v3f(0,0,0), "");
139
140 ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
141                 const std::string inventorystring):
142         ServerActiveObject(env, id, pos),
143         m_inventorystring(inventorystring),
144         m_speed_f(0,0,0),
145         m_last_sent_position(0,0,0)
146 {
147         ServerActiveObject::registerType(getType(), create);
148 }
149
150 ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos,
151                 const std::string &data)
152 {
153         std::istringstream is(data, std::ios::binary);
154         char buf[1];
155         // read version
156         is.read(buf, 1);
157         u8 version = buf[0];
158         // check if version is supported
159         if(version != 0)
160                 return NULL;
161         std::string inventorystring = deSerializeString(is);
162         dstream<<"ItemSAO::create(): Creating item \""
163                         <<inventorystring<<"\""<<std::endl;
164         return new ItemSAO(env, id, pos, inventorystring);
165 }
166
167 void ItemSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
168                 bool send_recommended)
169 {
170         assert(m_env);
171
172         const float interval = 0.2;
173         if(m_move_interval.step(dtime, interval)==false)
174                 return;
175         dtime = interval;
176         
177         core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
178         collisionMoveResult moveresult;
179         // Apply gravity
180         m_speed_f += v3f(0, -dtime*9.81*BS, 0);
181         // Maximum movement without glitches
182         f32 pos_max_d = BS*0.25;
183         // Limit speed
184         if(m_speed_f.getLength()*dtime > pos_max_d)
185                 m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
186         v3f pos_f = getBasePosition();
187         v3f pos_f_old = pos_f;
188         moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
189                         box, dtime, pos_f, m_speed_f);
190         
191         if(send_recommended == false)
192                 return;
193
194         if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
195         {
196                 setBasePosition(pos_f);
197                 m_last_sent_position = pos_f;
198
199                 std::ostringstream os(std::ios::binary);
200                 char buf[6];
201                 // command (0 = update position)
202                 buf[0] = 0;
203                 os.write(buf, 1);
204                 // pos
205                 writeS32((u8*)buf, m_base_position.X*1000);
206                 os.write(buf, 4);
207                 writeS32((u8*)buf, m_base_position.Y*1000);
208                 os.write(buf, 4);
209                 writeS32((u8*)buf, m_base_position.Z*1000);
210                 os.write(buf, 4);
211                 // create message and add to list
212                 ActiveObjectMessage aom(getId(), false, os.str());
213                 messages.push_back(aom);
214         }
215 }
216
217 std::string ItemSAO::getClientInitializationData()
218 {
219         std::ostringstream os(std::ios::binary);
220         char buf[6];
221         // version
222         buf[0] = 0;
223         os.write(buf, 1);
224         // pos
225         writeS32((u8*)buf, m_base_position.X*1000);
226         os.write(buf, 4);
227         writeS32((u8*)buf, m_base_position.Y*1000);
228         os.write(buf, 4);
229         writeS32((u8*)buf, m_base_position.Z*1000);
230         os.write(buf, 4);
231         // inventorystring
232         os<<serializeString(m_inventorystring);
233         return os.str();
234 }
235
236 std::string ItemSAO::getStaticData()
237 {
238         dstream<<__FUNCTION_NAME<<std::endl;
239         std::ostringstream os(std::ios::binary);
240         char buf[1];
241         // version
242         buf[0] = 0;
243         os.write(buf, 1);
244         // inventorystring
245         os<<serializeString(m_inventorystring);
246         return os.str();
247 }
248
249 InventoryItem * ItemSAO::createInventoryItem()
250 {
251         try{
252                 std::istringstream is(m_inventorystring, std::ios_base::binary);
253                 InventoryItem *item = InventoryItem::deSerialize(is);
254                 dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
255                                 <<m_inventorystring<<"\" -> item="<<item
256                                 <<std::endl;
257                 return item;
258         }
259         catch(SerializationError &e)
260         {
261                 dstream<<__FUNCTION_NAME<<": serialization error: "
262                                 <<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl;
263                 return NULL;
264         }
265 }
266
267
268 /*
269         RatSAO
270 */
271
272 // Prototype
273 RatSAO proto_RatSAO(NULL, 0, v3f(0,0,0));
274
275 RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos):
276         ServerActiveObject(env, id, pos),
277         m_is_active(false),
278         m_speed_f(0,0,0)
279 {
280         ServerActiveObject::registerType(getType(), create);
281
282         m_oldpos = v3f(0,0,0);
283         m_last_sent_position = v3f(0,0,0);
284         m_yaw = 0;
285         m_counter1 = 0;
286         m_counter2 = 0;
287         m_age = 0;
288         m_touching_ground = false;
289 }
290
291 ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
292                 const std::string &data)
293 {
294         std::istringstream is(data, std::ios::binary);
295         char buf[1];
296         // read version
297         is.read(buf, 1);
298         u8 version = buf[0];
299         // check if version is supported
300         if(version != 0)
301                 return NULL;
302         return new RatSAO(env, id, pos);
303 }
304
305 void RatSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
306                 bool send_recommended)
307 {
308         assert(m_env);
309
310         if(m_is_active == false)
311         {
312                 if(m_inactive_interval.step(dtime, 0.5)==false)
313                         return;
314         }
315
316         /*
317                 The AI
318         */
319
320         /*m_age += dtime;
321         if(m_age > 60)
322         {
323                 // Die
324                 m_removed = true;
325                 return;
326         }*/
327
328         // Apply gravity
329         m_speed_f.Y -= dtime*9.81*BS;
330
331         /*
332                 Move around if some player is close
333         */
334         bool player_is_close = false;
335         // Check connected players
336         core::list<Player*> players = m_env->getPlayers(true);
337         core::list<Player*>::Iterator i;
338         for(i = players.begin();
339                         i != players.end(); i++)
340         {
341                 Player *player = *i;
342                 v3f playerpos = player->getPosition();
343                 if(m_base_position.getDistanceFrom(playerpos) < BS*10.0)
344                 {
345                         player_is_close = true;
346                         break;
347                 }
348         }
349
350         m_is_active = player_is_close;
351         
352         if(player_is_close == false)
353         {
354                 m_speed_f.X = 0;
355                 m_speed_f.Z = 0;
356         }
357         else
358         {
359                 // Move around
360                 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
361                 f32 speed = 2*BS;
362                 m_speed_f.X = speed * dir.X;
363                 m_speed_f.Z = speed * dir.Z;
364
365                 if(m_touching_ground && (m_oldpos - m_base_position).getLength()
366                                 < dtime*speed/2)
367                 {
368                         m_counter1 -= dtime;
369                         if(m_counter1 < 0.0)
370                         {
371                                 m_counter1 += 1.0;
372                                 m_speed_f.Y = 5.0*BS;
373                         }
374                 }
375
376                 {
377                         m_counter2 -= dtime;
378                         if(m_counter2 < 0.0)
379                         {
380                                 m_counter2 += (float)(myrand()%100)/100*3.0;
381                                 m_yaw += ((float)(myrand()%200)-100)/100*180;
382                                 m_yaw = wrapDegrees(m_yaw);
383                         }
384                 }
385         }
386         
387         m_oldpos = m_base_position;
388
389         /*
390                 Move it, with collision detection
391         */
392
393         core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
394         collisionMoveResult moveresult;
395         // Maximum movement without glitches
396         f32 pos_max_d = BS*0.25;
397         // Limit speed
398         if(m_speed_f.getLength()*dtime > pos_max_d)
399                 m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
400         v3f pos_f = getBasePosition();
401         v3f pos_f_old = pos_f;
402         moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
403                         box, dtime, pos_f, m_speed_f);
404         m_touching_ground = moveresult.touching_ground;
405         
406         setBasePosition(pos_f);
407
408         if(send_recommended == false)
409                 return;
410
411         if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
412         {
413                 m_last_sent_position = pos_f;
414
415                 std::ostringstream os(std::ios::binary);
416                 // command (0 = update position)
417                 writeU8(os, 0);
418                 // pos
419                 writeV3F1000(os, m_base_position);
420                 // yaw
421                 writeF1000(os, m_yaw);
422                 // create message and add to list
423                 ActiveObjectMessage aom(getId(), false, os.str());
424                 messages.push_back(aom);
425         }
426 }
427
428 std::string RatSAO::getClientInitializationData()
429 {
430         std::ostringstream os(std::ios::binary);
431         // version
432         writeU8(os, 0);
433         // pos
434         writeV3F1000(os, m_base_position);
435         return os.str();
436 }
437
438 std::string RatSAO::getStaticData()
439 {
440         //dstream<<__FUNCTION_NAME<<std::endl;
441         std::ostringstream os(std::ios::binary);
442         // version
443         writeU8(os, 0);
444         return os.str();
445 }
446
447 InventoryItem* RatSAO::createPickedUpItem()
448 {
449         std::istringstream is("CraftItem rat 1", std::ios_base::binary);
450         InventoryItem *item = InventoryItem::deSerialize(is);
451         return item;
452 }
453
454