]> git.lizzy.rs Git - minetest-m13.git/blob - src/content_cao.cpp
Update to 4.6 base
[minetest-m13.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 #include "collision.h"
24 #include "settings.h"
25 #include <ICameraSceneNode.h>
26 #include <ITextSceneNode.h>
27 #include <IBillboardSceneNode.h>
28 #include "serialization.h" // For decompressZlib
29 #include "gamedef.h"
30 #include "clientobject.h"
31 #include "content_object.h"
32 #include "mesh.h"
33 #include "utility.h" // For IntervalLimiter
34 class Settings;
35
36 core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
37
38 /*
39         SmoothTranslator
40 */
41
42 struct SmoothTranslator
43 {
44         v3f vect_old;
45         v3f vect_show;
46         v3f vect_aim;
47         f32 anim_counter;
48         f32 anim_time;
49         f32 anim_time_counter;
50         bool aim_is_end;
51
52         SmoothTranslator():
53                 vect_old(0,0,0),
54                 vect_show(0,0,0),
55                 vect_aim(0,0,0),
56                 anim_counter(0),
57                 anim_time(0),
58                 anim_time_counter(0),
59                 aim_is_end(true)
60         {}
61
62         void init(v3f vect)
63         {
64                 vect_old = vect;
65                 vect_show = vect;
66                 vect_aim = vect;
67                 anim_counter = 0;
68                 anim_time = 0;
69                 anim_time_counter = 0;
70                 aim_is_end = true;
71         }
72
73         void sharpen()
74         {
75                 init(vect_show);
76         }
77
78         void update(v3f vect_new, bool is_end_position=false, float update_interval=-1)
79         {
80                 aim_is_end = is_end_position;
81                 vect_old = vect_show;
82                 vect_aim = vect_new;
83                 if(update_interval > 0){
84                         anim_time = update_interval;
85                 } else {
86                         if(anim_time < 0.001 || anim_time > 1.0)
87                                 anim_time = anim_time_counter;
88                         else
89                                 anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
90                 }
91                 anim_time_counter = 0;
92                 anim_counter = 0;
93         }
94
95         void translate(f32 dtime)
96         {
97                 anim_time_counter = anim_time_counter + dtime;
98                 anim_counter = anim_counter + dtime;
99                 v3f vect_move = vect_aim - vect_old;
100                 f32 moveratio = 1.0;
101                 if(anim_time > 0.001)
102                         moveratio = anim_time_counter / anim_time;
103                 // Move a bit less than should, to avoid oscillation
104                 moveratio = moveratio * 0.8;
105                 float move_end = 1.5;
106                 if(aim_is_end)
107                         move_end = 1.0;
108                 if(moveratio > move_end)
109                         moveratio = move_end;
110                 vect_show = vect_old + vect_move * moveratio;
111         }
112
113         bool is_moving()
114         {
115                 return ((anim_time_counter / anim_time) < 1.4);
116         }
117 };
118
119
120 /*
121         TestCAO
122 */
123
124 class TestCAO : public ClientActiveObject
125 {
126 public:
127         TestCAO(IGameDef *gamedef, ClientEnvironment *env);
128         virtual ~TestCAO();
129         
130         u8 getType() const
131         {
132                 return ACTIVEOBJECT_TYPE_TEST;
133         }
134         
135         static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
136
137         void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
138                         IrrlichtDevice *irr);
139         void removeFromScene();
140         void updateLight(u8 light_at_pos);
141         v3s16 getLightPosition();
142         void updateNodePos();
143
144         void step(float dtime, ClientEnvironment *env);
145
146         void processMessage(const std::string &data);
147
148 private:
149         scene::IMeshSceneNode *m_node;
150         v3f m_position;
151 };
152
153 /*
154         ItemCAO
155 */
156
157 class ItemCAO : public ClientActiveObject
158 {
159 public:
160         ItemCAO(IGameDef *gamedef, ClientEnvironment *env);
161         virtual ~ItemCAO();
162         
163         u8 getType() const
164         {
165                 return ACTIVEOBJECT_TYPE_ITEM;
166         }
167         
168         static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
169
170         void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
171                         IrrlichtDevice *irr);
172         void removeFromScene();
173         void updateLight(u8 light_at_pos);
174         v3s16 getLightPosition();
175         void updateNodePos();
176         void updateInfoText();
177         void updateTexture();
178
179         void step(float dtime, ClientEnvironment *env);
180
181         void processMessage(const std::string &data);
182
183         void initialize(const std::string &data);
184         
185         core::aabbox3d<f32>* getSelectionBox()
186                 {return &m_selection_box;}
187         v3f getPosition()
188                 {return m_position;}
189         
190         std::string infoText()
191                 {return m_infotext;}
192
193 private:
194         core::aabbox3d<f32> m_selection_box;
195         scene::IMeshSceneNode *m_node;
196         v3f m_position;
197         std::string m_itemstring;
198         std::string m_infotext;
199 };
200
201 /*
202         RatCAO
203 */
204
205 class RatCAO : public ClientActiveObject
206 {
207 public:
208         RatCAO(IGameDef *gamedef, ClientEnvironment *env);
209         virtual ~RatCAO();
210         
211         u8 getType() const
212         {
213                 return ACTIVEOBJECT_TYPE_RAT;
214         }
215         
216         static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
217
218         void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
219                         IrrlichtDevice *irr);
220         void removeFromScene();
221         void updateLight(u8 light_at_pos);
222         v3s16 getLightPosition();
223         void updateNodePos();
224
225         void step(float dtime, ClientEnvironment *env);
226
227         void processMessage(const std::string &data);
228
229         void initialize(const std::string &data);
230         
231         core::aabbox3d<f32>* getSelectionBox()
232                 {return &m_selection_box;}
233         v3f getPosition()
234                 {return pos_translator.vect_show;}
235                 //{return m_position;}
236
237 private:
238         core::aabbox3d<f32> m_selection_box;
239         scene::IMeshSceneNode *m_node;
240         v3f m_position;
241         float m_yaw;
242         SmoothTranslator pos_translator;
243 };
244
245 /*
246         Oerkki1CAO
247 */
248
249 class Oerkki1CAO : public ClientActiveObject
250 {
251 public:
252         Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env);
253         virtual ~Oerkki1CAO();
254         
255         u8 getType() const
256         {
257                 return ACTIVEOBJECT_TYPE_OERKKI1;
258         }
259         
260         static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
261
262         void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
263                         IrrlichtDevice *irr);
264         void removeFromScene();
265         void updateLight(u8 light_at_pos);
266         v3s16 getLightPosition();
267         void updateNodePos();
268
269         void step(float dtime, ClientEnvironment *env);
270
271         void processMessage(const std::string &data);
272
273         void initialize(const std::string &data);
274         
275         core::aabbox3d<f32>* getSelectionBox()
276                 {return &m_selection_box;}
277         v3f getPosition()
278                 {return pos_translator.vect_show;}
279                 //{return m_position;}
280
281         // If returns true, punch will not be sent to the server
282         bool directReportPunch(const std::string &toolname, v3f dir);
283
284 private:
285         IntervalLimiter m_attack_interval;
286         core::aabbox3d<f32> m_selection_box;
287         scene::IMeshSceneNode *m_node;
288         v3f m_position;
289         float m_yaw;
290         SmoothTranslator pos_translator;
291         float m_damage_visual_timer;
292         bool m_damage_texture_enabled;
293 };
294
295 /*
296         FireflyCAO
297 */
298
299 class FireflyCAO : public ClientActiveObject
300 {
301 public:
302         FireflyCAO(IGameDef *gamedef, ClientEnvironment *env);
303         virtual ~FireflyCAO();
304         
305         u8 getType() const
306         {
307                 return ACTIVEOBJECT_TYPE_FIREFLY;
308         }
309         
310         static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
311
312         void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
313                         IrrlichtDevice *irr);
314         void removeFromScene();
315         void updateLight(u8 light_at_pos);
316         v3s16 getLightPosition();
317         void updateNodePos();
318
319         void step(float dtime, ClientEnvironment *env);
320
321         void processMessage(const std::string &data);
322
323         void initialize(const std::string &data);
324         
325         core::aabbox3d<f32>* getSelectionBox()
326                 {return &m_selection_box;}
327         v3f getPosition()
328                 {return m_position;}
329
330 private:
331         core::aabbox3d<f32> m_selection_box;
332         scene::IMeshSceneNode *m_node;
333         v3f m_position;
334         float m_yaw;
335         SmoothTranslator pos_translator;
336 };
337
338 static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill,
339                 float txs, float tys, int col, int row)
340 {
341         video::SMaterial& material = bill->getMaterial(0);
342         core::matrix4& matrix = material.getTextureMatrix(0);
343         matrix.setTextureTranslate(txs*col, tys*row);
344         matrix.setTextureScale(txs, tys);
345 }
346
347 /*
348         MobV2CAO
349 */
350
351 class MobV2CAO : public ClientActiveObject
352 {
353 public:
354         MobV2CAO(IGameDef *gamedef, ClientEnvironment *env);
355         virtual ~MobV2CAO();
356         
357         u8 getType() const
358         {
359                 return ACTIVEOBJECT_TYPE_MOBV2;
360         }
361         
362         static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
363
364         void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
365                         IrrlichtDevice *irr);
366         void removeFromScene();
367         void updateLight(u8 light_at_pos);
368         v3s16 getLightPosition();
369         void updateNodePos();
370
371         void step(float dtime, ClientEnvironment *env);
372
373         void processMessage(const std::string &data);
374
375         void initialize(const std::string &data);
376         
377         core::aabbox3d<f32>* getSelectionBox()
378                 {return &m_selection_box;}
379         v3f getPosition()
380                 {return pos_translator.vect_show;}
381                 //{return m_position;}
382         bool doShowSelectionBox(){return false;}
383
384         // If returns true, punch will not be sent to the server
385         bool directReportPunch(const std::string &toolname, v3f dir);
386
387 private:
388         void setLooks(const std::string &looks);
389         
390         IntervalLimiter m_attack_interval;
391         core::aabbox3d<f32> m_selection_box;
392         scene::IBillboardSceneNode *m_node;
393         v3f m_position;
394         std::string m_texture_name;
395         float m_yaw;
396         SmoothTranslator pos_translator;
397         bool m_walking;
398         float m_walking_unset_timer;
399         float m_walk_timer;
400         int m_walk_frame;
401         float m_damage_visual_timer;
402         u8 m_last_light;
403         bool m_shooting;
404         float m_shooting_unset_timer;
405         v2f m_sprite_size;
406         float m_sprite_y;
407         bool m_bright_shooting;
408         std::string m_sprite_type;
409         int m_simple_anim_frames;
410         float m_simple_anim_frametime;
411         bool m_lock_full_brightness;
412         int m_player_hit_damage;
413         float m_player_hit_distance;
414         float m_player_hit_interval;
415         float m_player_hit_timer;
416
417         Settings *m_properties;
418 };
419
420 /*
421         TestCAO
422 */
423
424 // Prototype
425 TestCAO proto_TestCAO(NULL, NULL);
426
427 TestCAO::TestCAO(IGameDef *gamedef, ClientEnvironment *env):
428         ClientActiveObject(0, gamedef, env),
429         m_node(NULL),
430         m_position(v3f(0,10*BS,0))
431 {
432         ClientActiveObject::registerType(getType(), create);
433 }
434
435 TestCAO::~TestCAO()
436 {
437 }
438
439 ClientActiveObject* TestCAO::create(IGameDef *gamedef, ClientEnvironment *env)
440 {
441         return new TestCAO(gamedef, env);
442 }
443
444 void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
445                         IrrlichtDevice *irr)
446 {
447         if(m_node != NULL)
448                 return;
449         
450         //video::IVideoDriver* driver = smgr->getVideoDriver();
451         
452         scene::SMesh *mesh = new scene::SMesh();
453         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
454         video::SColor c(255,255,255,255);
455         video::S3DVertex vertices[4] =
456         {
457                 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
458                 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
459                 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
460                 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
461         };
462         u16 indices[] = {0,1,2,2,3,0};
463         buf->append(vertices, 4, indices, 6);
464         // Set material
465         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
466         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
467         buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
468         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
469         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
470         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
471         // Add to mesh
472         mesh->addMeshBuffer(buf);
473         buf->drop();
474         m_node = smgr->addMeshSceneNode(mesh, NULL);
475         mesh->drop();
476         updateNodePos();
477 }
478
479 void TestCAO::removeFromScene()
480 {
481         if(m_node == NULL)
482                 return;
483
484         m_node->remove();
485         m_node = NULL;
486 }
487
488 void TestCAO::updateLight(u8 light_at_pos)
489 {
490 }
491
492 v3s16 TestCAO::getLightPosition()
493 {
494         return floatToInt(m_position, BS);
495 }
496
497 void TestCAO::updateNodePos()
498 {
499         if(m_node == NULL)
500                 return;
501
502         m_node->setPosition(m_position);
503         //m_node->setRotation(v3f(0, 45, 0));
504 }
505
506 void TestCAO::step(float dtime, ClientEnvironment *env)
507 {
508         if(m_node)
509         {
510                 v3f rot = m_node->getRotation();
511                 //infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
512                 rot.Y += dtime * 180;
513                 m_node->setRotation(rot);
514         }
515 }
516
517 void TestCAO::processMessage(const std::string &data)
518 {
519         infostream<<"TestCAO: Got data: "<<data<<std::endl;
520         std::istringstream is(data, std::ios::binary);
521         u16 cmd;
522         is>>cmd;
523         if(cmd == 0)
524         {
525                 v3f newpos;
526                 is>>newpos.X;
527                 is>>newpos.Y;
528                 is>>newpos.Z;
529                 m_position = newpos;
530                 updateNodePos();
531         }
532 }
533
534 /*
535         ItemCAO
536 */
537
538 #include "inventory.h"
539
540 // Prototype
541 ItemCAO proto_ItemCAO(NULL, NULL);
542
543 ItemCAO::ItemCAO(IGameDef *gamedef, ClientEnvironment *env):
544         ClientActiveObject(0, gamedef, env),
545         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
546         m_node(NULL),
547         m_position(v3f(0,10*BS,0))
548 {
549         if(!gamedef && !env)
550         {
551                 ClientActiveObject::registerType(getType(), create);
552         }
553 }
554
555 ItemCAO::~ItemCAO()
556 {
557 }
558
559 ClientActiveObject* ItemCAO::create(IGameDef *gamedef, ClientEnvironment *env)
560 {
561         return new ItemCAO(gamedef, env);
562 }
563
564 void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
565                         IrrlichtDevice *irr)
566 {
567         if(m_node != NULL)
568                 return;
569         
570         //video::IVideoDriver* driver = smgr->getVideoDriver();
571         
572         scene::SMesh *mesh = new scene::SMesh();
573         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
574         video::SColor c(255,255,255,255);
575         video::S3DVertex vertices[4] =
576         {
577                 /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
578                 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
579                 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
580                 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
581                 video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
582                 video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
583                 video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
584                 video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
585         };
586         u16 indices[] = {0,1,2,2,3,0};
587         buf->append(vertices, 4, indices, 6);
588         // Set material
589         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
590         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
591         // Initialize with a generated placeholder texture
592         buf->getMaterial().setTexture(0, tsrc->getTextureRaw(""));
593         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
594         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
595         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
596         // Add to mesh
597         mesh->addMeshBuffer(buf);
598         buf->drop();
599         m_node = smgr->addMeshSceneNode(mesh, NULL);
600         mesh->drop();
601         updateNodePos();
602
603         /*
604                 Update image of node
605         */
606
607         updateTexture();
608 }
609
610 void ItemCAO::removeFromScene()
611 {
612         if(m_node == NULL)
613                 return;
614
615         m_node->remove();
616         m_node = NULL;
617 }
618
619 void ItemCAO::updateLight(u8 light_at_pos)
620 {
621         if(m_node == NULL)
622                 return;
623
624         u8 li = decode_light(light_at_pos);
625         video::SColor color(255,li,li,li);
626         setMeshColor(m_node->getMesh(), color);
627 }
628
629 v3s16 ItemCAO::getLightPosition()
630 {
631         return floatToInt(m_position, BS);
632 }
633
634 void ItemCAO::updateNodePos()
635 {
636         if(m_node == NULL)
637                 return;
638
639         m_node->setPosition(m_position);
640 }
641
642 void ItemCAO::updateInfoText()
643 {
644         try{
645                 IItemDefManager *idef = m_gamedef->idef();
646                 ItemStack item;
647                 item.deSerialize(m_itemstring, idef);
648                 if(item.isKnown(idef))
649                         m_infotext = item.getDefinition(idef).description;
650                 else
651                         m_infotext = "Unknown item: '" + m_itemstring + "'";
652                 if(item.count >= 2)
653                         m_infotext += " (" + itos(item.count) + ")";
654         }
655         catch(SerializationError &e)
656         {
657                 m_infotext = "Unknown item: '" + m_itemstring + "'";
658         }
659 }
660
661 void ItemCAO::updateTexture()
662 {
663         if(m_node == NULL)
664                 return;
665
666         // Create an inventory item to see what is its image
667         std::istringstream is(m_itemstring, std::ios_base::binary);
668         video::ITexture *texture = NULL;
669         try{
670                 IItemDefManager *idef = m_gamedef->idef();
671                 ItemStack item;
672                 item.deSerialize(is, idef);
673                 texture = item.getDefinition(idef).inventory_texture;
674         }
675         catch(SerializationError &e)
676         {
677                 infostream<<"WARNING: "<<__FUNCTION_NAME
678                                 <<": error deSerializing itemstring \""
679                                 <<m_itemstring<<std::endl;
680         }
681         
682         // Set meshbuffer texture
683         m_node->getMaterial(0).setTexture(0, texture);
684 }
685
686
687 void ItemCAO::step(float dtime, ClientEnvironment *env)
688 {
689         if(m_node)
690         {
691                 /*v3f rot = m_node->getRotation();
692                 rot.Y += dtime * 120;
693                 m_node->setRotation(rot);*/
694                 LocalPlayer *player = env->getLocalPlayer();
695                 assert(player);
696                 v3f rot = m_node->getRotation();
697                 rot.Y = 180.0 - (player->getYaw());
698                 m_node->setRotation(rot);
699         }
700 }
701
702 void ItemCAO::processMessage(const std::string &data)
703 {
704         //infostream<<"ItemCAO: Got message"<<std::endl;
705         std::istringstream is(data, std::ios::binary);
706         // command
707         u8 cmd = readU8(is);
708         if(cmd == 0)
709         {
710                 // pos
711                 m_position = readV3F1000(is);
712                 updateNodePos();
713         }
714         if(cmd == 1)
715         {
716                 // itemstring
717                 m_itemstring = deSerializeString(is);
718                 updateInfoText();
719                 updateTexture();
720         }
721 }
722
723 void ItemCAO::initialize(const std::string &data)
724 {
725         infostream<<"ItemCAO: Got init data"<<std::endl;
726         
727         {
728                 std::istringstream is(data, std::ios::binary);
729                 // version
730                 u8 version = readU8(is);
731                 // check version
732                 if(version != 0)
733                         return;
734                 // pos
735                 m_position = readV3F1000(is);
736                 // itemstring
737                 m_itemstring = deSerializeString(is);
738         }
739         
740         updateNodePos();
741         updateInfoText();
742 }
743
744 /*
745         RatCAO
746 */
747
748 #include "inventory.h"
749
750 // Prototype
751 RatCAO proto_RatCAO(NULL, NULL);
752
753 RatCAO::RatCAO(IGameDef *gamedef, ClientEnvironment *env):
754         ClientActiveObject(0, gamedef, env),
755         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
756         m_node(NULL),
757         m_position(v3f(0,10*BS,0)),
758         m_yaw(0)
759 {
760         ClientActiveObject::registerType(getType(), create);
761 }
762
763 RatCAO::~RatCAO()
764 {
765 }
766
767 ClientActiveObject* RatCAO::create(IGameDef *gamedef, ClientEnvironment *env)
768 {
769         return new RatCAO(gamedef, env);
770 }
771
772 void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
773                         IrrlichtDevice *irr)
774 {
775         if(m_node != NULL)
776                 return;
777         
778         //video::IVideoDriver* driver = smgr->getVideoDriver();
779         
780         scene::SMesh *mesh = new scene::SMesh();
781         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
782         video::SColor c(255,255,255,255);
783         video::S3DVertex vertices[4] =
784         {
785                 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
786                 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
787                 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
788                 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
789         };
790         u16 indices[] = {0,1,2,2,3,0};
791         buf->append(vertices, 4, indices, 6);
792         // Set material
793         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
794         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
795         //buf->getMaterial().setTexture(0, NULL);
796         buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
797         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
798         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
799         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
800         // Add to mesh
801         mesh->addMeshBuffer(buf);
802         buf->drop();
803         m_node = smgr->addMeshSceneNode(mesh, NULL);
804         mesh->drop();
805         // Set it to use the materials of the meshbuffers directly.
806         // This is needed for changing the texture in the future
807         m_node->setReadOnlyMaterials(true);
808         updateNodePos();
809 }
810
811 void RatCAO::removeFromScene()
812 {
813         if(m_node == NULL)
814                 return;
815
816         m_node->remove();
817         m_node = NULL;
818 }
819
820 void RatCAO::updateLight(u8 light_at_pos)
821 {
822         if(m_node == NULL)
823                 return;
824
825         u8 li = decode_light(light_at_pos);
826         video::SColor color(255,li,li,li);
827         setMeshColor(m_node->getMesh(), color);
828 }
829
830 v3s16 RatCAO::getLightPosition()
831 {
832         return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
833 }
834
835 void RatCAO::updateNodePos()
836 {
837         if(m_node == NULL)
838                 return;
839
840         //m_node->setPosition(m_position);
841         m_node->setPosition(pos_translator.vect_show);
842
843         v3f rot = m_node->getRotation();
844         rot.Y = 180.0 - m_yaw;
845         m_node->setRotation(rot);
846 }
847
848 void RatCAO::step(float dtime, ClientEnvironment *env)
849 {
850         pos_translator.translate(dtime);
851         updateNodePos();
852 }
853
854 void RatCAO::processMessage(const std::string &data)
855 {
856         //infostream<<"RatCAO: Got message"<<std::endl;
857         std::istringstream is(data, std::ios::binary);
858         // command
859         u8 cmd = readU8(is);
860         if(cmd == 0)
861         {
862                 // pos
863                 m_position = readV3F1000(is);
864                 pos_translator.update(m_position);
865                 // yaw
866                 m_yaw = readF1000(is);
867                 updateNodePos();
868         }
869 }
870
871 void RatCAO::initialize(const std::string &data)
872 {
873         //infostream<<"RatCAO: Got init data"<<std::endl;
874         
875         {
876                 std::istringstream is(data, std::ios::binary);
877                 // version
878                 u8 version = readU8(is);
879                 // check version
880                 if(version != 0)
881                         return;
882                 // pos
883                 m_position = readV3F1000(is);
884                 pos_translator.init(m_position);
885         }
886         
887         updateNodePos();
888 }
889
890 /*
891         Oerkki1CAO
892 */
893
894 #include "inventory.h"
895
896 // Prototype
897 Oerkki1CAO proto_Oerkki1CAO(NULL, NULL);
898
899 Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env):
900         ClientActiveObject(0, gamedef, env),
901         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
902         m_node(NULL),
903         m_position(v3f(0,10*BS,0)),
904         m_yaw(0),
905         m_damage_visual_timer(0),
906         m_damage_texture_enabled(false)
907 {
908         ClientActiveObject::registerType(getType(), create);
909 }
910
911 Oerkki1CAO::~Oerkki1CAO()
912 {
913 }
914
915 ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef, ClientEnvironment *env)
916 {
917         return new Oerkki1CAO(gamedef, env);
918 }
919
920 void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
921                         IrrlichtDevice *irr)
922 {
923         if(m_node != NULL)
924                 return;
925         
926         //video::IVideoDriver* driver = smgr->getVideoDriver();
927         
928         scene::SMesh *mesh = new scene::SMesh();
929         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
930         video::SColor c(255,255,255,255);
931         video::S3DVertex vertices[4] =
932         {
933                 video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
934                 video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
935                 video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
936                 video::S3DVertex(-BS/2-BS,BS*2,0, 0,0,0, c, 0,0),
937         };
938         u16 indices[] = {0,1,2,2,3,0};
939         buf->append(vertices, 4, indices, 6);
940         // Set material
941         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
942         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
943         //buf->getMaterial().setTexture(0, NULL);
944         buf->getMaterial().setTexture(0, tsrc->getTextureRaw("oerkki1.png"));
945         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
946         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
947         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
948         // Add to mesh
949         mesh->addMeshBuffer(buf);
950         buf->drop();
951         m_node = smgr->addMeshSceneNode(mesh, NULL);
952         mesh->drop();
953         // Set it to use the materials of the meshbuffers directly.
954         // This is needed for changing the texture in the future
955         m_node->setReadOnlyMaterials(true);
956         updateNodePos();
957 }
958
959 void Oerkki1CAO::removeFromScene()
960 {
961         if(m_node == NULL)
962                 return;
963
964         m_node->remove();
965         m_node = NULL;
966 }
967
968 void Oerkki1CAO::updateLight(u8 light_at_pos)
969 {
970         if(m_node == NULL)
971                 return;
972         
973         if(light_at_pos <= 2)
974         {
975                 m_node->setVisible(false);
976                 return;
977         }
978
979         m_node->setVisible(true);
980
981         u8 li = decode_light(light_at_pos);
982         video::SColor color(255,li,li,li);
983         setMeshColor(m_node->getMesh(), color);
984 }
985
986 v3s16 Oerkki1CAO::getLightPosition()
987 {
988         return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
989 }
990
991 void Oerkki1CAO::updateNodePos()
992 {
993         if(m_node == NULL)
994                 return;
995
996         //m_node->setPosition(m_position);
997         m_node->setPosition(pos_translator.vect_show);
998
999         v3f rot = m_node->getRotation();
1000         rot.Y = 180.0 - m_yaw + 90.0;
1001         m_node->setRotation(rot);
1002 }
1003
1004 void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
1005 {
1006         ITextureSource *tsrc = m_gamedef->tsrc();
1007
1008         pos_translator.translate(dtime);
1009         updateNodePos();
1010
1011         LocalPlayer *player = env->getLocalPlayer();
1012         assert(player);
1013         
1014         v3f playerpos = player->getPosition();
1015         v2f playerpos_2d(playerpos.X,playerpos.Z);
1016         v2f objectpos_2d(m_position.X,m_position.Z);
1017
1018         if(fabs(m_position.Y - playerpos.Y) < 1.5*BS &&
1019                         objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
1020         {
1021                 if(m_attack_interval.step(dtime, 0.5))
1022                 {
1023                         env->damageLocalPlayer(2);
1024                 }
1025         }
1026
1027         if(m_damage_visual_timer > 0)
1028         {
1029                 if(!m_damage_texture_enabled)
1030                 {
1031                         // Enable damage texture
1032                         if(m_node)
1033                         {
1034                                 /*video::IVideoDriver* driver =
1035                                         m_node->getSceneManager()->getVideoDriver();*/
1036                                 
1037                                 scene::IMesh *mesh = m_node->getMesh();
1038                                 if(mesh == NULL)
1039                                         return;
1040                                 
1041                                 u16 mc = mesh->getMeshBufferCount();
1042                                 for(u16 j=0; j<mc; j++)
1043                                 {
1044                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
1045                                         buf->getMaterial().setTexture(0,
1046                                                         tsrc->getTextureRaw("oerkki1_damaged.png"));
1047                                 }
1048                         }
1049                         m_damage_texture_enabled = true;
1050                 }
1051                 m_damage_visual_timer -= dtime;
1052         }
1053         else
1054         {
1055                 if(m_damage_texture_enabled)
1056                 {
1057                         // Disable damage texture
1058                         if(m_node)
1059                         {
1060                                 /*video::IVideoDriver* driver =
1061                                         m_node->getSceneManager()->getVideoDriver();*/
1062                                 
1063                                 scene::IMesh *mesh = m_node->getMesh();
1064                                 if(mesh == NULL)
1065                                         return;
1066                                 
1067                                 u16 mc = mesh->getMeshBufferCount();
1068                                 for(u16 j=0; j<mc; j++)
1069                                 {
1070                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
1071                                         buf->getMaterial().setTexture(0,
1072                                                         tsrc->getTextureRaw("oerkki1.png"));
1073                                 }
1074                         }
1075                         m_damage_texture_enabled = false;
1076                 }
1077         }
1078 }
1079
1080 void Oerkki1CAO::processMessage(const std::string &data)
1081 {
1082         //infostream<<"Oerkki1CAO: Got message"<<std::endl;
1083         std::istringstream is(data, std::ios::binary);
1084         // command
1085         u8 cmd = readU8(is);
1086         if(cmd == 0)
1087         {
1088                 // pos
1089                 m_position = readV3F1000(is);
1090                 pos_translator.update(m_position);
1091                 // yaw
1092                 m_yaw = readF1000(is);
1093                 updateNodePos();
1094         }
1095         else if(cmd == 1)
1096         {
1097                 //u16 damage = readU8(is);
1098                 m_damage_visual_timer = 1.0;
1099         }
1100 }
1101
1102 void Oerkki1CAO::initialize(const std::string &data)
1103 {
1104         //infostream<<"Oerkki1CAO: Got init data"<<std::endl;
1105         
1106         {
1107                 std::istringstream is(data, std::ios::binary);
1108                 // version
1109                 u8 version = readU8(is);
1110                 // check version
1111                 if(version != 0)
1112                         return;
1113                 // pos
1114                 m_position = readV3F1000(is);
1115                 pos_translator.init(m_position);
1116         }
1117         
1118         updateNodePos();
1119 }
1120
1121 bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
1122 {
1123         m_damage_visual_timer = 1.0;
1124
1125         m_position += dir * BS;
1126         pos_translator.sharpen();
1127         pos_translator.update(m_position);
1128         updateNodePos();
1129         
1130         return false;
1131 }
1132
1133 /*
1134         FireflyCAO
1135 */
1136
1137 // Prototype
1138 FireflyCAO proto_FireflyCAO(NULL, NULL);
1139
1140 FireflyCAO::FireflyCAO(IGameDef *gamedef, ClientEnvironment *env):
1141         ClientActiveObject(0, gamedef, env),
1142         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
1143         m_node(NULL),
1144         m_position(v3f(0,10*BS,0)),
1145         m_yaw(0)
1146 {
1147         ClientActiveObject::registerType(getType(), create);
1148 }
1149
1150 FireflyCAO::~FireflyCAO()
1151 {
1152 }
1153
1154 ClientActiveObject* FireflyCAO::create(IGameDef *gamedef, ClientEnvironment *env)
1155 {
1156         return new FireflyCAO(gamedef, env);
1157 }
1158
1159 void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1160                         IrrlichtDevice *irr)
1161 {
1162         if(m_node != NULL)
1163                 return;
1164         
1165         //video::IVideoDriver* driver = smgr->getVideoDriver();
1166         
1167         scene::SMesh *mesh = new scene::SMesh();
1168         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
1169         video::SColor c(255,255,255,255);
1170         video::S3DVertex vertices[4] =
1171         {
1172                 video::S3DVertex(0,0,0, 0,0,0, c, 0,1),
1173                 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
1174                 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
1175                 video::S3DVertex(0,BS/2,0, 0,0,0, c, 0,0),
1176         };
1177         u16 indices[] = {0,1,2,2,3,0};
1178         buf->append(vertices, 4, indices, 6);
1179         // Set material
1180         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
1181         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
1182         //buf->getMaterial().setTexture(0, NULL);
1183         buf->getMaterial().setTexture(0, tsrc->getTextureRaw("firefly.png"));
1184         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
1185         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
1186         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
1187         // Add to mesh
1188         mesh->addMeshBuffer(buf);
1189         buf->drop();
1190         m_node = smgr->addMeshSceneNode(mesh, NULL);
1191         mesh->drop();
1192         // Set it to use the materials of the meshbuffers directly.
1193         // This is needed for changing the texture in the future
1194         m_node->setReadOnlyMaterials(true);
1195         updateNodePos();
1196 }
1197
1198 void FireflyCAO::removeFromScene()
1199 {
1200         if(m_node == NULL)
1201                 return;
1202
1203         m_node->remove();
1204         m_node = NULL;
1205 }
1206
1207 void FireflyCAO::updateLight(u8 light_at_pos)
1208 {
1209         if(m_node == NULL)
1210                 return;
1211
1212         u8 li = 255;
1213         video::SColor color(255,li,li,li);
1214         setMeshColor(m_node->getMesh(), color);
1215 }
1216
1217 v3s16 FireflyCAO::getLightPosition()
1218 {
1219         return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
1220 }
1221
1222 void FireflyCAO::updateNodePos()
1223 {
1224         if(m_node == NULL)
1225                 return;
1226
1227         //m_node->setPosition(m_position);
1228         m_node->setPosition(pos_translator.vect_show);
1229
1230         v3f rot = m_node->getRotation();
1231         rot.Y = 180.0 - m_yaw;
1232         m_node->setRotation(rot);
1233 }
1234
1235 void FireflyCAO::step(float dtime, ClientEnvironment *env)
1236 {
1237         pos_translator.translate(dtime);
1238         updateNodePos();
1239 }
1240
1241 void FireflyCAO::processMessage(const std::string &data)
1242 {
1243         //infostream<<"FireflyCAO: Got message"<<std::endl;
1244         std::istringstream is(data, std::ios::binary);
1245         // command
1246         u8 cmd = readU8(is);
1247         if(cmd == 0)
1248         {
1249                 // pos
1250                 m_position = readV3F1000(is);
1251                 pos_translator.update(m_position);
1252                 // yaw
1253                 m_yaw = readF1000(is);
1254                 updateNodePos();
1255         }
1256 }
1257
1258 void FireflyCAO::initialize(const std::string &data)
1259 {
1260         //infostream<<"FireflyCAO: Got init data"<<std::endl;
1261         
1262         {
1263                 std::istringstream is(data, std::ios::binary);
1264                 // version
1265                 u8 version = readU8(is);
1266                 // check version
1267                 if(version != 0)
1268                         return;
1269                 // pos
1270                 m_position = readV3F1000(is);
1271                 pos_translator.init(m_position);
1272         }
1273         
1274         updateNodePos();
1275 }
1276
1277 /*
1278         MobV2CAO
1279 */
1280
1281 // Prototype
1282 MobV2CAO proto_MobV2CAO(NULL, NULL);
1283
1284 MobV2CAO::MobV2CAO(IGameDef *gamedef, ClientEnvironment *env):
1285         ClientActiveObject(0, gamedef, env),
1286         m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
1287         m_node(NULL),
1288         m_position(v3f(0,10*BS,0)),
1289         m_yaw(0),
1290         m_walking(false),
1291         m_walking_unset_timer(0),
1292         m_walk_timer(0),
1293         m_walk_frame(0),
1294         m_damage_visual_timer(0),
1295         m_last_light(0),
1296         m_shooting(0),
1297         m_shooting_unset_timer(0),
1298         m_sprite_size(BS,BS),
1299         m_sprite_y(0),
1300         m_bright_shooting(false),
1301         m_lock_full_brightness(false),
1302         m_player_hit_timer(0)
1303 {
1304         ClientActiveObject::registerType(getType(), create);
1305
1306         m_properties = new Settings;
1307 }
1308
1309 MobV2CAO::~MobV2CAO()
1310 {
1311         delete m_properties;
1312 }
1313
1314 ClientActiveObject* MobV2CAO::create(IGameDef *gamedef, ClientEnvironment *env)
1315 {
1316         return new MobV2CAO(gamedef, env);
1317 }
1318
1319 void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1320                         IrrlichtDevice *irr)
1321 {
1322         if(m_node != NULL)
1323                 return;
1324         
1325         /*infostream<<"MobV2CAO::addToScene using texture_name="<<
1326                         m_texture_name<<std::endl;*/
1327         std::string texture_string = m_texture_name +
1328                         "^[makealpha:128,0,0^[makealpha:128,128,0";
1329         
1330         scene::IBillboardSceneNode *bill = smgr->addBillboardSceneNode(
1331                         NULL, v2f(1, 1), v3f(0,0,0), -1);
1332         bill->setMaterialTexture(0, tsrc->getTextureRaw(texture_string));
1333         bill->setMaterialFlag(video::EMF_LIGHTING, false);
1334         bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1335         bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1336         bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1337         bill->setColor(video::SColor(255,0,0,0));
1338         bill->setVisible(false); /* Set visible when brightness is known */
1339         bill->setSize(m_sprite_size);
1340         if(m_sprite_type == "humanoid_1"){
1341                 const float txp = 1./192;
1342                 const float txs = txp*32;
1343                 const float typ = 1./240;
1344                 const float tys = typ*48;
1345                 setBillboardTextureMatrix(bill, txs, tys, 0, 0);
1346         } else if(m_sprite_type == "simple"){
1347                 const float txs = 1.0;
1348                 const float tys = 1.0 / m_simple_anim_frames;
1349                 setBillboardTextureMatrix(bill, txs, tys, 0, 0);
1350         } else {
1351                 infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
1352                                 <<std::endl;
1353         }
1354
1355         m_node = bill;
1356
1357         updateNodePos();
1358 }
1359
1360 void MobV2CAO::removeFromScene()
1361 {
1362         if(m_node == NULL)
1363                 return;
1364
1365         m_node->remove();
1366         m_node = NULL;
1367 }
1368
1369 void MobV2CAO::updateLight(u8 light_at_pos)
1370 {
1371         if(m_lock_full_brightness)
1372                 light_at_pos = 15;
1373         
1374         m_last_light = light_at_pos;
1375
1376         if(m_node == NULL)
1377                 return;
1378         
1379         if(m_damage_visual_timer > 0)
1380                 return;
1381         
1382         if(m_shooting && m_bright_shooting)
1383                 return;
1384         
1385         /*if(light_at_pos <= 2){
1386                 m_node->setVisible(false);
1387                 return;
1388         }*/
1389
1390         m_node->setVisible(true);
1391
1392         u8 li = decode_light(light_at_pos);
1393         video::SColor color(255,li,li,li);
1394         m_node->setColor(color);
1395 }
1396
1397 v3s16 MobV2CAO::getLightPosition()
1398 {
1399         return floatToInt(m_position+v3f(0,0,0), BS);
1400 }
1401
1402 void MobV2CAO::updateNodePos()
1403 {
1404         if(m_node == NULL)
1405                 return;
1406
1407         m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
1408 }
1409
1410 void MobV2CAO::step(float dtime, ClientEnvironment *env)
1411 {
1412         scene::IBillboardSceneNode *bill = m_node;
1413         if(!bill)
1414                 return;
1415
1416         pos_translator.translate(dtime);
1417         
1418         if(m_sprite_type == "humanoid_1"){
1419                 scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
1420                 if(!camera)
1421                         return;
1422                 v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
1423                 cam_to_mob.normalize();
1424                 int col = 0;
1425                 if(cam_to_mob.Y > 0.75)
1426                         col = 5;
1427                 else if(cam_to_mob.Y < -0.75)
1428                         col = 4;
1429                 else{
1430                         float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.;
1431                         float dir = mob_dir - m_yaw;
1432                         dir = wrapDegrees_180(dir);
1433                         //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1434                         if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1435                                 col = 2;
1436                         else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1437                                 col = 3;
1438                         else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1439                                 col = 0;
1440                         else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1441                                 col = 1;
1442                         else
1443                                 col = 4;
1444                 }
1445
1446                 int row = 0;
1447                 if(m_shooting){
1448                         row = 3;
1449                 } else if(m_walking){
1450                         m_walk_timer += dtime;
1451                         if(m_walk_timer >= 0.5){
1452                                 m_walk_frame = (m_walk_frame + 1) % 2;
1453                                 m_walk_timer = 0;
1454                         }
1455                         if(m_walk_frame == 0)
1456                                 row = 1;
1457                         else
1458                                 row = 2;
1459                 }
1460
1461                 const float txp = 1./192;
1462                 const float txs = txp*32;
1463                 const float typ = 1./240;
1464                 const float tys = typ*48;
1465                 setBillboardTextureMatrix(bill, txs, tys, col, row);
1466         } else if(m_sprite_type == "simple"){
1467                 m_walk_timer += dtime;
1468                 if(m_walk_timer >= m_simple_anim_frametime){
1469                         m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
1470                         m_walk_timer = 0;
1471                 }
1472                 int col = 0;
1473                 int row = m_walk_frame;
1474                 const float txs = 1.0;
1475                 const float tys = 1.0 / m_simple_anim_frames;
1476                 setBillboardTextureMatrix(bill, txs, tys, col, row);
1477         } else {
1478                 infostream<<"MobV2CAO::step(): Unknown sprite type \""
1479                                 <<m_sprite_type<<"\""<<std::endl;
1480         }
1481
1482         updateNodePos();
1483
1484         /* Damage local player */
1485         if(m_player_hit_damage && m_player_hit_timer <= 0.0){
1486                 LocalPlayer *player = env->getLocalPlayer();
1487                 assert(player);
1488                 
1489                 v3f playerpos = player->getPosition();
1490                 v2f playerpos_2d(playerpos.X,playerpos.Z);
1491                 v2f objectpos_2d(m_position.X,m_position.Z);
1492
1493                 if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
1494                 objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
1495                 {
1496                         env->damageLocalPlayer(m_player_hit_damage);
1497                         m_player_hit_timer = m_player_hit_interval;
1498                 }
1499         }
1500
1501         /* Run timers */
1502
1503         m_player_hit_timer -= dtime;
1504
1505         if(m_damage_visual_timer >= 0){
1506                 m_damage_visual_timer -= dtime;
1507                 if(m_damage_visual_timer <= 0){
1508                         infostream<<"id="<<m_id<<" damage visual ended"<<std::endl;
1509                 }
1510         }
1511
1512         m_walking_unset_timer += dtime;
1513         if(m_walking_unset_timer >= 1.0){
1514                 m_walking = false;
1515         }
1516
1517         m_shooting_unset_timer -= dtime;
1518         if(m_shooting_unset_timer <= 0.0){
1519                 if(m_bright_shooting){
1520                         u8 li = decode_light(m_last_light);
1521                         video::SColor color(255,li,li,li);
1522                         bill->setColor(color);
1523                         m_bright_shooting = false;
1524                 }
1525                 m_shooting = false;
1526         }
1527
1528 }
1529
1530 void MobV2CAO::processMessage(const std::string &data)
1531 {
1532         //infostream<<"MobV2CAO: Got message"<<std::endl;
1533         std::istringstream is(data, std::ios::binary);
1534         // command
1535         u8 cmd = readU8(is);
1536
1537         // Move
1538         if(cmd == 0)
1539         {
1540                 // pos
1541                 m_position = readV3F1000(is);
1542                 pos_translator.update(m_position);
1543                 // yaw
1544                 m_yaw = readF1000(is);
1545
1546                 m_walking = true;
1547                 m_walking_unset_timer = 0;
1548
1549                 updateNodePos();
1550         }
1551         // Damage
1552         else if(cmd == 1)
1553         {
1554                 //u16 damage = readU16(is);
1555
1556                 /*u8 li = decode_light(m_last_light);
1557                 if(li >= 100)
1558                         li = 30;
1559                 else
1560                         li = 255;*/
1561
1562                 /*video::SColor color(255,255,0,0);
1563                 m_node->setColor(color);
1564
1565                 m_damage_visual_timer = 0.2;*/
1566         }
1567         // Trigger shooting
1568         else if(cmd == 2)
1569         {
1570                 // length
1571                 m_shooting_unset_timer = readF1000(is);
1572                 // bright?
1573                 m_bright_shooting = readU8(is);
1574                 if(m_bright_shooting){
1575                         u8 li = 255;
1576                         video::SColor color(255,li,li,li);
1577                         m_node->setColor(color);
1578                 }
1579
1580                 m_shooting = true;
1581         }
1582 }
1583
1584 void MobV2CAO::initialize(const std::string &data)
1585 {
1586         //infostream<<"MobV2CAO: Got init data"<<std::endl;
1587         
1588         {
1589                 std::istringstream is(data, std::ios::binary);
1590                 // version
1591                 u8 version = readU8(is);
1592                 // check version
1593                 if(version != 0){
1594                         infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
1595                         return;
1596                 }
1597                 
1598                 std::ostringstream tmp_os(std::ios::binary);
1599                 decompressZlib(is, tmp_os);
1600                 std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
1601                 m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
1602
1603                 infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl;
1604                 m_properties->writeLines(infostream);
1605                 
1606                 m_properties->setDefault("looks", "dummy_default");
1607                 m_properties->setDefault("yaw", "0");
1608                 m_properties->setDefault("pos", "(0,0,0)");
1609                 m_properties->setDefault("player_hit_damage", "0");
1610                 m_properties->setDefault("player_hit_distance", "1.5");
1611                 m_properties->setDefault("player_hit_interval", "1.5");
1612                 
1613                 setLooks(m_properties->get("looks"));
1614                 m_yaw = m_properties->getFloat("yaw");
1615                 m_position = m_properties->getV3F("pos");
1616                 m_player_hit_damage = m_properties->getS32("player_hit_damage");
1617                 m_player_hit_distance = m_properties->getFloat("player_hit_distance");
1618                 m_player_hit_interval = m_properties->getFloat("player_hit_interval");
1619
1620                 pos_translator.init(m_position);
1621         }
1622         
1623         updateNodePos();
1624 }
1625
1626 bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir)
1627 {
1628         video::SColor color(255,255,0,0);
1629         m_node->setColor(color);
1630
1631         m_damage_visual_timer = 0.05;
1632
1633         m_position += dir * BS;
1634         pos_translator.sharpen();
1635         pos_translator.update(m_position);
1636         updateNodePos();
1637         
1638         return false;
1639 }
1640
1641 void MobV2CAO::setLooks(const std::string &looks)
1642 {
1643         v2f selection_size = v2f(0.4, 0.4) * BS;
1644         float selection_y = 0 * BS;
1645
1646         if(looks == "dungeon_master"){
1647                 m_texture_name = "dungeon_master.png";
1648                 m_sprite_type = "humanoid_1";
1649                 m_sprite_size = v2f(2, 3) * BS;
1650                 m_sprite_y = 0.85 * BS;
1651                 selection_size = v2f(0.4, 2.6) * BS;
1652                 selection_y = -0.4 * BS;
1653         }
1654         else if(looks == "fireball"){
1655                 m_texture_name = "fireball.png";
1656                 m_sprite_type = "simple";
1657                 m_sprite_size = v2f(1, 1) * BS;
1658                 m_simple_anim_frames = 3;
1659                 m_simple_anim_frametime = 0.1;
1660                 m_lock_full_brightness = true;
1661         }
1662         else{
1663                 m_texture_name = "stone.png";
1664                 m_sprite_type = "simple";
1665                 m_sprite_size = v2f(1, 1) * BS;
1666                 m_simple_anim_frames = 3;
1667                 m_simple_anim_frametime = 0.333;
1668                 selection_size = v2f(0.4, 0.4) * BS;
1669                 selection_y = 0 * BS;
1670         }
1671
1672         m_selection_box = core::aabbox3d<f32>(
1673                         -selection_size.X, selection_y, -selection_size.X,
1674                         selection_size.X, selection_y+selection_size.Y,
1675                         selection_size.X);
1676 }
1677
1678 /*
1679         LuaEntityCAO
1680 */
1681
1682 #include "luaentity_common.h"
1683
1684 class LuaEntityCAO : public ClientActiveObject
1685 {
1686 private:
1687         core::aabbox3d<f32> m_selection_box;
1688         scene::IMeshSceneNode *m_meshnode;
1689         scene::IBillboardSceneNode *m_spritenode;
1690         v3f m_position;
1691         v3f m_velocity;
1692         v3f m_acceleration;
1693         float m_yaw;
1694         struct LuaEntityProperties *m_prop;
1695         SmoothTranslator pos_translator;
1696         // Spritesheet/animation stuff
1697         v2f m_tx_size;
1698         v2s16 m_tx_basepos;
1699         bool m_tx_select_horiz_by_yawpitch;
1700         int m_anim_frame;
1701         int m_anim_num_frames;
1702         float m_anim_framelength;
1703         float m_anim_timer;
1704
1705 public:
1706         LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
1707                 ClientActiveObject(0, gamedef, env),
1708                 m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
1709                 m_meshnode(NULL),
1710                 m_spritenode(NULL),
1711                 m_position(v3f(0,10*BS,0)),
1712                 m_velocity(v3f(0,0,0)),
1713                 m_acceleration(v3f(0,0,0)),
1714                 m_yaw(0),
1715                 m_prop(new LuaEntityProperties),
1716                 m_tx_size(1,1),
1717                 m_tx_basepos(0,0),
1718                 m_tx_select_horiz_by_yawpitch(false),
1719                 m_anim_frame(0),
1720                 m_anim_num_frames(1),
1721                 m_anim_framelength(0.2),
1722                 m_anim_timer(0)
1723         {
1724                 if(gamedef == NULL)
1725                         ClientActiveObject::registerType(getType(), create);
1726         }
1727
1728         void initialize(const std::string &data)
1729         {
1730                 infostream<<"LuaEntityCAO: Got init data"<<std::endl;
1731                 
1732                 std::istringstream is(data, std::ios::binary);
1733                 // version
1734                 u8 version = readU8(is);
1735                 // check version
1736                 if(version != 0)
1737                         return;
1738                 // pos
1739                 m_position = readV3F1000(is);
1740                 // yaw
1741                 m_yaw = readF1000(is);
1742                 // properties
1743                 std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
1744                 m_prop->deSerialize(prop_is);
1745
1746                 infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
1747
1748                 m_selection_box = m_prop->collisionbox;
1749                 m_selection_box.MinEdge *= BS;
1750                 m_selection_box.MaxEdge *= BS;
1751                         
1752                 pos_translator.init(m_position);
1753
1754                 m_tx_size.X = 1.0 / m_prop->spritediv.X;
1755                 m_tx_size.Y = 1.0 / m_prop->spritediv.Y;
1756                 m_tx_basepos.X = m_tx_size.X * m_prop->initial_sprite_basepos.X;
1757                 m_tx_basepos.Y = m_tx_size.Y * m_prop->initial_sprite_basepos.Y;
1758                 
1759                 updateNodePos();
1760         }
1761
1762         ~LuaEntityCAO()
1763         {
1764                 delete m_prop;
1765         }
1766
1767         static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
1768         {
1769                 return new LuaEntityCAO(gamedef, env);
1770         }
1771
1772         u8 getType() const
1773         {
1774                 return ACTIVEOBJECT_TYPE_LUAENTITY;
1775         }
1776         core::aabbox3d<f32>* getSelectionBox()
1777         {
1778                 return &m_selection_box;
1779         }
1780         v3f getPosition()
1781         {
1782                 return pos_translator.vect_show;
1783         }
1784                 
1785         void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1786                         IrrlichtDevice *irr)
1787         {
1788                 if(m_meshnode != NULL || m_spritenode != NULL)
1789                         return;
1790                 
1791                 //video::IVideoDriver* driver = smgr->getVideoDriver();
1792
1793                 if(m_prop->visual == "sprite"){
1794                         infostream<<"LuaEntityCAO::addToScene(): single_sprite"<<std::endl;
1795                         m_spritenode = smgr->addBillboardSceneNode(
1796                                         NULL, v2f(1, 1), v3f(0,0,0), -1);
1797                         m_spritenode->setMaterialTexture(0,
1798                                         tsrc->getTextureRaw("unknown_block.png"));
1799                         m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
1800                         m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1801                         m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1802                         m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1803                         m_spritenode->setColor(video::SColor(255,0,0,0));
1804                         m_spritenode->setVisible(false); /* Set visible when brightness is known */
1805                         m_spritenode->setSize(m_prop->visual_size*BS);
1806                         {
1807                                 const float txs = 1.0 / 1;
1808                                 const float tys = 1.0 / 1;
1809                                 setBillboardTextureMatrix(m_spritenode,
1810                                                 txs, tys, 0, 0);
1811                         }
1812                 } else if(m_prop->visual == "cube"){
1813                         infostream<<"LuaEntityCAO::addToScene(): cube"<<std::endl;
1814                         scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS));
1815                         m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
1816                         mesh->drop();
1817                         
1818                         m_meshnode->setScale(v3f(1));
1819                         // Will be shown when we know the brightness
1820                         m_meshnode->setVisible(false);
1821                 } else {
1822                         infostream<<"LuaEntityCAO::addToScene(): \""<<m_prop->visual
1823                                         <<"\" not supported"<<std::endl;
1824                 }
1825                 updateTextures("");
1826                 updateNodePos();
1827         }
1828
1829         void removeFromScene()
1830         {
1831                 if(m_meshnode){
1832                         m_meshnode->remove();
1833                         m_meshnode = NULL;
1834                 }
1835                 if(m_spritenode){
1836                         m_spritenode->remove();
1837                         m_spritenode = NULL;
1838                 }
1839         }
1840
1841         void updateLight(u8 light_at_pos)
1842         {
1843                 u8 li = decode_light(light_at_pos);
1844                 video::SColor color(255,li,li,li);
1845                 if(m_meshnode){
1846                         setMeshColor(m_meshnode->getMesh(), color);
1847                         m_meshnode->setVisible(true);
1848                 }
1849                 if(m_spritenode){
1850                         m_spritenode->setColor(color);
1851                         m_spritenode->setVisible(true);
1852                 }
1853         }
1854
1855         v3s16 getLightPosition()
1856         {
1857                 return floatToInt(m_position, BS);
1858         }
1859
1860         void updateNodePos()
1861         {
1862                 if(m_meshnode){
1863                         m_meshnode->setPosition(pos_translator.vect_show);
1864                 }
1865                 if(m_spritenode){
1866                         m_spritenode->setPosition(pos_translator.vect_show);
1867                 }
1868         }
1869
1870         void step(float dtime, ClientEnvironment *env)
1871         {
1872                 if(m_prop->physical){
1873                         core::aabbox3d<f32> box = m_prop->collisionbox;
1874                         box.MinEdge *= BS;
1875                         box.MaxEdge *= BS;
1876                         collisionMoveResult moveresult;
1877                         f32 pos_max_d = BS*0.25; // Distance per iteration
1878                         v3f p_pos = m_position;
1879                         v3f p_velocity = m_velocity;
1880                         IGameDef *gamedef = env->getGameDef();
1881                         moveresult = collisionMovePrecise(&env->getMap(), gamedef,
1882                                         pos_max_d, box, dtime, p_pos, p_velocity);
1883                         // Apply results
1884                         m_position = p_pos;
1885                         m_velocity = p_velocity;
1886                         
1887                         bool is_end_position = moveresult.collides;
1888                         pos_translator.update(m_position, is_end_position, dtime);
1889                         pos_translator.translate(dtime);
1890                         updateNodePos();
1891
1892                         m_velocity += dtime * m_acceleration;
1893                 } else {
1894                         m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
1895                         m_velocity += dtime * m_acceleration;
1896                         pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
1897                         pos_translator.translate(dtime);
1898                         updateNodePos();
1899                 }
1900
1901                 m_anim_timer += dtime;
1902                 if(m_anim_timer >= m_anim_framelength){
1903                         m_anim_timer -= m_anim_framelength;
1904                         m_anim_frame++;
1905                         if(m_anim_frame >= m_anim_num_frames)
1906                                 m_anim_frame = 0;
1907                 }
1908
1909                 updateTexturePos();
1910         }
1911
1912         void updateTexturePos()
1913         {
1914                 if(m_spritenode){
1915                         scene::ICameraSceneNode* camera =
1916                                         m_spritenode->getSceneManager()->getActiveCamera();
1917                         if(!camera)
1918                                 return;
1919                         v3f cam_to_entity = m_spritenode->getAbsolutePosition()
1920                                         - camera->getAbsolutePosition();
1921                         cam_to_entity.normalize();
1922
1923                         int row = m_tx_basepos.Y;
1924                         int col = m_tx_basepos.X;
1925                         
1926                         if(m_tx_select_horiz_by_yawpitch)
1927                         {
1928                                 if(cam_to_entity.Y > 0.75)
1929                                         col += 5;
1930                                 else if(cam_to_entity.Y < -0.75)
1931                                         col += 4;
1932                                 else{
1933                                         float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.;
1934                                         float dir = mob_dir - m_yaw;
1935                                         dir = wrapDegrees_180(dir);
1936                                         //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1937                                         if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1938                                                 col += 2;
1939                                         else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1940                                                 col += 3;
1941                                         else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1942                                                 col += 0;
1943                                         else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1944                                                 col += 1;
1945                                         else
1946                                                 col += 4;
1947                                 }
1948                         }
1949                         
1950                         // Animation goes downwards
1951                         row += m_anim_frame;
1952
1953                         float txs = m_tx_size.X;
1954                         float tys = m_tx_size.Y;
1955                         setBillboardTextureMatrix(m_spritenode,
1956                                         txs, tys, col, row);
1957                 }
1958         }
1959
1960         void updateTextures(const std::string &mod)
1961         {
1962                 ITextureSource *tsrc = m_gamedef->tsrc();
1963
1964                 if(m_spritenode){
1965                         std::string texturestring = "unknown_block.png";
1966                         if(m_prop->textures.size() >= 1)
1967                                 texturestring = m_prop->textures[0];
1968                         texturestring += mod;
1969                         m_spritenode->setMaterialTexture(0,
1970                                         tsrc->getTextureRaw(texturestring));
1971                 }
1972                 if(m_meshnode){
1973                         for (u32 i = 0; i < 6; ++i)
1974                         {
1975                                 std::string texturestring = "unknown_block.png";
1976                                 if(m_prop->textures.size() > i)
1977                                         texturestring = m_prop->textures[i];
1978                                 texturestring += mod;
1979                                 AtlasPointer ap = tsrc->getTexture(texturestring);
1980
1981                                 // Get the tile texture and atlas transformation
1982                                 video::ITexture* atlas = ap.atlas;
1983                                 v2f pos = ap.pos;
1984                                 v2f size = ap.size;
1985
1986                                 // Set material flags and texture
1987                                 video::SMaterial& material = m_meshnode->getMaterial(i);
1988                                 material.setFlag(video::EMF_LIGHTING, false);
1989                                 material.setFlag(video::EMF_BILINEAR_FILTER, false);
1990                                 material.setTexture(0, atlas);
1991                                 material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
1992                                 material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
1993                         }
1994                 }
1995         }
1996
1997         void processMessage(const std::string &data)
1998         {
1999                 //infostream<<"LuaEntityCAO: Got message"<<std::endl;
2000                 std::istringstream is(data, std::ios::binary);
2001                 // command
2002                 u8 cmd = readU8(is);
2003                 if(cmd == 0) // update position
2004                 {
2005                         // do_interpolate
2006                         bool do_interpolate = readU8(is);
2007                         // pos
2008                         m_position = readV3F1000(is);
2009                         // velocity
2010                         m_velocity = readV3F1000(is);
2011                         // acceleration
2012                         m_acceleration = readV3F1000(is);
2013                         // yaw
2014                         m_yaw = readF1000(is);
2015                         // is_end_position (for interpolation)
2016                         bool is_end_position = readU8(is);
2017                         // update_interval
2018                         float update_interval = readF1000(is);
2019                         
2020                         if(do_interpolate){
2021                                 if(!m_prop->physical)
2022                                         pos_translator.update(m_position, is_end_position, update_interval);
2023                         } else {
2024                                 pos_translator.init(m_position);
2025                         }
2026                         updateNodePos();
2027                 }
2028                 else if(cmd == 1) // set texture modification
2029                 {
2030                         std::string mod = deSerializeString(is);
2031                         updateTextures(mod);
2032                 }
2033                 else if(cmd == 2) // set sprite
2034                 {
2035                         v2s16 p = readV2S16(is);
2036                         int num_frames = readU16(is);
2037                         float framelength = readF1000(is);
2038                         bool select_horiz_by_yawpitch = readU8(is);
2039                         
2040                         m_tx_basepos = p;
2041                         m_anim_num_frames = num_frames;
2042                         m_anim_framelength = framelength;
2043                         m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
2044
2045                         updateTexturePos();
2046                 }
2047         }
2048 };
2049
2050 // Prototype
2051 LuaEntityCAO proto_LuaEntityCAO(NULL, NULL);
2052
2053 /*
2054         PlayerCAO
2055 */
2056
2057 class PlayerCAO : public ClientActiveObject
2058 {
2059 private:
2060         core::aabbox3d<f32> m_selection_box;
2061         scene::IMeshSceneNode *m_body, *m_head, *m_leg_l, *m_leg_r, *m_arm_l, *m_arm_r;
2062         scene::ITextSceneNode* m_text;
2063         std::string m_name;
2064         v3f m_position;
2065         v3f m_old_position;
2066         float m_leg_rot;
2067         float m_leg_rot_i;
2068         float m_speed;
2069         float m_pitch;
2070         float m_yaw;
2071         SmoothTranslator pos_translator;
2072         SmoothTranslator old_pos_translator;
2073         SmoothTranslator head_translator;
2074         bool m_is_local_player;
2075         LocalPlayer *m_local_player;
2076         float m_damage_visual_timer;
2077
2078 public:
2079         PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
2080                 ClientActiveObject(0, gamedef, env),
2081                 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.),
2082                 m_body(NULL), m_head(NULL), m_leg_l(NULL), m_leg_r(NULL), m_arm_l(NULL), m_arm_r(NULL),
2083                 m_text(NULL),
2084                 m_position(v3f(0,0,0)),
2085                 m_old_position(v3f(0,0,0)),
2086                 m_leg_rot(0),
2087                 m_leg_rot_i(0),
2088                 m_speed(0),
2089                 m_pitch(0),
2090                 m_yaw(0),
2091                 m_is_local_player(false),
2092                 m_local_player(NULL),
2093                 m_damage_visual_timer(0)
2094         {
2095                 if(gamedef == NULL)
2096                         ClientActiveObject::registerType(getType(), create);
2097         }
2098
2099         void initialize(const std::string &data)
2100         {
2101                 infostream<<"PlayerCAO: Got init data"<<std::endl;
2102                 
2103                 std::istringstream is(data, std::ios::binary);
2104                 // version
2105                 u8 version = readU8(is);
2106                 // check version
2107                 if(version != 0)
2108                         return;
2109                 // name
2110                 m_name = deSerializeString(is);
2111                 // pos
2112                 m_old_position = m_position; // old position
2113                 m_position = readV3F1000(is);
2114                 // pitch
2115                 m_pitch = readF1000(is);
2116                 m_pitch = updateHeadPitch(m_pitch);
2117                 // yaw
2118                 m_yaw = readF1000(is);
2119
2120                 pos_translator.init(m_position);
2121                 old_pos_translator.init(m_old_position);
2122                 head_translator.init(v3f(m_pitch, 0, 0));
2123
2124                 Player *player = m_env->getPlayer(m_name.c_str());
2125                 if(player && player->isLocal()){
2126                         m_is_local_player = true;
2127                         m_local_player = (LocalPlayer*)player;
2128                 }
2129         }
2130
2131         ~PlayerCAO()
2132         {
2133                 if(m_body)
2134                         m_body->remove();
2135                 if(m_head)
2136                         m_head->remove();
2137                 if(m_leg_l)
2138                         m_leg_l->remove();
2139                 if(m_leg_r)
2140                         m_leg_r->remove();
2141                 if(m_arm_l)
2142                         m_arm_l->remove();
2143                 if(m_arm_r)
2144                         m_arm_r->remove();
2145         }
2146
2147         static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
2148         {
2149                 return new PlayerCAO(gamedef, env);
2150         }
2151
2152         u8 getType() const
2153         {
2154                 return ACTIVEOBJECT_TYPE_PLAYER;
2155         }
2156         core::aabbox3d<f32>* getSelectionBox()
2157         {
2158                 if(m_is_local_player)
2159                         return NULL;
2160                 return &m_selection_box;
2161         }
2162         v3f getPosition()
2163         {
2164                 return pos_translator.vect_show;
2165         }
2166                 
2167         void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
2168                         IrrlichtDevice *irr)
2169         {
2170                 if(m_body != NULL || m_head != NULL || m_leg_l != NULL || m_leg_r != NULL || m_arm_l != NULL || m_arm_r != NULL)
2171                         return;
2172                 if(m_is_local_player)
2173                         return;
2174                 
2175                 //video::IVideoDriver* driver = smgr->getVideoDriver();
2176                 gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
2177                 
2178                 { // Body
2179                 scene::SMesh *mesh = new scene::SMesh();
2180                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2181                 video::SColor c(255,255,255,255);
2182                 video::S3DVertex vertices[46] =
2183                 {
2184                         video::S3DVertex(1.125000, 0.750000, 2.125066, 1.000000, 0.000000, -0.000000,c, 0.815385, 0.714286),
2185                         video::S3DVertex(1.125001, 0.750000, 4.375066, 1.000000, 0.000000, -0.000000,c, 0.815385, 0.642857),
2186                         video::S3DVertex(1.125000, -0.750000, 2.125066, 1.000000, 0.000000, -0.000000,c, 0.769231, 0.714286),
2187                         video::S3DVertex(1.125001, 0.750000, 4.375066, 1.000000, -0.000001, 0.000000,c, 0.815385, 0.642857),
2188                         video::S3DVertex(1.124999, -0.750001, 4.375066, 1.000000, -0.000001, 0.000000,c, 0.769231, 0.642857),
2189                         video::S3DVertex(1.125000, -0.750000, 2.125066, 1.000000, -0.000001, 0.000000,c, 0.769231, 0.714286),
2190                         video::S3DVertex(1.125000, -0.750000, 2.125066, 0.000000, -1.000000, -0.000000,c, 0.753846, 0.714286),
2191                         video::S3DVertex(1.124999, -0.750001, 4.375066, 0.000000, -1.000000, -0.000000,c, 0.753846, 0.642857),
2192                         video::S3DVertex(-1.125000, -0.750000, 2.125066, 0.000000, -1.000000, -0.000000,c, 0.692308, 0.714286),
2193                         video::S3DVertex(1.124999, -0.750001, 4.375066, -0.000001, -1.000000, 0.000000,c, 0.753846, 0.642857),
2194                         video::S3DVertex(-1.125001, -0.749999, 4.375066, -0.000001, -1.000000, 0.000000,c, 0.692308, 0.642857),
2195                         video::S3DVertex(-1.125000, -0.750000, 2.125066, -0.000001, -1.000000, 0.000000,c, 0.692308, 0.714286),
2196                         video::S3DVertex(-1.125000, -0.750000, 2.125066, -1.000000, 0.000000, -0.000000,c, 0.876923, 0.714286),
2197                         video::S3DVertex(-1.125001, -0.749999, 4.375066, -1.000000, 0.000000, -0.000000,c, 0.876923, 0.642857),
2198                         video::S3DVertex(-1.125000, 0.750000, 4.375066, -1.000000, 0.000000, -0.000000,c, 0.830769, 0.642857),
2199                         video::S3DVertex(-1.125000, 0.750000, 2.125066, -1.000000, 0.000000, -0.000000,c, 0.830769, 0.714286),
2200                         video::S3DVertex(1.125001, 0.750000, 4.375066, 0.000000, 1.000000, 0.000000,c, 0.953846, 0.714286),
2201                         video::S3DVertex(1.125000, 0.750000, 2.125066, 0.000000, 1.000000, 0.000000,c, 0.953846, 0.642857),
2202                         video::S3DVertex(-1.125000, 0.750000, 2.125066, 0.000000, 1.000000, 0.000000,c, 0.892308, 0.642857),
2203                         video::S3DVertex(-1.125000, 0.750000, 4.375066, 0.000000, 1.000000, 0.000000,c, 0.892308, 0.714286),
2204                         video::S3DVertex(3.000002, 1.124999, 2.499885, 0.000000, 1.000000, 0.000000,c, 0.353846, 0.446429),
2205                         video::S3DVertex(3.000000, 1.125000, -5.000116, 0.000000, 1.000000, 0.000000,c, 0.353846, 0.714286),
2206                         video::S3DVertex(-2.999999, 1.125000, -5.000116, 0.000000, 1.000000, 0.000000,c, 0.507692, 0.714286),
2207                         video::S3DVertex(-3.000000, 1.124999, 2.499885, 0.000000, 1.000000, 0.000000,c, 0.507692, 0.446429),
2208                         video::S3DVertex(-3.000000, -1.125000, -5.000116, -1.000000, 0.000001, -0.000000,c, 0.338462, 0.714286),
2209                         video::S3DVertex(-3.000001, -1.124999, 2.499885, -1.000000, 0.000001, -0.000000,c, 0.338462, 0.446429),
2210                         video::S3DVertex(-3.000000, 1.124999, 2.499885, -1.000000, 0.000001, -0.000000,c, 0.261538, 0.446429),
2211                         video::S3DVertex(-2.999999, 1.125000, -5.000116, -1.000000, 0.000001, -0.000000,c, 0.261538, 0.714286),
2212                         video::S3DVertex(3.000000, -1.124999, -5.000116, 0.000000, -1.000000, -0.000000,c, 0.153846, 0.714286),
2213                         video::S3DVertex(2.999998, -1.125001, 2.499885, 0.000000, -1.000000, -0.000000,c, 0.153846, 0.446429),
2214                         video::S3DVertex(-3.000000, -1.125000, -5.000116, 0.000000, -1.000000, -0.000000,c, 0.000000, 0.714286),
2215                         video::S3DVertex(-3.000001, -1.124999, 2.499885, -0.000000, -1.000000, 0.000000,c, 0.000000, 0.446429),
2216                         video::S3DVertex(3.000000, 1.125000, -5.000116, 1.000000, -0.000000, -0.000000,c, 0.246154, 0.714286),
2217                         video::S3DVertex(3.000002, 1.124999, 2.499885, 1.000000, -0.000000, -0.000000,c, 0.246154, 0.446429),
2218                         video::S3DVertex(3.000000, -1.124999, -5.000116, 1.000000, -0.000000, -0.000000,c, 0.169231, 0.714286),
2219                         video::S3DVertex(3.000002, 1.124999, 2.499885, 1.000000, -0.000002, 0.000000,c, 0.246154, 0.446429),
2220                         video::S3DVertex(2.999998, -1.125001, 2.499885, 1.000000, -0.000002, 0.000000,c, 0.169231, 0.446429),
2221                         video::S3DVertex(3.000000, -1.124999, -5.000116, 1.000000, -0.000002, 0.000000,c, 0.169231, 0.714286),
2222                         video::S3DVertex(3.000002, 1.124999, 2.499885, -0.000000, -0.000000, 1.000000,c, 0.676923, 0.517857),
2223                         video::S3DVertex(-3.000000, 1.124999, 2.499885, -0.000000, -0.000000, 1.000000,c, 0.523077, 0.517857),
2224                         video::S3DVertex(2.999998, -1.125001, 2.499885, -0.000000, -0.000000, 1.000000,c, 0.676923, 0.607143),
2225                         video::S3DVertex(-3.000001, -1.124999, 2.499885, 0.000000, -0.000000, 1.000000,c, 0.523077, 0.607143),
2226                         video::S3DVertex(3.000000, 1.125000, -5.000116, 0.000000, 0.000000, -1.000000,c, 0.676923, 0.714286),
2227                         video::S3DVertex(3.000000, -1.124999, -5.000116, 0.000000, 0.000000, -1.000000,c, 0.676923, 0.625000),
2228                         video::S3DVertex(-2.999999, 1.125000, -5.000116, 0.000000, 0.000000, -1.000000,c, 0.523077, 0.714286),
2229                         video::S3DVertex(-3.000000, -1.125000, -5.000116, 0.000000, -0.000000, -1.000000,c, 0.523077, 0.625000),
2230                 };
2231                 u16 indices[] = {0, 1, 2, 
2232                                                 3, 4, 5, 
2233                                                 6, 7, 8, 
2234                                                 9, 10, 11, 
2235                                                 12, 13, 14, 
2236                                                 12, 14, 15, 
2237                                                 16, 17, 18, 
2238                                                 16, 18, 19, 
2239                                                 20, 21, 22, 
2240                                                 20, 22, 23, 
2241                                                 24, 25, 26, 
2242                                                 24, 26, 27, 
2243                                                 28, 29, 30, 
2244                                                 29, 31, 30, 
2245                                                 32, 33, 34, 
2246                                                 35, 36, 37, 
2247                                                 38, 39, 40, 
2248                                                 39, 41, 40, 
2249                                                 42, 43, 44, 
2250                                                 43, 45, 44};
2251                 buf->append(vertices, 46, indices, 60);
2252                 // Set material
2253                 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2254                 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2255                 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2256                 //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
2257                 // Add to mesh
2258                 mesh->addMeshBuffer(buf);
2259                 buf->drop();
2260                 
2261                 m_body = smgr->addMeshSceneNode(mesh, NULL);
2262                 m_body->setPosition(v3f(0,0,0));
2263                 m_body->setRotation(v3f(-90,0,0));
2264                 
2265                 // Set it to use the materials of the meshbuffers directly.
2266                 // This is needed for changing the texture in the future
2267                 m_body->setReadOnlyMaterials(true);
2268                 updateNodePos();
2269                 }
2270                 
2271                 { // Head
2272                 scene::SMesh *mesh = new scene::SMesh();
2273                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2274                 video::SColor c(255,255,255,255);
2275                 video::S3DVertex vertices[30] =
2276                 {
2277                         video::S3DVertex(2.250001, 1.499998, 3.774997, 0.000000, 1.000000, 0.000001,c, 0.353846, 0.000000),
2278                         video::S3DVertex(2.249999, 1.500000, 0.024998, 0.000000, 1.000000, 0.000001,c, 0.353846, 0.142857),
2279                         video::S3DVertex(-2.250000, 1.499999, 3.774997, 0.000000, 1.000000, 0.000001,c, 0.507638, -0.000000),
2280                         video::S3DVertex(2.249999, 1.500000, 0.024998, 0.000000, 1.000000, 0.000000,c, 0.353846, 0.142857),
2281                         video::S3DVertex(-2.250000, 1.500001, 0.024998, 0.000000, 1.000000, 0.000000,c, 0.507638, 0.142857),
2282                         video::S3DVertex(-2.250000, 1.499999, 3.774997, 0.000000, 1.000000, 0.000000,c, 0.507638, -0.000000),
2283                         video::S3DVertex(-2.250000, -1.500000, 0.024998, -1.000000, -0.000000, -0.000000,c, 0.338462, 0.142857),
2284                         video::S3DVertex(-2.250000, -1.499999, 3.774997, -1.000000, -0.000000, -0.000000,c, 0.338285, 0.000163),
2285                         video::S3DVertex(-2.250000, 1.499999, 3.774997, -1.000000, -0.000000, -0.000000,c, 0.261538, 0.000000),
2286                         video::S3DVertex(-2.250000, 1.500001, 0.024998, -1.000000, 0.000000, -0.000000,c, 0.261538, 0.142857),
2287                         video::S3DVertex(2.250001, -1.499999, 0.024998, 0.000000, -1.000000, -0.000001,c, 0.153846, 0.142857),
2288                         video::S3DVertex(2.249998, -1.500001, 3.774997, 0.000000, -1.000000, -0.000001,c, 0.153846, -0.000000),
2289                         video::S3DVertex(-2.250000, -1.500000, 0.024998, 0.000000, -1.000000, -0.000001,c, 0.000000, 0.142857),
2290                         video::S3DVertex(2.249998, -1.500001, 3.774997, -0.000001, -1.000000, 0.000000,c, 0.153846, -0.000000),
2291                         video::S3DVertex(-2.250000, -1.499999, 3.774997, -0.000001, -1.000000, 0.000000,c, 0.000000, 0.000000),
2292                         video::S3DVertex(-2.250000, -1.500000, 0.024998, -0.000001, -1.000000, 0.000000,c, 0.000000, 0.142857),
2293                         video::S3DVertex(2.249999, 1.500000, 0.024998, 1.000000, 0.000001, -0.000000,c, 0.246154, 0.142857),
2294                         video::S3DVertex(2.250001, 1.499998, 3.774997, 1.000000, 0.000001, -0.000000,c, 0.246154, 0.000000),
2295                         video::S3DVertex(2.250001, -1.499999, 0.024998, 1.000000, 0.000001, -0.000000,c, 0.169231, 0.142857),
2296                         video::S3DVertex(2.250001, 1.499998, 3.774997, 1.000000, -0.000001, 0.000001,c, 0.246154, 0.000000),
2297                         video::S3DVertex(2.249998, -1.500001, 3.774997, 1.000000, -0.000001, 0.000001,c, 0.169231, 0.000000),
2298                         video::S3DVertex(2.250001, -1.499999, 0.024998, 1.000000, -0.000001, 0.000001,c, 0.169231, 0.142857),
2299                         video::S3DVertex(2.250001, 1.499998, 3.774997, -0.000000, -0.000000, 1.000000,c, 0.523077, 0.142857),
2300                         video::S3DVertex(-2.250000, 1.499999, 3.774997, -0.000000, -0.000000, 1.000000,c, 0.676923, 0.142857),
2301                         video::S3DVertex(-2.250000, -1.499999, 3.774997, -0.000000, -0.000000, 1.000000,c, 0.676923, 0.053571),
2302                         video::S3DVertex(2.249998, -1.500001, 3.774997, 0.000000, -0.000000, 1.000000,c, 0.523077, 0.053571),
2303                         video::S3DVertex(2.249999, 1.500000, 0.024998, 0.000000, 0.000000, -1.000000,c, 0.692308, 0.053571),
2304                         video::S3DVertex(2.250001, -1.499999, 0.024998, 0.000000, 0.000000, -1.000000,c, 0.692308, 0.142857),
2305                         video::S3DVertex(-2.250000, -1.500000, 0.024998, 0.000000, 0.000000, -1.000000,c, 0.846154, 0.142857),
2306                         video::S3DVertex(-2.250000, 1.500001, 0.024998, 0.000000, 0.000000, -1.000000,c, 0.846154, 0.053571),
2307                 };
2308                 u16 indices[] = {0, 1, 2, 
2309                                                 3, 4, 5, 
2310                                                 6, 7, 8, 
2311                                                 6, 8, 9, 
2312                                                 10, 11, 12, 
2313                                                 13, 14, 15, 
2314                                                 16, 17, 18, 
2315                                                 19, 20, 21, 
2316                                                 22, 23, 24, 
2317                                                 22, 24, 25, 
2318                                                 26, 27, 28, 
2319                                                 26, 28, 29};
2320                 buf->append(vertices, 30, indices, 36);
2321                 // Set material
2322                 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2323                 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2324                 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2325                 //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
2326                 // Add to mesh
2327                 mesh->addMeshBuffer(buf);
2328                 buf->drop();
2329                 
2330                 m_head = smgr->addMeshSceneNode(mesh, NULL);
2331                 m_head->setPosition(v3f(0,0,0));
2332                 m_head->setRotation(v3f(-90,0,0));
2333                 
2334                 // Set it to use the materials of the meshbuffers directly.
2335                 // This is needed for changing the texture in the future
2336                 m_head->setReadOnlyMaterials(true);
2337                 updateNodePos();
2338                 }
2339                 
2340                 { // Leg-Left
2341                 scene::SMesh *mesh = new scene::SMesh();
2342                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2343                 video::SColor c(255,255,255,255);
2344                 video::S3DVertex vertices[28] =
2345                 {
2346                         video::S3DVertex(-0.144449, 1.124999, 0.224998, 0.000000, 1.000000, 0.000000,c, 0.292308, 0.732143),
2347                         video::S3DVertex(-0.144450, 1.125000, -8.025005, 0.000000, 1.000000, 0.000000,c, 0.292308, 1.000000),
2348                         video::S3DVertex(-2.995950, 1.125000, -8.025005, 0.000000, 1.000000, 0.000000,c, 0.384615, 1.000000),
2349                         video::S3DVertex(-2.995950, 1.125000, 0.224998, 0.000000, 1.000000, 0.000000,c, 0.384615, 0.732143),
2350                         video::S3DVertex(-2.995950, -1.125000, -8.025005, -1.000000, 0.000000, -0.000000,c, 0.276923, 1.000000),
2351                         video::S3DVertex(-2.995950, -1.124999, 0.224998, -1.000000, 0.000000, -0.000000,c, 0.276923, 0.732143),
2352                         video::S3DVertex(-2.995950, 1.125000, -8.025005, -1.000000, 0.000000, -0.000000,c, 0.200000, 1.000000),
2353                         video::S3DVertex(-2.995950, 1.125000, 0.224998, -1.000000, 0.000000, -0.000000,c, 0.200000, 0.732143),
2354                         video::S3DVertex(-0.144450, -1.125000, -8.025005, -0.000001, -1.000000, -0.000000,c, 0.092308, 1.000000),
2355                         video::S3DVertex(-0.144451, -1.125001, 0.224998, -0.000001, -1.000000, -0.000000,c, 0.092308, 0.732143),
2356                         video::S3DVertex(-2.995950, -1.124999, 0.224998, -0.000001, -1.000000, -0.000000,c, 0.000000, 0.732143),
2357                         video::S3DVertex(-0.144450, -1.125000, -8.025005, -0.000000, -1.000000, 0.000000,c, 0.092308, 1.000000),
2358                         video::S3DVertex(-2.995950, -1.124999, 0.224998, -0.000000, -1.000000, 0.000000,c, 0.000000, 0.732143),
2359                         video::S3DVertex(-2.995950, -1.125000, -8.025005, -0.000000, -1.000000, 0.000000,c, 0.000000, 1.000000),
2360                         video::S3DVertex(-0.144450, 1.125000, -8.025005, 1.000000, -0.000000, -0.000000,c, 0.184615, 1.000000),
2361                         video::S3DVertex(-0.144449, 1.124999, 0.224998, 1.000000, -0.000000, -0.000000,c, 0.184615, 0.732143),
2362                         video::S3DVertex(-0.144450, -1.125000, -8.025005, 1.000000, -0.000000, -0.000000,c, 0.107692, 1.000000),
2363                         video::S3DVertex(-0.144449, 1.124999, 0.224998, 1.000000, -0.000001, 0.000000,c, 0.184615, 0.732143),
2364                         video::S3DVertex(-0.144451, -1.125001, 0.224998, 1.000000, -0.000001, 0.000000,c, 0.107692, 0.732143),
2365                         video::S3DVertex(-0.144450, -1.125000, -8.025005, 1.000000, -0.000001, 0.000000,c, 0.107692, 1.000000),
2366                         video::S3DVertex(-0.144449, 1.124999, 0.224998, -0.000000, 0.000000, 1.000000,c, 0.400000, 0.892857),
2367                         video::S3DVertex(-2.995950, 1.125000, 0.224998, -0.000000, 0.000000, 1.000000,c, 0.492308, 0.892857),
2368                         video::S3DVertex(-2.995950, -1.124999, 0.224998, -0.000000, 0.000000, 1.000000,c, 0.492308, 0.803656),
2369                         video::S3DVertex(-0.144451, -1.125001, 0.224998, 0.000000, -0.000000, 1.000000,c, 0.400000, 0.803656),
2370                         video::S3DVertex(-0.144450, 1.125000, -8.025005, 0.000000, 0.000000, -1.000000,c, 0.400000, 1.000000),
2371                         video::S3DVertex(-0.144450, -1.125000, -8.025005, 0.000000, 0.000000, -1.000000,c, 0.492308, 1.000000),
2372                         video::S3DVertex(-2.995950, -1.125000, -8.025005, 0.000000, 0.000000, -1.000000,c, 0.492308, 0.910714),
2373                         video::S3DVertex(-2.995950, 1.125000, -8.025005, 0.000000, -0.000000, -1.000000,c, 0.400000, 0.910714),
2374                 };
2375                 u16 indices[] = {0, 1, 2, 
2376                                                 0, 2, 3, 
2377                                                 4, 5, 6, 
2378                                                 5, 7, 6, 
2379                                                 8, 9, 10, 
2380                                                 11, 12, 13, 
2381                                                 14, 15, 16, 
2382                                                 17, 18, 19, 
2383                                                 20, 21, 22, 
2384                                                 20, 22, 23, 
2385                                                 24, 25, 26, 
2386                                                 24, 26, 27};
2387                 buf->append(vertices, 28, indices, 36);
2388                 // Set material
2389                 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2390                 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2391                 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2392                 //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
2393                 // Add to mesh
2394                 mesh->addMeshBuffer(buf);
2395                 buf->drop();
2396                 
2397                 m_leg_l = smgr->addMeshSceneNode(mesh, NULL);
2398                 m_leg_l->setPosition(v3f(0,0,0));
2399                 m_leg_l->setRotation(v3f(-90,0,0));
2400                 
2401                 // Set it to use the materials of the meshbuffers directly.
2402                 // This is needed for changing the texture in the future
2403                 m_leg_l->setReadOnlyMaterials(true);
2404                 updateNodePos();
2405                 }
2406                 
2407                 { // Leg-Right
2408                 scene::SMesh *mesh = new scene::SMesh();
2409                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2410                 video::SColor c(255,255,255,255);
2411                 video::S3DVertex vertices[28] =
2412                 {
2413                         video::S3DVertex(2.995751, 1.124999, 0.224998, 0.000000, 1.000000, 0.000000,c, 0.615385, 0.732143),
2414                         video::S3DVertex(2.995750, 1.125000, -8.025005, 0.000000, 1.000000, 0.000000,c, 0.615385, 1.000000),
2415                         video::S3DVertex(0.144250, 1.125000, -8.025005, 0.000000, 1.000000, 0.000000,c, 0.707692, 1.000000),
2416                         video::S3DVertex(0.144250, 1.125000, 0.224998, 0.000000, 1.000000, 0.000000,c, 0.707692, 0.732143),
2417                         video::S3DVertex(0.144249, -1.125000, -8.025005, -1.000000, 0.000000, -0.000000,c, 0.892308, 1.000000),
2418                         video::S3DVertex(0.144249, -1.124999, 0.224998, -1.000000, 0.000000, -0.000000,c, 0.892308, 0.732143),
2419                         video::S3DVertex(0.144250, 1.125000, -8.025005, -1.000000, 0.000000, -0.000000,c, 0.815385, 1.000000),
2420                         video::S3DVertex(0.144250, 1.125000, 0.224998, -1.000000, 0.000000, -0.000000,c, 0.815385, 0.732143),
2421                         video::S3DVertex(2.995750, -1.125000, -8.025005, -0.000001, -1.000000, -0.000000,c, 1.000000, 1.000000),
2422                         video::S3DVertex(2.995749, -1.125001, 0.224998, -0.000001, -1.000000, -0.000000,c, 1.000000, 0.732143),
2423                         video::S3DVertex(0.144249, -1.124999, 0.224998, -0.000001, -1.000000, -0.000000,c, 0.907692, 0.732143),
2424                         video::S3DVertex(2.995750, -1.125000, -8.025005, -0.000000, -1.000000, 0.000000,c, 1.000000, 1.000000),
2425                         video::S3DVertex(0.144249, -1.124999, 0.224998, -0.000000, -1.000000, 0.000000,c, 0.907692, 0.732143),
2426                         video::S3DVertex(0.144249, -1.125000, -8.025005, -0.000000, -1.000000, 0.000000,c, 0.907692, 1.000000),
2427                         video::S3DVertex(2.995750, 1.125000, -8.025005, 1.000000, 0.000000, -0.000000,c, 0.800022, 1.000000),
2428                         video::S3DVertex(2.995751, 1.124999, 0.224998, 1.000000, 0.000000, -0.000000,c, 0.800000, 0.732143),
2429                         video::S3DVertex(2.995750, -1.125000, -8.025005, 1.000000, 0.000000, -0.000000,c, 0.723055, 1.000000),
2430                         video::S3DVertex(2.995751, 1.124999, 0.224998, 1.000000, -0.000001, 0.000000,c, 0.800000, 0.732143),
2431                         video::S3DVertex(2.995749, -1.125001, 0.224998, 1.000000, -0.000001, 0.000000,c, 0.723055, 0.732143),
2432                         video::S3DVertex(2.995750, -1.125000, -8.025005, 1.000000, -0.000001, 0.000000,c, 0.723055, 1.000000),
2433                         video::S3DVertex(2.995751, 1.124999, 0.224998, -0.000000, 0.000000, 1.000000,c, 0.600000, 0.803571),
2434                         video::S3DVertex(0.144250, 1.125000, 0.224998, -0.000000, 0.000000, 1.000000,c, 0.507692, 0.803571),
2435                         video::S3DVertex(0.144249, -1.124999, 0.224998, -0.000000, 0.000000, 1.000000,c, 0.507692, 0.892857),
2436                         video::S3DVertex(2.995749, -1.125001, 0.224998, 0.000000, -0.000000, 1.000000,c, 0.600000, 0.892857),
2437                         video::S3DVertex(2.995750, 1.125000, -8.025005, 0.000000, 0.000000, -1.000000,c, 0.600000, 0.910714),
2438                         video::S3DVertex(2.995750, -1.125000, -8.025005, 0.000000, 0.000000, -1.000000,c, 0.507659, 0.910714),
2439                         video::S3DVertex(0.144249, -1.125000, -8.025005, 0.000000, 0.000000, -1.000000,c, 0.507659, 1.000000),
2440                         video::S3DVertex(0.144250, 1.125000, -8.025005, 0.000000, -0.000000, -1.000000,c, 0.600000, 1.000000),
2441                 };
2442                 u16 indices[] = {0, 1, 2, 
2443                                                 0, 2, 3, 
2444                                                 4, 5, 6, 
2445                                                 5, 7, 6, 
2446                                                 8, 9, 10, 
2447                                                 11, 12, 13, 
2448                                                 14, 15, 16, 
2449                                                 17, 18, 19, 
2450                                                 20, 21, 22, 
2451                                                 20, 22, 23, 
2452                                                 24, 25, 26, 
2453                                                 24, 26, 27};
2454                 buf->append(vertices, 28, indices, 36);
2455                 // Set material
2456                 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2457                 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2458                 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2459                 //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
2460                 // Add to mesh
2461                 mesh->addMeshBuffer(buf);
2462                 buf->drop();
2463                 
2464                 m_leg_r = smgr->addMeshSceneNode(mesh, NULL);
2465                 m_leg_r->setPosition(v3f(0,0,0));
2466                 m_leg_r->setRotation(v3f(-90,0,0));
2467                 
2468                 // Set it to use the materials of the meshbuffers directly.
2469                 // This is needed for changing the texture in the future
2470                 m_leg_r->setReadOnlyMaterials(true);
2471                 updateNodePos();
2472                 }
2473                 
2474                 { // Arm-Left
2475                 scene::SMesh *mesh = new scene::SMesh();
2476                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2477                 video::SColor c(255,255,255,255);
2478                 video::S3DVertex vertices[28] =
2479                 {
2480                         video::S3DVertex(-3.049999, 1.124999, 0.300000, 0.000000, 1.000000, 0.000000,c, 0.261538, 0.160714),
2481                         video::S3DVertex(-3.049999, 1.125000, -7.200000, 0.000000, 1.000000, 0.000000,c, 0.261538, 0.428571),
2482                         video::S3DVertex(-4.849999, 1.125001, -7.200000, 0.000000, 1.000000, 0.000000,c, 0.323077, 0.428644),
2483                         video::S3DVertex(-3.049999, 1.124999, 0.300000, 0.000001, 1.000000, 0.000000,c, 0.261538, 0.160714),
2484                         video::S3DVertex(-4.849999, 1.125001, -7.200000, 0.000001, 1.000000, 0.000000,c, 0.323077, 0.428644),
2485                         video::S3DVertex(-4.849999, 1.125000, 0.300000, 0.000001, 1.000000, 0.000000,c, 0.323077, 0.160714),
2486                         video::S3DVertex(-4.849999, -1.125000, -7.200000, -1.000000, 0.000000, -0.000000,c, 0.246154, 0.428571),
2487                         video::S3DVertex(-4.850000, -1.124999, 0.300000, -1.000000, 0.000000, -0.000000,c, 0.246154, 0.160714),
2488                         video::S3DVertex(-4.849999, 1.125001, -7.200000, -1.000000, 0.000000, -0.000000,c, 0.169231, 0.428571),
2489                         video::S3DVertex(-4.849999, 1.125000, 0.300000, -1.000000, 0.000000, 0.000000,c, 0.169231, 0.160714),
2490                         video::S3DVertex(-3.049999, -1.125000, -7.200000, -0.000001, -1.000000, -0.000000,c, 0.061538, 0.428571),
2491                         video::S3DVertex(-3.050000, -1.125001, 0.300000, -0.000001, -1.000000, -0.000000,c, 0.061538, 0.160714),
2492                         video::S3DVertex(-4.850000, -1.124999, 0.300000, -0.000001, -1.000000, -0.000000,c, 0.000000, 0.160714),
2493                         video::S3DVertex(-3.049999, -1.125000, -7.200000, -0.000000, -1.000000, 0.000000,c, 0.061538, 0.428571),
2494                         video::S3DVertex(-4.850000, -1.124999, 0.300000, -0.000000, -1.000000, 0.000000,c, 0.000000, 0.160714),
2495                         video::S3DVertex(-4.849999, -1.125000, -7.200000, -0.000000, -1.000000, 0.000000,c, 0.000000, 0.428571),
2496                         video::S3DVertex(-3.049999, 1.125000, -7.200000, 1.000000, -0.000000, 0.000000,c, 0.153846, 0.428571),
2497                         video::S3DVertex(-3.049999, 1.124999, 0.300000, 1.000000, -0.000000, 0.000000,c, 0.153846, 0.160714),
2498                         video::S3DVertex(-3.049999, -1.125000, -7.200000, 1.000000, -0.000000, 0.000000,c, 0.076923, 0.428571),
2499                         video::S3DVertex(-3.050000, -1.125001, 0.300000, 1.000000, -0.000000, 0.000000,c, 0.076923, 0.160714),
2500                         video::S3DVertex(-3.049999, 1.124999, 0.300000, -0.000000, 0.000000, 1.000000,c, 0.400000, 0.232143),
2501                         video::S3DVertex(-4.849999, 1.125000, 0.300000, -0.000000, 0.000000, 1.000000,c, 0.338462, 0.232143),
2502                         video::S3DVertex(-4.850000, -1.124999, 0.300000, -0.000000, 0.000000, 1.000000,c, 0.338462, 0.321429),
2503                         video::S3DVertex(-3.050000, -1.125001, 0.300000, 0.000000, -0.000000, 1.000000,c, 0.400000, 0.321429),
2504                         video::S3DVertex(-3.049999, 1.125000, -7.200000, 0.000000, 0.000000, -1.000000,c, 0.400000, 0.428571),
2505                         video::S3DVertex(-3.049999, -1.125000, -7.200000, 0.000000, 0.000000, -1.000000,c, 0.400000, 0.339286),
2506                         video::S3DVertex(-4.849999, -1.125000, -7.200000, 0.000000, 0.000000, -1.000000,c, 0.338462, 0.339286),
2507                         video::S3DVertex(-4.849999, 1.125001, -7.200000, 0.000000, 0.000000, -1.000000,c, 0.338462, 0.428571),
2508                 };
2509                 u16 indices[] = {0, 1, 2, 
2510                                                 3, 4, 5, 
2511                                                 6, 7, 8, 
2512                                                 7, 9, 8, 
2513                                                 10, 11, 12, 
2514                                                 13, 14, 15, 
2515                                                 16, 17, 18, 
2516                                                 17, 19, 18, 
2517                                                 20, 21, 22, 
2518                                                 20, 22, 23, 
2519                                                 24, 25, 26, 
2520                                                 24, 26, 27};
2521                 buf->append(vertices, 28, indices, 36);
2522                 // Set material
2523                 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2524                 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2525                 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2526                 //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
2527                 // Add to mesh
2528                 mesh->addMeshBuffer(buf);
2529                 buf->drop();
2530                 
2531                 m_arm_l = smgr->addMeshSceneNode(mesh, NULL);
2532                 m_arm_l->setPosition(v3f(0,0,0));
2533                 m_arm_l->setRotation(v3f(-90,0,0));
2534                 
2535                 // Set it to use the materials of the meshbuffers directly.
2536                 // This is needed for changing the texture in the future
2537                 m_arm_l->setReadOnlyMaterials(true);
2538                 updateNodePos();
2539                 }
2540                 
2541                 { // Arm-Right
2542                 scene::SMesh *mesh = new scene::SMesh();
2543                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2544                 video::SColor c(255,255,255,255);
2545                 video::S3DVertex vertices[28] =
2546                 {
2547                         video::S3DVertex(4.850001, 1.124999, 0.300000, 0.000000, 1.000000, 0.000000,c, 0.753846, 0.160714),
2548                         video::S3DVertex(4.850000, 1.125000, -7.200000, 0.000000, 1.000000, 0.000000,c, 0.753846, 0.428571),
2549                         video::S3DVertex(3.050001, 1.125000, -7.200000, 0.000000, 1.000000, 0.000000,c, 0.815385, 0.428571),
2550                         video::S3DVertex(4.850001, 1.124999, 0.300000, 0.000001, 1.000000, 0.000000,c, 0.753846, 0.160714),
2551                         video::S3DVertex(3.050001, 1.125000, -7.200000, 0.000001, 1.000000, 0.000000,c, 0.815385, 0.428571),
2552                         video::S3DVertex(3.050001, 1.125000, 0.300000, 0.000001, 1.000000, 0.000000,c, 0.815385, 0.160714),
2553                         video::S3DVertex(3.050000, -1.125000, -7.200000, -1.000000, 0.000000, -0.000000,c, 0.738462, 0.428571),
2554                         video::S3DVertex(3.050000, -1.124999, 0.300000, -1.000000, 0.000000, -0.000000,c, 0.738462, 0.160714),
2555                         video::S3DVertex(3.050001, 1.125000, -7.200000, -1.000000, 0.000000, -0.000000,c, 0.661538, 0.428571),
2556                         video::S3DVertex(3.050001, 1.125000, 0.300000, -1.000000, 0.000000, 0.000000,c, 0.661538, 0.160714),
2557                         video::S3DVertex(4.850000, -1.125000, -7.200000, -0.000001, -1.000000, -0.000000,c, 0.553846, 0.428571),
2558                         video::S3DVertex(4.850000, -1.125001, 0.300000, -0.000001, -1.000000, -0.000000,c, 0.553846, 0.160714),
2559                         video::S3DVertex(3.050000, -1.124999, 0.300000, -0.000001, -1.000000, -0.000000,c, 0.492308, 0.160714),
2560                         video::S3DVertex(4.850000, -1.125000, -7.200000, -0.000000, -1.000000, 0.000000,c, 0.553846, 0.428571),
2561                         video::S3DVertex(3.050000, -1.124999, 0.300000, -0.000000, -1.000000, 0.000000,c, 0.492308, 0.160714),
2562                         video::S3DVertex(3.050000, -1.125000, -7.200000, -0.000000, -1.000000, 0.000000,c, 0.492308, 0.428571),
2563                         video::S3DVertex(4.850000, 1.125000, -7.200000, 1.000000, 0.000000, -0.000000,c, 0.646154, 0.428571),
2564                         video::S3DVertex(4.850001, 1.124999, 0.300000, 1.000000, 0.000000, -0.000000,c, 0.646154, 0.160714),
2565                         video::S3DVertex(4.850000, -1.125000, -7.200000, 1.000000, 0.000000, -0.000000,c, 0.569231, 0.428571),
2566                         video::S3DVertex(4.850000, -1.125001, 0.300000, 1.000000, -0.000000, 0.000000,c, 0.569279, 0.160714),
2567                         video::S3DVertex(4.850001, 1.124999, 0.300000, -0.000000, 0.000000, 1.000000,c, 0.415385, 0.321429),
2568                         video::S3DVertex(3.050001, 1.125000, 0.300000, -0.000000, 0.000000, 1.000000,c, 0.476923, 0.321429),
2569                         video::S3DVertex(3.050000, -1.124999, 0.300000, -0.000000, 0.000000, 1.000000,c, 0.476923, 0.232143),
2570                         video::S3DVertex(4.850000, -1.125001, 0.300000, 0.000000, -0.000000, 1.000000,c, 0.415385, 0.232143),
2571                         video::S3DVertex(4.850000, 1.125000, -7.200000, 0.000000, 0.000000, -1.000000,c, 0.415385, 0.339286),
2572                         video::S3DVertex(4.850000, -1.125000, -7.200000, 0.000000, 0.000000, -1.000000,c, 0.415385, 0.428571),
2573                         video::S3DVertex(3.050000, -1.125000, -7.200000, 0.000000, 0.000000, -1.000000,c, 0.476923, 0.428571),
2574                         video::S3DVertex(3.050001, 1.125000, -7.200000, 0.000000, -0.000000, -1.000000,c, 0.476923, 0.339286),
2575                 };
2576                 u16 indices[] = {0, 1, 2, 
2577                                                 3, 4, 5, 
2578                                                 6, 7, 8, 
2579                                                 7, 9, 8, 
2580                                                 10, 11, 12, 
2581                                                 13, 14, 15, 
2582                                                 16, 17, 18, 
2583                                                 17, 19, 18, 
2584                                                 20, 21, 22, 
2585                                                 20, 22, 23, 
2586                                                 24, 25, 26, 
2587                                                 24, 26, 27};
2588                 buf->append(vertices, 28, indices, 36);
2589                 // Set material
2590                 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2591                 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2592                 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2593                 //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
2594                 // Add to mesh
2595                 mesh->addMeshBuffer(buf);
2596                 buf->drop();
2597                 
2598                 m_arm_r = smgr->addMeshSceneNode(mesh, NULL);
2599                 m_arm_r->setPosition(v3f(0,0,0));
2600                 m_arm_r->setRotation(v3f(-90,0,0));
2601                 
2602                 // Set it to use the materials of the meshbuffers directly.
2603                 // This is needed for changing the texture in the future
2604                 m_arm_r->setReadOnlyMaterials(true);
2605                 updateNodePos();
2606                 }
2607
2608                 // Add a text node for showing the name
2609                 std::wstring wname = narrow_to_wide(m_name);
2610                 m_text = smgr->addTextSceneNode(gui->getBuiltInFont(),
2611                                 wname.c_str(), video::SColor(255,255,255,255), m_head);
2612                 m_text->setPosition(v3f(0, 0, 5));
2613                 
2614                 updateTextures("");
2615                 //updateLegRot(dtime);
2616                 updateNodePos();
2617         }
2618
2619         void removeFromScene()
2620         {
2621                 if (m_body != NULL) {
2622                         m_body->remove();
2623                         m_body = NULL;
2624                 }
2625                 if (m_head != NULL) {
2626                         m_head->remove();
2627                         m_head = NULL;
2628                 }
2629                 if (m_leg_l != NULL) {
2630                         m_leg_l->remove();
2631                         m_leg_l = NULL;
2632                 }
2633                 if (m_leg_r != NULL) {
2634                         m_leg_r->remove();
2635                         m_leg_r = NULL;
2636                 }
2637                 if (m_arm_l != NULL) {
2638                         m_arm_l->remove();
2639                         m_arm_l = NULL;
2640                 }
2641                 if (m_arm_r != NULL) {
2642                         m_arm_r->remove();
2643                         m_arm_r = NULL;
2644                 }
2645         }
2646
2647         void updateLight(u8 light_at_pos)
2648         {
2649                 u8 li = decode_light(light_at_pos);
2650                 video::SColor color(255,li,li,li);
2651                 
2652                 if (m_body != NULL) {
2653                         m_body->setVisible(true);
2654                         setMeshColor(m_body->getMesh(), color);
2655                 }
2656                 
2657                 if (m_head != NULL) {
2658                         m_head->setVisible(true);
2659                         setMeshColor(m_head->getMesh(), color);
2660                 }
2661                 
2662                 if (m_leg_l != NULL) {
2663                         m_leg_l->setVisible(true);
2664                         setMeshColor(m_leg_l->getMesh(), color);
2665                 }
2666                 
2667                 if (m_leg_r != NULL) {
2668                         m_leg_r->setVisible(true);
2669                         setMeshColor(m_leg_r->getMesh(), color);
2670                 }
2671                 
2672                 if (m_arm_l != NULL) {
2673                         m_arm_l->setVisible(true);
2674                         setMeshColor(m_arm_l->getMesh(), color);
2675                 }
2676                 
2677                 if (m_arm_r != NULL) {
2678                         m_arm_r->setVisible(true);
2679                         setMeshColor(m_arm_r->getMesh(), color);
2680                 }
2681         }
2682
2683         v3s16 getLightPosition()
2684         {
2685                 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
2686         }
2687         
2688         float updateHeadPitch(float pitch) {
2689                 if (pitch > 75) {
2690                         return 75-90;
2691                 }
2692                 else if (pitch < -75) {
2693                         return -75-90;
2694                 }
2695                 else {
2696                         return pitch-90;
2697                 }
2698                 return false;
2699         }
2700         
2701         void updateLegRot(float dtime) {
2702                 v3f real_pos = pos_translator.vect_show;
2703                 v3f real_old_pos = old_pos_translator.vect_show;
2704                 
2705                 m_speed = (real_pos.X-real_old_pos.X+real_pos.Z-real_old_pos.Z)/2;
2706                 if (m_speed < 0) {
2707                         m_speed = -m_speed;
2708                 }
2709                 
2710                 if (m_speed > 0.5) {
2711                         m_leg_rot = sin(m_leg_rot_i)*25;
2712                         m_leg_rot_i += (m_speed*2.5)*dtime;
2713                 }
2714                 else {
2715                         if (m_leg_rot > 0) {
2716                                 if (m_leg_rot-(50.0*dtime) < 0) {
2717                                         m_leg_rot = 0;
2718                                 }
2719                                 else {
2720                                         m_leg_rot -= 50.0*dtime;
2721                                         m_leg_rot_i = 0;
2722                                 }
2723                         }
2724                         else if (m_leg_rot < 0) {
2725                                 if (m_leg_rot+(50.0*dtime) > 0) {
2726                                         m_leg_rot = 0;
2727                                 }
2728                                 else {
2729                                         m_leg_rot += 50.0*dtime;
2730                                         m_leg_rot_i = 0;
2731                                 }
2732                         }
2733                 }
2734         }
2735
2736         void updateNodePos()
2737         {
2738                 v3f real_pos = pos_translator.vect_show;
2739                 v3f real_old_pos = old_pos_translator.vect_show;
2740                 v3f head_pitch = head_translator.vect_show;
2741                 
2742                 if (m_body != NULL) {
2743                         v3f rot = m_body->getRotation();
2744                         rot.Y = -m_yaw;
2745                         m_body->setPosition(v3f(real_pos.X+0, real_pos.Y+13.3, real_pos.Z+0));
2746                         m_body->setRotation(rot);
2747                 }
2748                 
2749                 if (m_head != NULL) {
2750                         v3f rot = m_head->getRotation();
2751                         rot.Y = -m_yaw;
2752                         rot.X = head_pitch.X;
2753
2754                         m_head->setPosition(v3f(real_pos.X+0, real_pos.Y+16.2, real_pos.Z+0));
2755                         m_head->setRotation(rot);
2756                 }
2757                 
2758                 if (m_leg_l != NULL) {
2759                         v3f rot = m_leg_l->getRotation();
2760                         rot.Y = -m_yaw;
2761                         rot.X = m_leg_rot-90;
2762                         
2763                         m_leg_l->setPosition(v3f(real_pos.X+0, real_pos.Y+8.03, real_pos.Z+0));
2764                         m_leg_l->setRotation(rot);
2765                 }
2766                 if (m_leg_r != NULL) {
2767                         v3f rot = m_leg_r->getRotation();
2768                         rot.Y = -m_yaw;
2769                         rot.X = -m_leg_rot-90;
2770                         
2771                         m_leg_r->setPosition(v3f(real_pos.X+0, real_pos.Y+8.03, real_pos.Z+0));
2772                         m_leg_r->setRotation(rot);
2773                 }
2774                 
2775                 if (m_arm_l != NULL) {
2776                         v3f rot = m_arm_l->getRotation();
2777                         rot.Y = -m_yaw;
2778                         rot.X = -m_leg_rot-90;
2779                         
2780                         m_arm_l->setPosition(v3f(real_pos.X+0, real_pos.Y+15.5, real_pos.Z+0));
2781                         m_arm_l->setRotation(rot);
2782                 }
2783                 if (m_arm_r != NULL) {
2784                         v3f rot = m_arm_r->getRotation();
2785                         rot.Y = -m_yaw;
2786                         rot.X = m_leg_rot-90;
2787                         
2788                         m_arm_r->setPosition(v3f(real_pos.X+0, real_pos.Y+15.5, real_pos.Z+0));
2789                         m_arm_r->setRotation(rot);
2790                 }
2791         }
2792
2793         void step(float dtime, ClientEnvironment *env)
2794         {
2795                 pos_translator.translate(dtime);
2796                 old_pos_translator.translate(dtime);
2797                 head_translator.translate(dtime);
2798                 updateLegRot(dtime);
2799                 updateNodePos();
2800
2801                 if(m_damage_visual_timer > 0){
2802                         m_damage_visual_timer -= dtime;
2803                         if(m_damage_visual_timer <= 0){
2804                                 updateTextures("");
2805                         }
2806                 }
2807         }
2808
2809         void processMessage(const std::string &data)
2810         {
2811                 //infostream<<"PlayerCAO: Got message"<<std::endl;
2812                 std::istringstream is(data, std::ios::binary);
2813                 // command
2814                 u8 cmd = readU8(is);
2815                 if(cmd == 0) // update position
2816                 {
2817                         // pos
2818                         m_old_position = m_position; //old position
2819                         m_position = readV3F1000(is);
2820                         // pitch
2821                         m_pitch = readF1000(is);
2822                         m_pitch = updateHeadPitch(m_pitch);
2823                         // yaw
2824                         m_yaw = readF1000(is);
2825
2826                         pos_translator.update(m_position, false);
2827                         old_pos_translator.update(m_old_position);
2828                         head_translator.update(v3f(m_pitch, 0, 0));
2829                         
2830                         //updateLegRot(dtime);
2831                         updateNodePos();
2832                 }
2833                 else if(cmd == 1) // punched
2834                 {
2835                         // damage
2836                         s16 damage = readS16(is);
2837                         
2838                         if(m_is_local_player)
2839                                 m_env->damageLocalPlayer(damage, false);
2840                         
2841                         m_damage_visual_timer = 0.5;
2842                         updateTextures("^[brighten");
2843                 }
2844         }
2845
2846         void updateTextures(const std::string &mod)
2847         {
2848                 ITextureSource *tsrc = m_gamedef->tsrc();
2849                 if(m_body) {
2850                         scene::IMesh *mesh = m_body->getMesh();
2851                         if(mesh){
2852                                 {
2853                                         std::string tname = "mt_player.png";
2854                                         tname += mod;
2855                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
2856                                         buf->getMaterial().setTexture(0,
2857                                                         tsrc->getTextureRaw(tname));
2858                                 }
2859                         }
2860                 }
2861                 
2862                 if(m_head) {
2863                         scene::IMesh *mesh = m_head->getMesh();
2864                         if(mesh){
2865                                 {
2866                                         std::string tname = "mt_player.png";
2867                                         tname += mod;
2868                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
2869                                         buf->getMaterial().setTexture(0,
2870                                                         tsrc->getTextureRaw(tname));
2871                                 }
2872                         }
2873                 }
2874                 
2875                 if(m_leg_l) {
2876                         scene::IMesh *mesh = m_leg_l->getMesh();
2877                         if(mesh){
2878                                 {
2879                                         std::string tname = "mt_player.png";
2880                                         tname += mod;
2881                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
2882                                         buf->getMaterial().setTexture(0,
2883                                                         tsrc->getTextureRaw(tname));
2884                                 }
2885                         }
2886                 }
2887                 
2888                 if(m_leg_r) {
2889                         scene::IMesh *mesh = m_leg_r->getMesh();
2890                         if(mesh){
2891                                 {
2892                                         std::string tname = "mt_player.png";
2893                                         tname += mod;
2894                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
2895                                         buf->getMaterial().setTexture(0,
2896                                                         tsrc->getTextureRaw(tname));
2897                                 }
2898                         }
2899                 }
2900                 
2901                 if(m_arm_l) {
2902                         scene::IMesh *mesh = m_arm_l->getMesh();
2903                         if(mesh){
2904                                 {
2905                                         std::string tname = "mt_player.png";
2906                                         tname += mod;
2907                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
2908                                         buf->getMaterial().setTexture(0,
2909                                                         tsrc->getTextureRaw(tname));
2910                                 }
2911                         }
2912                 }
2913                 
2914                 if(m_arm_r) {
2915                         scene::IMesh *mesh = m_arm_r->getMesh();
2916                         if(mesh){
2917                                 {
2918                                         std::string tname = "mt_player.png";
2919                                         tname += mod;
2920                                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
2921                                         buf->getMaterial().setTexture(0,
2922                                                         tsrc->getTextureRaw(tname));
2923                                 }
2924                         }
2925                 }
2926         }
2927 };
2928
2929 // Prototype
2930 PlayerCAO proto_PlayerCAO(NULL, NULL);