]> git.lizzy.rs Git - minetest.git/blob - src/content_cao.cpp
b6543061aea6b38c612820d9dd2cffdf8238bbdb
[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         setMeshVerticesColor(m_node->getMesh(), color);
228 }
229
230 v3s16 ItemCAO::getLightPosition()
231 {
232         return floatToInt(m_position, BS);
233 }
234
235 void ItemCAO::updateNodePos()
236 {
237         if(m_node == NULL)
238                 return;
239
240         m_node->setPosition(m_position);
241 }
242
243 void ItemCAO::step(float dtime, ClientEnvironment *env)
244 {
245         if(m_node)
246         {
247                 /*v3f rot = m_node->getRotation();
248                 rot.Y += dtime * 120;
249                 m_node->setRotation(rot);*/
250                 LocalPlayer *player = env->getLocalPlayer();
251                 assert(player);
252                 v3f rot = m_node->getRotation();
253                 rot.Y = 180.0 - (player->getYaw());
254                 m_node->setRotation(rot);
255         }
256 }
257
258 void ItemCAO::processMessage(const std::string &data)
259 {
260         dstream<<"ItemCAO: Got message"<<std::endl;
261         std::istringstream is(data, std::ios::binary);
262         // command
263         u8 cmd = readU8(is);
264         if(cmd == 0)
265         {
266                 // pos
267                 m_position = readV3F1000(is);
268                 updateNodePos();
269         }
270 }
271
272 void ItemCAO::initialize(const std::string &data)
273 {
274         dstream<<"ItemCAO: Got init data"<<std::endl;
275         
276         {
277                 std::istringstream is(data, std::ios::binary);
278                 // version
279                 u8 version = readU8(is);
280                 // check version
281                 if(version != 0)
282                         return;
283                 // pos
284                 m_position = readV3F1000(is);
285                 // inventorystring
286                 m_inventorystring = deSerializeString(is);
287         }
288         
289         updateNodePos();
290
291         /*
292                 Update image of node
293         */
294
295         if(m_node == NULL)
296                 return;
297
298         scene::IMesh *mesh = m_node->getMesh();
299
300         if(mesh == NULL)
301                 return;
302         
303         scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
304
305         if(buf == NULL)
306                 return;
307
308         // Create an inventory item to see what is its image
309         std::istringstream is(m_inventorystring, std::ios_base::binary);
310         video::ITexture *texture = NULL;
311         try{
312                 InventoryItem *item = NULL;
313                 item = InventoryItem::deSerialize(is);
314                 dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
315                                 <<m_inventorystring<<"\" -> item="<<item
316                                 <<std::endl;
317                 if(item)
318                 {
319                         texture = item->getImage();
320                         delete item;
321                 }
322         }
323         catch(SerializationError &e)
324         {
325                 dstream<<"WARNING: "<<__FUNCTION_NAME
326                                 <<": error deSerializing inventorystring \""
327                                 <<m_inventorystring<<"\""<<std::endl;
328         }
329         
330         // Set meshbuffer texture
331         buf->getMaterial().setTexture(0, texture);
332         
333 }
334
335 /*
336         RatCAO
337 */
338
339 #include "inventory.h"
340
341 // Prototype
342 RatCAO proto_RatCAO;
343
344 RatCAO::RatCAO():
345         ClientActiveObject(0),
346         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
347         m_node(NULL),
348         m_position(v3f(0,10*BS,0)),
349         m_yaw(0)
350 {
351         ClientActiveObject::registerType(getType(), create);
352 }
353
354 RatCAO::~RatCAO()
355 {
356 }
357
358 ClientActiveObject* RatCAO::create()
359 {
360         return new RatCAO();
361 }
362
363 void RatCAO::addToScene(scene::ISceneManager *smgr)
364 {
365         if(m_node != NULL)
366                 return;
367         
368         video::IVideoDriver* driver = smgr->getVideoDriver();
369         
370         scene::SMesh *mesh = new scene::SMesh();
371         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
372         video::SColor c(255,255,255,255);
373         video::S3DVertex vertices[4] =
374         {
375                 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
376                 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
377                 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
378                 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
379         };
380         u16 indices[] = {0,1,2,2,3,0};
381         buf->append(vertices, 4, indices, 6);
382         // Set material
383         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
384         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
385         //buf->getMaterial().setTexture(0, NULL);
386         buf->getMaterial().setTexture
387                         (0, driver->getTexture(getTexturePath("rat.png").c_str()));
388         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
389         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
390         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
391         // Add to mesh
392         mesh->addMeshBuffer(buf);
393         buf->drop();
394         m_node = smgr->addMeshSceneNode(mesh, NULL);
395         mesh->drop();
396         // Set it to use the materials of the meshbuffers directly.
397         // This is needed for changing the texture in the future
398         m_node->setReadOnlyMaterials(true);
399         updateNodePos();
400 }
401
402 void RatCAO::removeFromScene()
403 {
404         if(m_node == NULL)
405                 return;
406
407         m_node->remove();
408         m_node = NULL;
409 }
410
411 void RatCAO::updateLight(u8 light_at_pos)
412 {
413         if(m_node == NULL)
414                 return;
415
416         u8 li = decode_light(light_at_pos);
417         video::SColor color(255,li,li,li);
418         setMeshVerticesColor(m_node->getMesh(), color);
419 }
420
421 v3s16 RatCAO::getLightPosition()
422 {
423         return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
424 }
425
426 void RatCAO::updateNodePos()
427 {
428         if(m_node == NULL)
429                 return;
430
431         //m_node->setPosition(m_position);
432         m_node->setPosition(pos_translator.vect_show);
433
434         v3f rot = m_node->getRotation();
435         rot.Y = 180.0 - m_yaw;
436         m_node->setRotation(rot);
437 }
438
439 void RatCAO::step(float dtime, ClientEnvironment *env)
440 {
441         pos_translator.translate(dtime);
442         updateNodePos();
443 }
444
445 void RatCAO::processMessage(const std::string &data)
446 {
447         //dstream<<"RatCAO: Got message"<<std::endl;
448         std::istringstream is(data, std::ios::binary);
449         // command
450         u8 cmd = readU8(is);
451         if(cmd == 0)
452         {
453                 // pos
454                 m_position = readV3F1000(is);
455                 pos_translator.update(m_position);
456                 // yaw
457                 m_yaw = readF1000(is);
458                 updateNodePos();
459         }
460 }
461
462 void RatCAO::initialize(const std::string &data)
463 {
464         //dstream<<"RatCAO: Got init data"<<std::endl;
465         
466         {
467                 std::istringstream is(data, std::ios::binary);
468                 // version
469                 u8 version = readU8(is);
470                 // check version
471                 if(version != 0)
472                         return;
473                 // pos
474                 m_position = readV3F1000(is);
475                 pos_translator.init(m_position);
476         }
477         
478         updateNodePos();
479 }
480
481 /*
482         Oerkki1CAO
483 */
484
485 #include "inventory.h"
486
487 // Prototype
488 Oerkki1CAO proto_Oerkki1CAO;
489
490 Oerkki1CAO::Oerkki1CAO():
491         ClientActiveObject(0),
492         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
493         m_node(NULL),
494         m_position(v3f(0,10*BS,0)),
495         m_yaw(0),
496         m_damage_visual_timer(0),
497         m_damage_texture_enabled(false)
498 {
499         ClientActiveObject::registerType(getType(), create);
500 }
501
502 Oerkki1CAO::~Oerkki1CAO()
503 {
504 }
505
506 ClientActiveObject* Oerkki1CAO::create()
507 {
508         return new Oerkki1CAO();
509 }
510
511 void Oerkki1CAO::addToScene(scene::ISceneManager *smgr)
512 {
513         if(m_node != NULL)
514                 return;
515         
516         video::IVideoDriver* driver = smgr->getVideoDriver();
517         
518         scene::SMesh *mesh = new scene::SMesh();
519         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
520         video::SColor c(255,255,255,255);
521         video::S3DVertex vertices[4] =
522         {
523                 video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
524                 video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
525                 video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
526                 video::S3DVertex(-BS/2-BS,BS*2,0, 0,0,0, c, 0,0),
527         };
528         u16 indices[] = {0,1,2,2,3,0};
529         buf->append(vertices, 4, indices, 6);
530         // Set material
531         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
532         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
533         //buf->getMaterial().setTexture(0, NULL);
534         buf->getMaterial().setTexture
535                         (0, driver->getTexture(getTexturePath("oerkki1.png").c_str()));
536         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
537         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
538         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
539         // Add to mesh
540         mesh->addMeshBuffer(buf);
541         buf->drop();
542         m_node = smgr->addMeshSceneNode(mesh, NULL);
543         mesh->drop();
544         // Set it to use the materials of the meshbuffers directly.
545         // This is needed for changing the texture in the future
546         m_node->setReadOnlyMaterials(true);
547         updateNodePos();
548 }
549
550 void Oerkki1CAO::removeFromScene()
551 {
552         if(m_node == NULL)
553                 return;
554
555         m_node->remove();
556         m_node = NULL;
557 }
558
559 void Oerkki1CAO::updateLight(u8 light_at_pos)
560 {
561         if(m_node == NULL)
562                 return;
563         
564         if(light_at_pos <= 2)
565         {
566                 m_node->setVisible(false);
567                 return;
568         }
569
570         m_node->setVisible(true);
571
572         u8 li = decode_light(light_at_pos);
573         video::SColor color(255,li,li,li);
574         setMeshVerticesColor(m_node->getMesh(), color);
575 }
576
577 v3s16 Oerkki1CAO::getLightPosition()
578 {
579         return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
580 }
581
582 void Oerkki1CAO::updateNodePos()
583 {
584         if(m_node == NULL)
585                 return;
586
587         //m_node->setPosition(m_position);
588         m_node->setPosition(pos_translator.vect_show);
589
590         v3f rot = m_node->getRotation();
591         rot.Y = 180.0 - m_yaw + 90.0;
592         m_node->setRotation(rot);
593 }
594
595 void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
596 {
597         pos_translator.translate(dtime);
598         updateNodePos();
599
600         LocalPlayer *player = env->getLocalPlayer();
601         assert(player);
602         
603         v3f playerpos = player->getPosition();
604         v2f playerpos_2d(playerpos.X,playerpos.Z);
605         v2f objectpos_2d(m_position.X,m_position.Z);
606
607         if(fabs(m_position.Y - playerpos.Y) < 3.0*BS &&
608                         objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
609         {
610                 if(m_attack_interval.step(dtime, 0.5))
611                 {
612                         env->damageLocalPlayer(2);
613                 }
614         }
615
616         if(m_damage_visual_timer > 0)
617         {
618                 if(!m_damage_texture_enabled)
619                 {
620                         // Enable damage texture
621                         if(m_node)
622                         {
623                                 video::IVideoDriver* driver =
624                                         m_node->getSceneManager()->getVideoDriver();
625                                 
626                                 scene::IMesh *mesh = m_node->getMesh();
627                                 if(mesh == NULL)
628                                         return;
629                                 
630                                 u16 mc = mesh->getMeshBufferCount();
631                                 for(u16 j=0; j<mc; j++)
632                                 {
633                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
634                                         buf->getMaterial().setTexture(0, driver->getTexture(
635                                                         getTexturePath("oerkki1_damaged.png").c_str()));
636                                 }
637                         }
638                         m_damage_texture_enabled = true;
639                 }
640                 m_damage_visual_timer -= dtime;
641         }
642         else
643         {
644                 if(m_damage_texture_enabled)
645                 {
646                         // Disable damage texture
647                         if(m_node)
648                         {
649                                 video::IVideoDriver* driver =
650                                         m_node->getSceneManager()->getVideoDriver();
651                                 
652                                 scene::IMesh *mesh = m_node->getMesh();
653                                 if(mesh == NULL)
654                                         return;
655                                 
656                                 u16 mc = mesh->getMeshBufferCount();
657                                 for(u16 j=0; j<mc; j++)
658                                 {
659                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
660                                         buf->getMaterial().setTexture(0, driver->getTexture(
661                                                         getTexturePath("oerkki1.png").c_str()));
662                                 }
663                         }
664                         m_damage_texture_enabled = false;
665                 }
666         }
667 }
668
669 void Oerkki1CAO::processMessage(const std::string &data)
670 {
671         //dstream<<"Oerkki1CAO: Got message"<<std::endl;
672         std::istringstream is(data, std::ios::binary);
673         // command
674         u8 cmd = readU8(is);
675         if(cmd == 0)
676         {
677                 // pos
678                 m_position = readV3F1000(is);
679                 pos_translator.update(m_position);
680                 // yaw
681                 m_yaw = readF1000(is);
682                 updateNodePos();
683         }
684         else if(cmd == 1)
685         {
686                 u16 damage = readU8(is);
687                 m_damage_visual_timer = 1.0;
688         }
689 }
690
691 void Oerkki1CAO::initialize(const std::string &data)
692 {
693         //dstream<<"Oerkki1CAO: Got init data"<<std::endl;
694         
695         {
696                 std::istringstream is(data, std::ios::binary);
697                 // version
698                 u8 version = readU8(is);
699                 // check version
700                 if(version != 0)
701                         return;
702                 // pos
703                 m_position = readV3F1000(is);
704                 pos_translator.init(m_position);
705         }
706         
707         updateNodePos();
708 }
709
710 /*
711         FireflyCAO
712 */
713
714 // Prototype
715 FireflyCAO proto_FireflyCAO;
716
717 FireflyCAO::FireflyCAO():
718         ClientActiveObject(0),
719         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
720         m_node(NULL),
721         m_position(v3f(0,10*BS,0)),
722         m_yaw(0)
723 {
724         ClientActiveObject::registerType(getType(), create);
725 }
726
727 FireflyCAO::~FireflyCAO()
728 {
729 }
730
731 ClientActiveObject* FireflyCAO::create()
732 {
733         return new FireflyCAO();
734 }
735
736 void FireflyCAO::addToScene(scene::ISceneManager *smgr)
737 {
738         if(m_node != NULL)
739                 return;
740         
741         video::IVideoDriver* driver = smgr->getVideoDriver();
742         
743         scene::SMesh *mesh = new scene::SMesh();
744         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
745         video::SColor c(255,255,255,255);
746         video::S3DVertex vertices[4] =
747         {
748                 video::S3DVertex(0,0,0, 0,0,0, c, 0,1),
749                 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
750                 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
751                 video::S3DVertex(0,BS/2,0, 0,0,0, c, 0,0),
752         };
753         u16 indices[] = {0,1,2,2,3,0};
754         buf->append(vertices, 4, indices, 6);
755         // Set material
756         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
757         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
758         //buf->getMaterial().setTexture(0, NULL);
759         buf->getMaterial().setTexture
760                         (0, driver->getTexture(getTexturePath("firefly.png").c_str()));
761         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
762         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
763         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
764         // Add to mesh
765         mesh->addMeshBuffer(buf);
766         buf->drop();
767         m_node = smgr->addMeshSceneNode(mesh, NULL);
768         mesh->drop();
769         // Set it to use the materials of the meshbuffers directly.
770         // This is needed for changing the texture in the future
771         m_node->setReadOnlyMaterials(true);
772         updateNodePos();
773 }
774
775 void FireflyCAO::removeFromScene()
776 {
777         if(m_node == NULL)
778                 return;
779
780         m_node->remove();
781         m_node = NULL;
782 }
783
784 void FireflyCAO::updateLight(u8 light_at_pos)
785 {
786         if(m_node == NULL)
787                 return;
788
789         u8 li = 255;
790         video::SColor color(255,li,li,li);
791         setMeshVerticesColor(m_node->getMesh(), color);
792 }
793
794 v3s16 FireflyCAO::getLightPosition()
795 {
796         return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
797 }
798
799 void FireflyCAO::updateNodePos()
800 {
801         if(m_node == NULL)
802                 return;
803
804         //m_node->setPosition(m_position);
805         m_node->setPosition(pos_translator.vect_show);
806
807         v3f rot = m_node->getRotation();
808         rot.Y = 180.0 - m_yaw;
809         m_node->setRotation(rot);
810 }
811
812 void FireflyCAO::step(float dtime, ClientEnvironment *env)
813 {
814         pos_translator.translate(dtime);
815         updateNodePos();
816 }
817
818 void FireflyCAO::processMessage(const std::string &data)
819 {
820         //dstream<<"FireflyCAO: Got message"<<std::endl;
821         std::istringstream is(data, std::ios::binary);
822         // command
823         u8 cmd = readU8(is);
824         if(cmd == 0)
825         {
826                 // pos
827                 m_position = readV3F1000(is);
828                 pos_translator.update(m_position);
829                 // yaw
830                 m_yaw = readF1000(is);
831                 updateNodePos();
832         }
833 }
834
835 void FireflyCAO::initialize(const std::string &data)
836 {
837         //dstream<<"FireflyCAO: Got init data"<<std::endl;
838         
839         {
840                 std::istringstream is(data, std::ios::binary);
841                 // version
842                 u8 version = readU8(is);
843                 // check version
844                 if(version != 0)
845                         return;
846                 // pos
847                 m_position = readV3F1000(is);
848                 pos_translator.init(m_position);
849         }
850         
851         updateNodePos();
852 }