Changed the Heal Amount of Apples from 6 to 2
[oweals/minetest.git] / src / content_cao.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_cao.h"
21 #include "tile.h"
22 #include "environment.h"
23
24 core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
25
26 /*
27         TestCAO
28 */
29
30 // Prototype
31 TestCAO proto_TestCAO;
32
33 TestCAO::TestCAO():
34         ClientActiveObject(0),
35         m_node(NULL),
36         m_position(v3f(0,10*BS,0))
37 {
38         ClientActiveObject::registerType(getType(), create);
39 }
40
41 TestCAO::~TestCAO()
42 {
43 }
44
45 ClientActiveObject* TestCAO::create()
46 {
47         return new TestCAO();
48 }
49
50 void TestCAO::addToScene(scene::ISceneManager *smgr)
51 {
52         if(m_node != NULL)
53                 return;
54         
55         video::IVideoDriver* driver = smgr->getVideoDriver();
56         
57         scene::SMesh *mesh = new scene::SMesh();
58         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
59         video::SColor c(255,255,255,255);
60         video::S3DVertex vertices[4] =
61         {
62                 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
63                 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
64                 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
65                 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
66         };
67         u16 indices[] = {0,1,2,2,3,0};
68         buf->append(vertices, 4, indices, 6);
69         // Set material
70         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
71         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
72         buf->getMaterial().setTexture
73                         (0, driver->getTexture(getTexturePath("rat.png").c_str()));
74         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
75         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
76         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
77         // Add to mesh
78         mesh->addMeshBuffer(buf);
79         buf->drop();
80         m_node = smgr->addMeshSceneNode(mesh, NULL);
81         mesh->drop();
82         updateNodePos();
83 }
84
85 void TestCAO::removeFromScene()
86 {
87         if(m_node == NULL)
88                 return;
89
90         m_node->remove();
91         m_node = NULL;
92 }
93
94 void TestCAO::updateLight(u8 light_at_pos)
95 {
96 }
97
98 v3s16 TestCAO::getLightPosition()
99 {
100         return floatToInt(m_position, BS);
101 }
102
103 void TestCAO::updateNodePos()
104 {
105         if(m_node == NULL)
106                 return;
107
108         m_node->setPosition(m_position);
109         //m_node->setRotation(v3f(0, 45, 0));
110 }
111
112 void TestCAO::step(float dtime, ClientEnvironment *env)
113 {
114         if(m_node)
115         {
116                 v3f rot = m_node->getRotation();
117                 //dstream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
118                 rot.Y += dtime * 180;
119                 m_node->setRotation(rot);
120         }
121 }
122
123 void TestCAO::processMessage(const std::string &data)
124 {
125         dstream<<"TestCAO: Got data: "<<data<<std::endl;
126         std::istringstream is(data, std::ios::binary);
127         u16 cmd;
128         is>>cmd;
129         if(cmd == 0)
130         {
131                 v3f newpos;
132                 is>>newpos.X;
133                 is>>newpos.Y;
134                 is>>newpos.Z;
135                 m_position = newpos;
136                 updateNodePos();
137         }
138 }
139
140 /*
141         ItemCAO
142 */
143
144 #include "inventory.h"
145
146 // Prototype
147 ItemCAO proto_ItemCAO;
148
149 ItemCAO::ItemCAO():
150         ClientActiveObject(0),
151         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
152         m_node(NULL),
153         m_position(v3f(0,10*BS,0))
154 {
155         ClientActiveObject::registerType(getType(), create);
156 }
157
158 ItemCAO::~ItemCAO()
159 {
160 }
161
162 ClientActiveObject* ItemCAO::create()
163 {
164         return new ItemCAO();
165 }
166
167 void ItemCAO::addToScene(scene::ISceneManager *smgr)
168 {
169         if(m_node != NULL)
170                 return;
171         
172         video::IVideoDriver* driver = smgr->getVideoDriver();
173         
174         scene::SMesh *mesh = new scene::SMesh();
175         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
176         video::SColor c(255,255,255,255);
177         video::S3DVertex vertices[4] =
178         {
179                 /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
180                 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
181                 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
182                 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
183                 video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
184                 video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
185                 video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
186                 video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
187         };
188         u16 indices[] = {0,1,2,2,3,0};
189         buf->append(vertices, 4, indices, 6);
190         // Set material
191         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
192         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
193         //buf->getMaterial().setTexture(0, NULL);
194         // Initialize with the stick texture
195         buf->getMaterial().setTexture
196                         (0, driver->getTexture(getTexturePath("stick.png").c_str()));
197         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
198         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
199         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
200         // Add to mesh
201         mesh->addMeshBuffer(buf);
202         buf->drop();
203         m_node = smgr->addMeshSceneNode(mesh, NULL);
204         mesh->drop();
205         // Set it to use the materials of the meshbuffers directly.
206         // This is needed for changing the texture in the future
207         m_node->setReadOnlyMaterials(true);
208         updateNodePos();
209 }
210
211 void ItemCAO::removeFromScene()
212 {
213         if(m_node == NULL)
214                 return;
215
216         m_node->remove();
217         m_node = NULL;
218 }
219
220 void ItemCAO::updateLight(u8 light_at_pos)
221 {
222         if(m_node == NULL)
223                 return;
224
225         u8 li = decode_light(light_at_pos);
226         video::SColor color(255,li,li,li);
227
228         scene::IMesh *mesh = m_node->getMesh();
229         if(mesh == NULL)
230                 return;
231         
232         u16 mc = mesh->getMeshBufferCount();
233         for(u16 j=0; j<mc; j++)
234         {
235                 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
236                 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
237                 u16 vc = buf->getVertexCount();
238                 for(u16 i=0; i<vc; i++)
239                 {
240                         vertices[i].Color = color;
241                 }
242         }
243 }
244
245 v3s16 ItemCAO::getLightPosition()
246 {
247         return floatToInt(m_position, BS);
248 }
249
250 void ItemCAO::updateNodePos()
251 {
252         if(m_node == NULL)
253                 return;
254
255         m_node->setPosition(m_position);
256 }
257
258 void ItemCAO::step(float dtime, ClientEnvironment *env)
259 {
260         if(m_node)
261         {
262                 /*v3f rot = m_node->getRotation();
263                 rot.Y += dtime * 120;
264                 m_node->setRotation(rot);*/
265                 LocalPlayer *player = env->getLocalPlayer();
266                 assert(player);
267                 v3f rot = m_node->getRotation();
268                 rot.Y = 180.0 - (player->getYaw());
269                 m_node->setRotation(rot);
270         }
271 }
272
273 void ItemCAO::processMessage(const std::string &data)
274 {
275         dstream<<"ItemCAO: Got message"<<std::endl;
276         std::istringstream is(data, std::ios::binary);
277         // command
278         u8 cmd = readU8(is);
279         if(cmd == 0)
280         {
281                 // pos
282                 m_position = readV3F1000(is);
283                 updateNodePos();
284         }
285 }
286
287 void ItemCAO::initialize(const std::string &data)
288 {
289         dstream<<"ItemCAO: Got init data"<<std::endl;
290         
291         {
292                 std::istringstream is(data, std::ios::binary);
293                 // version
294                 u8 version = readU8(is);
295                 // check version
296                 if(version != 0)
297                         return;
298                 // pos
299                 m_position = readV3F1000(is);
300                 // inventorystring
301                 m_inventorystring = deSerializeString(is);
302         }
303         
304         updateNodePos();
305
306         /*
307                 Update image of node
308         */
309
310         if(m_node == NULL)
311                 return;
312
313         scene::IMesh *mesh = m_node->getMesh();
314
315         if(mesh == NULL)
316                 return;
317         
318         scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
319
320         if(buf == NULL)
321                 return;
322
323         // Create an inventory item to see what is its image
324         std::istringstream is(m_inventorystring, std::ios_base::binary);
325         video::ITexture *texture = NULL;
326         try{
327                 InventoryItem *item = NULL;
328                 item = InventoryItem::deSerialize(is);
329                 dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
330                                 <<m_inventorystring<<"\" -> item="<<item
331                                 <<std::endl;
332                 if(item)
333                 {
334                         texture = item->getImage();
335                         delete item;
336                 }
337         }
338         catch(SerializationError &e)
339         {
340                 dstream<<"WARNING: "<<__FUNCTION_NAME
341                                 <<": error deSerializing inventorystring \""
342                                 <<m_inventorystring<<"\""<<std::endl;
343         }
344         
345         // Set meshbuffer texture
346         buf->getMaterial().setTexture(0, texture);
347         
348 }
349
350 /*
351         RatCAO
352 */
353
354 #include "inventory.h"
355
356 // Prototype
357 RatCAO proto_RatCAO;
358
359 RatCAO::RatCAO():
360         ClientActiveObject(0),
361         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
362         m_node(NULL),
363         m_position(v3f(0,10*BS,0)),
364         m_yaw(0)
365 {
366         ClientActiveObject::registerType(getType(), create);
367 }
368
369 RatCAO::~RatCAO()
370 {
371 }
372
373 ClientActiveObject* RatCAO::create()
374 {
375         return new RatCAO();
376 }
377
378 void RatCAO::addToScene(scene::ISceneManager *smgr)
379 {
380         if(m_node != NULL)
381                 return;
382         
383         video::IVideoDriver* driver = smgr->getVideoDriver();
384         
385         scene::SMesh *mesh = new scene::SMesh();
386         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
387         video::SColor c(255,255,255,255);
388         video::S3DVertex vertices[4] =
389         {
390                 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
391                 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
392                 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
393                 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
394         };
395         u16 indices[] = {0,1,2,2,3,0};
396         buf->append(vertices, 4, indices, 6);
397         // Set material
398         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
399         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
400         //buf->getMaterial().setTexture(0, NULL);
401         buf->getMaterial().setTexture
402                         (0, driver->getTexture(getTexturePath("rat.png").c_str()));
403         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
404         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
405         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
406         // Add to mesh
407         mesh->addMeshBuffer(buf);
408         buf->drop();
409         m_node = smgr->addMeshSceneNode(mesh, NULL);
410         mesh->drop();
411         // Set it to use the materials of the meshbuffers directly.
412         // This is needed for changing the texture in the future
413         m_node->setReadOnlyMaterials(true);
414         updateNodePos();
415 }
416
417 void RatCAO::removeFromScene()
418 {
419         if(m_node == NULL)
420                 return;
421
422         m_node->remove();
423         m_node = NULL;
424 }
425
426 void RatCAO::updateLight(u8 light_at_pos)
427 {
428         if(m_node == NULL)
429                 return;
430
431         u8 li = decode_light(light_at_pos);
432         video::SColor color(255,li,li,li);
433
434         scene::IMesh *mesh = m_node->getMesh();
435         if(mesh == NULL)
436                 return;
437         
438         u16 mc = mesh->getMeshBufferCount();
439         for(u16 j=0; j<mc; j++)
440         {
441                 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
442                 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
443                 u16 vc = buf->getVertexCount();
444                 for(u16 i=0; i<vc; i++)
445                 {
446                         vertices[i].Color = color;
447                 }
448         }
449 }
450
451 v3s16 RatCAO::getLightPosition()
452 {
453         return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
454 }
455
456 void RatCAO::updateNodePos()
457 {
458         if(m_node == NULL)
459                 return;
460
461         //m_node->setPosition(m_position);
462         m_node->setPosition(pos_translator.vect_show);
463
464         v3f rot = m_node->getRotation();
465         rot.Y = 180.0 - m_yaw;
466         m_node->setRotation(rot);
467 }
468
469 void RatCAO::step(float dtime, ClientEnvironment *env)
470 {
471         pos_translator.translate(dtime);
472         updateNodePos();
473 }
474
475 void RatCAO::processMessage(const std::string &data)
476 {
477         //dstream<<"RatCAO: Got message"<<std::endl;
478         std::istringstream is(data, std::ios::binary);
479         // command
480         u8 cmd = readU8(is);
481         if(cmd == 0)
482         {
483                 // pos
484                 m_position = readV3F1000(is);
485                 pos_translator.update(m_position);
486                 // yaw
487                 m_yaw = readF1000(is);
488                 updateNodePos();
489         }
490 }
491
492 void RatCAO::initialize(const std::string &data)
493 {
494         //dstream<<"RatCAO: Got init data"<<std::endl;
495         
496         {
497                 std::istringstream is(data, std::ios::binary);
498                 // version
499                 u8 version = readU8(is);
500                 // check version
501                 if(version != 0)
502                         return;
503                 // pos
504                 m_position = readV3F1000(is);
505                 pos_translator.init(m_position);
506         }
507         
508         updateNodePos();
509 }
510
511 /*
512         Oerkki1CAO
513 */
514
515 #include "inventory.h"
516
517 // Prototype
518 Oerkki1CAO proto_Oerkki1CAO;
519
520 Oerkki1CAO::Oerkki1CAO():
521         ClientActiveObject(0),
522         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
523         m_node(NULL),
524         m_position(v3f(0,10*BS,0)),
525         m_yaw(0),
526         m_damage_visual_timer(0),
527         m_damage_texture_enabled(false)
528 {
529         ClientActiveObject::registerType(getType(), create);
530 }
531
532 Oerkki1CAO::~Oerkki1CAO()
533 {
534 }
535
536 ClientActiveObject* Oerkki1CAO::create()
537 {
538         return new Oerkki1CAO();
539 }
540
541 void Oerkki1CAO::addToScene(scene::ISceneManager *smgr)
542 {
543         if(m_node != NULL)
544                 return;
545         
546         video::IVideoDriver* driver = smgr->getVideoDriver();
547         
548         scene::SMesh *mesh = new scene::SMesh();
549         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
550         video::SColor c(255,255,255,255);
551         video::S3DVertex vertices[4] =
552         {
553                 video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
554                 video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
555                 video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
556                 video::S3DVertex(-BS/2-BS,BS*2,0, 0,0,0, c, 0,0),
557         };
558         u16 indices[] = {0,1,2,2,3,0};
559         buf->append(vertices, 4, indices, 6);
560         // Set material
561         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
562         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
563         //buf->getMaterial().setTexture(0, NULL);
564         buf->getMaterial().setTexture
565                         (0, driver->getTexture(getTexturePath("oerkki1.png").c_str()));
566         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
567         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
568         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
569         // Add to mesh
570         mesh->addMeshBuffer(buf);
571         buf->drop();
572         m_node = smgr->addMeshSceneNode(mesh, NULL);
573         mesh->drop();
574         // Set it to use the materials of the meshbuffers directly.
575         // This is needed for changing the texture in the future
576         m_node->setReadOnlyMaterials(true);
577         updateNodePos();
578 }
579
580 void Oerkki1CAO::removeFromScene()
581 {
582         if(m_node == NULL)
583                 return;
584
585         m_node->remove();
586         m_node = NULL;
587 }
588
589 void Oerkki1CAO::updateLight(u8 light_at_pos)
590 {
591         if(m_node == NULL)
592                 return;
593         
594         if(light_at_pos <= 2)
595         {
596                 m_node->setVisible(false);
597                 return;
598         }
599
600         m_node->setVisible(true);
601
602         u8 li = decode_light(light_at_pos);
603         video::SColor color(255,li,li,li);
604
605         scene::IMesh *mesh = m_node->getMesh();
606         if(mesh == NULL)
607                 return;
608         
609         u16 mc = mesh->getMeshBufferCount();
610         for(u16 j=0; j<mc; j++)
611         {
612                 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
613                 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
614                 u16 vc = buf->getVertexCount();
615                 for(u16 i=0; i<vc; i++)
616                 {
617                         vertices[i].Color = color;
618                 }
619         }
620 }
621
622 v3s16 Oerkki1CAO::getLightPosition()
623 {
624         return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
625 }
626
627 void Oerkki1CAO::updateNodePos()
628 {
629         if(m_node == NULL)
630                 return;
631
632         //m_node->setPosition(m_position);
633         m_node->setPosition(pos_translator.vect_show);
634
635         v3f rot = m_node->getRotation();
636         rot.Y = 180.0 - m_yaw + 90.0;
637         m_node->setRotation(rot);
638 }
639
640 void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
641 {
642         pos_translator.translate(dtime);
643         updateNodePos();
644
645         LocalPlayer *player = env->getLocalPlayer();
646         assert(player);
647         
648         v3f playerpos = player->getPosition();
649         v2f playerpos_2d(playerpos.X,playerpos.Z);
650         v2f objectpos_2d(m_position.X,m_position.Z);
651
652         if(fabs(m_position.Y - playerpos.Y) < 3.0*BS &&
653                         objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
654         {
655                 if(m_attack_interval.step(dtime, 0.5))
656                 {
657                         env->damageLocalPlayer(2);
658                 }
659         }
660
661         if(m_damage_visual_timer > 0)
662         {
663                 if(!m_damage_texture_enabled)
664                 {
665                         // Enable damage texture
666                         if(m_node)
667                         {
668                                 video::IVideoDriver* driver =
669                                         m_node->getSceneManager()->getVideoDriver();
670                                 
671                                 scene::IMesh *mesh = m_node->getMesh();
672                                 if(mesh == NULL)
673                                         return;
674                                 
675                                 u16 mc = mesh->getMeshBufferCount();
676                                 for(u16 j=0; j<mc; j++)
677                                 {
678                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
679                                         buf->getMaterial().setTexture(0, driver->getTexture(
680                                                         getTexturePath("oerkki1_damaged.png").c_str()));
681                                 }
682                         }
683                         m_damage_texture_enabled = true;
684                 }
685                 m_damage_visual_timer -= dtime;
686         }
687         else
688         {
689                 if(m_damage_texture_enabled)
690                 {
691                         // Disable damage texture
692                         if(m_node)
693                         {
694                                 video::IVideoDriver* driver =
695                                         m_node->getSceneManager()->getVideoDriver();
696                                 
697                                 scene::IMesh *mesh = m_node->getMesh();
698                                 if(mesh == NULL)
699                                         return;
700                                 
701                                 u16 mc = mesh->getMeshBufferCount();
702                                 for(u16 j=0; j<mc; j++)
703                                 {
704                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
705                                         buf->getMaterial().setTexture(0, driver->getTexture(
706                                                         getTexturePath("oerkki1.png").c_str()));
707                                 }
708                         }
709                         m_damage_texture_enabled = false;
710                 }
711         }
712 }
713
714 void Oerkki1CAO::processMessage(const std::string &data)
715 {
716         //dstream<<"Oerkki1CAO: Got message"<<std::endl;
717         std::istringstream is(data, std::ios::binary);
718         // command
719         u8 cmd = readU8(is);
720         if(cmd == 0)
721         {
722                 // pos
723                 m_position = readV3F1000(is);
724                 pos_translator.update(m_position);
725                 // yaw
726                 m_yaw = readF1000(is);
727                 updateNodePos();
728         }
729         else if(cmd == 1)
730         {
731                 u16 damage = readU8(is);
732                 m_damage_visual_timer = 1.0;
733         }
734 }
735
736 void Oerkki1CAO::initialize(const std::string &data)
737 {
738         //dstream<<"Oerkki1CAO: Got init data"<<std::endl;
739         
740         {
741                 std::istringstream is(data, std::ios::binary);
742                 // version
743                 u8 version = readU8(is);
744                 // check version
745                 if(version != 0)
746                         return;
747                 // pos
748                 m_position = readV3F1000(is);
749                 pos_translator.init(m_position);
750         }
751         
752         updateNodePos();
753 }
754
755 /*
756         FireflyCAO
757 */
758
759 // Prototype
760 FireflyCAO proto_FireflyCAO;
761
762 FireflyCAO::FireflyCAO():
763         ClientActiveObject(0),
764         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
765         m_node(NULL),
766         m_position(v3f(0,10*BS,0)),
767         m_yaw(0)
768 {
769         ClientActiveObject::registerType(getType(), create);
770 }
771
772 FireflyCAO::~FireflyCAO()
773 {
774 }
775
776 ClientActiveObject* FireflyCAO::create()
777 {
778         return new FireflyCAO();
779 }
780
781 void FireflyCAO::addToScene(scene::ISceneManager *smgr)
782 {
783         if(m_node != NULL)
784                 return;
785         
786         video::IVideoDriver* driver = smgr->getVideoDriver();
787         
788         scene::SMesh *mesh = new scene::SMesh();
789         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
790         video::SColor c(255,255,255,255);
791         video::S3DVertex vertices[4] =
792         {
793                 video::S3DVertex(0,0,0, 0,0,0, c, 0,1),
794                 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
795                 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
796                 video::S3DVertex(0,BS/2,0, 0,0,0, c, 0,0),
797         };
798         u16 indices[] = {0,1,2,2,3,0};
799         buf->append(vertices, 4, indices, 6);
800         // Set material
801         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
802         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
803         //buf->getMaterial().setTexture(0, NULL);
804         buf->getMaterial().setTexture
805                         (0, driver->getTexture(getTexturePath("firefly.png").c_str()));
806         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
807         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
808         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
809         // Add to mesh
810         mesh->addMeshBuffer(buf);
811         buf->drop();
812         m_node = smgr->addMeshSceneNode(mesh, NULL);
813         mesh->drop();
814         // Set it to use the materials of the meshbuffers directly.
815         // This is needed for changing the texture in the future
816         m_node->setReadOnlyMaterials(true);
817         updateNodePos();
818 }
819
820 void FireflyCAO::removeFromScene()
821 {
822         if(m_node == NULL)
823                 return;
824
825         m_node->remove();
826         m_node = NULL;
827 }
828
829 void FireflyCAO::updateLight(u8 light_at_pos)
830 {
831         if(m_node == NULL)
832                 return;
833
834         u8 li = 255;
835         video::SColor color(255,li,li,li);
836
837         scene::IMesh *mesh = m_node->getMesh();
838         if(mesh == NULL)
839                 return;
840         
841         u16 mc = mesh->getMeshBufferCount();
842         for(u16 j=0; j<mc; j++)
843         {
844                 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
845                 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
846                 u16 vc = buf->getVertexCount();
847                 for(u16 i=0; i<vc; i++)
848                 {
849                         vertices[i].Color = color;
850                 }
851         }
852 }
853
854 v3s16 FireflyCAO::getLightPosition()
855 {
856         return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
857 }
858
859 void FireflyCAO::updateNodePos()
860 {
861         if(m_node == NULL)
862                 return;
863
864         //m_node->setPosition(m_position);
865         m_node->setPosition(pos_translator.vect_show);
866
867         v3f rot = m_node->getRotation();
868         rot.Y = 180.0 - m_yaw;
869         m_node->setRotation(rot);
870 }
871
872 void FireflyCAO::step(float dtime, ClientEnvironment *env)
873 {
874         pos_translator.translate(dtime);
875         updateNodePos();
876 }
877
878 void FireflyCAO::processMessage(const std::string &data)
879 {
880         //dstream<<"FireflyCAO: Got message"<<std::endl;
881         std::istringstream is(data, std::ios::binary);
882         // command
883         u8 cmd = readU8(is);
884         if(cmd == 0)
885         {
886                 // pos
887                 m_position = readV3F1000(is);
888                 pos_translator.update(m_position);
889                 // yaw
890                 m_yaw = readF1000(is);
891                 updateNodePos();
892         }
893 }
894
895 void FireflyCAO::initialize(const std::string &data)
896 {
897         //dstream<<"FireflyCAO: Got init data"<<std::endl;
898         
899         {
900                 std::istringstream is(data, std::ios::binary);
901                 // version
902                 u8 version = readU8(is);
903                 // check version
904                 if(version != 0)
905                         return;
906                 // pos
907                 m_position = readV3F1000(is);
908                 pos_translator.init(m_position);
909         }
910         
911         updateNodePos();
912 }