3 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
20 #include "content_cao.h"
22 #include "environment.h"
23 #include "collision.h"
25 #include <ICameraSceneNode.h>
26 #include <ITextSceneNode.h>
27 #include <IBillboardSceneNode.h>
28 #include "serialization.h" // For decompressZlib
30 #include "clientobject.h"
31 #include "content_object.h"
33 #include "utility.h" // For IntervalLimiter
37 struct ToolCapabilities;
39 core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
45 struct SmoothTranslator
52 f32 anim_time_counter;
72 anim_time_counter = 0;
81 void update(v3f vect_new, bool is_end_position=false, float update_interval=-1)
83 aim_is_end = is_end_position;
86 if(update_interval > 0){
87 anim_time = update_interval;
89 if(anim_time < 0.001 || anim_time > 1.0)
90 anim_time = anim_time_counter;
92 anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
94 anim_time_counter = 0;
98 void translate(f32 dtime)
100 anim_time_counter = anim_time_counter + dtime;
101 anim_counter = anim_counter + dtime;
102 v3f vect_move = vect_aim - vect_old;
104 if(anim_time > 0.001)
105 moveratio = anim_time_counter / anim_time;
106 // Move a bit less than should, to avoid oscillation
107 moveratio = moveratio * 0.8;
108 float move_end = 1.5;
111 if(moveratio > move_end)
112 moveratio = move_end;
113 vect_show = vect_old + vect_move * moveratio;
118 return ((anim_time_counter / anim_time) < 1.4);
126 static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill,
127 float txs, float tys, int col, int row)
129 video::SMaterial& material = bill->getMaterial(0);
130 core::matrix4& matrix = material.getTextureMatrix(0);
131 matrix.setTextureTranslate(txs*col, tys*row);
132 matrix.setTextureScale(txs, tys);
139 class TestCAO : public ClientActiveObject
142 TestCAO(IGameDef *gamedef, ClientEnvironment *env);
147 return ACTIVEOBJECT_TYPE_TEST;
150 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
152 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
153 IrrlichtDevice *irr);
154 void removeFromScene();
155 void updateLight(u8 light_at_pos);
156 v3s16 getLightPosition();
157 void updateNodePos();
159 void step(float dtime, ClientEnvironment *env);
161 void processMessage(const std::string &data);
164 scene::IMeshSceneNode *m_node;
169 TestCAO proto_TestCAO(NULL, NULL);
171 TestCAO::TestCAO(IGameDef *gamedef, ClientEnvironment *env):
172 ClientActiveObject(0, gamedef, env),
174 m_position(v3f(0,10*BS,0))
176 ClientActiveObject::registerType(getType(), create);
183 ClientActiveObject* TestCAO::create(IGameDef *gamedef, ClientEnvironment *env)
185 return new TestCAO(gamedef, env);
188 void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
194 //video::IVideoDriver* driver = smgr->getVideoDriver();
196 scene::SMesh *mesh = new scene::SMesh();
197 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
198 video::SColor c(255,255,255,255);
199 video::S3DVertex vertices[4] =
201 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
202 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
203 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
204 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
206 u16 indices[] = {0,1,2,2,3,0};
207 buf->append(vertices, 4, indices, 6);
209 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
210 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
211 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
212 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
213 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
214 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
216 mesh->addMeshBuffer(buf);
218 m_node = smgr->addMeshSceneNode(mesh, NULL);
223 void TestCAO::removeFromScene()
232 void TestCAO::updateLight(u8 light_at_pos)
236 v3s16 TestCAO::getLightPosition()
238 return floatToInt(m_position, BS);
241 void TestCAO::updateNodePos()
246 m_node->setPosition(m_position);
247 //m_node->setRotation(v3f(0, 45, 0));
250 void TestCAO::step(float dtime, ClientEnvironment *env)
254 v3f rot = m_node->getRotation();
255 //infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
256 rot.Y += dtime * 180;
257 m_node->setRotation(rot);
261 void TestCAO::processMessage(const std::string &data)
263 infostream<<"TestCAO: Got data: "<<data<<std::endl;
264 std::istringstream is(data, std::ios::binary);
282 class ItemCAO : public ClientActiveObject
285 ItemCAO(IGameDef *gamedef, ClientEnvironment *env);
290 return ACTIVEOBJECT_TYPE_ITEM;
293 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
295 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
296 IrrlichtDevice *irr);
297 void removeFromScene();
298 void updateLight(u8 light_at_pos);
299 v3s16 getLightPosition();
300 void updateNodePos();
301 void updateInfoText();
302 void updateTexture();
304 void step(float dtime, ClientEnvironment *env);
306 void processMessage(const std::string &data);
308 void initialize(const std::string &data);
310 core::aabbox3d<f32>* getSelectionBox()
311 {return &m_selection_box;}
315 std::string infoText()
319 core::aabbox3d<f32> m_selection_box;
320 scene::IMeshSceneNode *m_node;
322 std::string m_itemstring;
323 std::string m_infotext;
326 #include "inventory.h"
329 ItemCAO proto_ItemCAO(NULL, NULL);
331 ItemCAO::ItemCAO(IGameDef *gamedef, ClientEnvironment *env):
332 ClientActiveObject(0, gamedef, env),
333 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
335 m_position(v3f(0,10*BS,0))
339 ClientActiveObject::registerType(getType(), create);
347 ClientActiveObject* ItemCAO::create(IGameDef *gamedef, ClientEnvironment *env)
349 return new ItemCAO(gamedef, env);
352 void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
358 //video::IVideoDriver* driver = smgr->getVideoDriver();
360 scene::SMesh *mesh = new scene::SMesh();
361 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
362 video::SColor c(255,255,255,255);
363 video::S3DVertex vertices[4] =
365 /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
366 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
367 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
368 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
369 video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
370 video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
371 video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
372 video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
374 u16 indices[] = {0,1,2,2,3,0};
375 buf->append(vertices, 4, indices, 6);
377 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
378 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
379 // Initialize with a generated placeholder texture
380 buf->getMaterial().setTexture(0, tsrc->getTextureRaw(""));
381 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
382 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
383 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
385 mesh->addMeshBuffer(buf);
387 m_node = smgr->addMeshSceneNode(mesh, NULL);
398 void ItemCAO::removeFromScene()
407 void ItemCAO::updateLight(u8 light_at_pos)
412 u8 li = decode_light(light_at_pos);
413 video::SColor color(255,li,li,li);
414 setMeshColor(m_node->getMesh(), color);
417 v3s16 ItemCAO::getLightPosition()
419 return floatToInt(m_position + v3f(0,0.5*BS,0), BS);
422 void ItemCAO::updateNodePos()
427 m_node->setPosition(m_position);
430 void ItemCAO::updateInfoText()
433 IItemDefManager *idef = m_gamedef->idef();
435 item.deSerialize(m_itemstring, idef);
436 if(item.isKnown(idef))
437 m_infotext = item.getDefinition(idef).description;
439 m_infotext = "Unknown item: '" + m_itemstring + "'";
441 m_infotext += " (" + itos(item.count) + ")";
443 catch(SerializationError &e)
445 m_infotext = "Unknown item: '" + m_itemstring + "'";
449 void ItemCAO::updateTexture()
454 // Create an inventory item to see what is its image
455 std::istringstream is(m_itemstring, std::ios_base::binary);
456 video::ITexture *texture = NULL;
458 IItemDefManager *idef = m_gamedef->idef();
460 item.deSerialize(is, idef);
461 texture = item.getDefinition(idef).inventory_texture;
463 catch(SerializationError &e)
465 infostream<<"WARNING: "<<__FUNCTION_NAME
466 <<": error deSerializing itemstring \""
467 <<m_itemstring<<std::endl;
470 // Set meshbuffer texture
471 m_node->getMaterial(0).setTexture(0, texture);
475 void ItemCAO::step(float dtime, ClientEnvironment *env)
479 /*v3f rot = m_node->getRotation();
480 rot.Y += dtime * 120;
481 m_node->setRotation(rot);*/
482 LocalPlayer *player = env->getLocalPlayer();
484 v3f rot = m_node->getRotation();
485 rot.Y = 180.0 - (player->getYaw());
486 m_node->setRotation(rot);
490 void ItemCAO::processMessage(const std::string &data)
492 //infostream<<"ItemCAO: Got message"<<std::endl;
493 std::istringstream is(data, std::ios::binary);
499 m_position = readV3F1000(is);
505 m_itemstring = deSerializeString(is);
511 void ItemCAO::initialize(const std::string &data)
513 infostream<<"ItemCAO: Got init data"<<std::endl;
516 std::istringstream is(data, std::ios::binary);
518 u8 version = readU8(is);
523 m_position = readV3F1000(is);
525 m_itemstring = deSerializeString(is);
536 #include "luaentity_common.h"
538 class LuaEntityCAO : public ClientActiveObject
541 core::aabbox3d<f32> m_selection_box;
542 scene::IMeshSceneNode *m_meshnode;
543 scene::IBillboardSceneNode *m_spritenode;
549 struct LuaEntityProperties *m_prop;
550 SmoothTranslator pos_translator;
551 // Spritesheet/animation stuff
554 bool m_tx_select_horiz_by_yawpitch;
556 int m_anim_num_frames;
557 float m_anim_framelength;
559 ItemGroupList m_armor_groups;
560 float m_reset_textures_timer;
563 LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
564 ClientActiveObject(0, gamedef, env),
565 m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
568 m_position(v3f(0,10*BS,0)),
569 m_velocity(v3f(0,0,0)),
570 m_acceleration(v3f(0,0,0)),
573 m_prop(new LuaEntityProperties),
576 m_tx_select_horiz_by_yawpitch(false),
578 m_anim_num_frames(1),
579 m_anim_framelength(0.2),
581 m_reset_textures_timer(-1)
584 ClientActiveObject::registerType(getType(), create);
587 void initialize(const std::string &data)
589 infostream<<"LuaEntityCAO: Got init data"<<std::endl;
591 std::istringstream is(data, std::ios::binary);
593 u8 version = readU8(is);
598 m_position = readV3F1000(is);
600 m_yaw = readF1000(is);
604 std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
605 m_prop->deSerialize(prop_is);
607 infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
609 m_selection_box = m_prop->collisionbox;
610 m_selection_box.MinEdge *= BS;
611 m_selection_box.MaxEdge *= BS;
613 pos_translator.init(m_position);
615 m_tx_size.X = 1.0 / m_prop->spritediv.X;
616 m_tx_size.Y = 1.0 / m_prop->spritediv.Y;
617 m_tx_basepos.X = m_tx_size.X * m_prop->initial_sprite_basepos.X;
618 m_tx_basepos.Y = m_tx_size.Y * m_prop->initial_sprite_basepos.Y;
628 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
630 return new LuaEntityCAO(gamedef, env);
635 return ACTIVEOBJECT_TYPE_LUAENTITY;
637 core::aabbox3d<f32>* getSelectionBox()
639 return &m_selection_box;
643 return pos_translator.vect_show;
646 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
649 if(m_meshnode != NULL || m_spritenode != NULL)
652 //video::IVideoDriver* driver = smgr->getVideoDriver();
654 if(m_prop->visual == "sprite"){
655 infostream<<"LuaEntityCAO::addToScene(): single_sprite"<<std::endl;
656 m_spritenode = smgr->addBillboardSceneNode(
657 NULL, v2f(1, 1), v3f(0,0,0), -1);
658 m_spritenode->setMaterialTexture(0,
659 tsrc->getTextureRaw("unknown_block.png"));
660 m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
661 m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
662 m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
663 m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
664 m_spritenode->setColor(video::SColor(255,0,0,0));
665 m_spritenode->setVisible(false); /* Set visible when brightness is known */
666 m_spritenode->setSize(m_prop->visual_size*BS);
668 const float txs = 1.0 / 1;
669 const float tys = 1.0 / 1;
670 setBillboardTextureMatrix(m_spritenode,
673 } else if(m_prop->visual == "cube"){
674 infostream<<"LuaEntityCAO::addToScene(): cube"<<std::endl;
675 scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS));
676 m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
679 m_meshnode->setScale(v3f(1));
680 // Will be shown when we know the brightness
681 m_meshnode->setVisible(false);
683 infostream<<"LuaEntityCAO::addToScene(): \""<<m_prop->visual
684 <<"\" not supported"<<std::endl;
690 void removeFromScene()
693 m_meshnode->remove();
697 m_spritenode->remove();
702 void updateLight(u8 light_at_pos)
704 u8 li = decode_light(light_at_pos);
705 video::SColor color(255,li,li,li);
707 setMeshColor(m_meshnode->getMesh(), color);
708 m_meshnode->setVisible(true);
711 m_spritenode->setColor(color);
712 m_spritenode->setVisible(true);
716 v3s16 getLightPosition()
718 return floatToInt(m_position, BS);
724 m_meshnode->setPosition(pos_translator.vect_show);
727 m_spritenode->setPosition(pos_translator.vect_show);
731 void step(float dtime, ClientEnvironment *env)
733 if(m_prop->physical){
734 core::aabbox3d<f32> box = m_prop->collisionbox;
737 collisionMoveResult moveresult;
738 f32 pos_max_d = BS*0.25; // Distance per iteration
739 v3f p_pos = m_position;
740 v3f p_velocity = m_velocity;
741 IGameDef *gamedef = env->getGameDef();
742 moveresult = collisionMovePrecise(&env->getMap(), gamedef,
743 pos_max_d, box, dtime, p_pos, p_velocity);
746 m_velocity = p_velocity;
748 bool is_end_position = moveresult.collides;
749 pos_translator.update(m_position, is_end_position, dtime);
750 pos_translator.translate(dtime);
753 m_velocity += dtime * m_acceleration;
755 m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
756 m_velocity += dtime * m_acceleration;
757 pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
758 pos_translator.translate(dtime);
762 m_anim_timer += dtime;
763 if(m_anim_timer >= m_anim_framelength){
764 m_anim_timer -= m_anim_framelength;
766 if(m_anim_frame >= m_anim_num_frames)
772 if(m_reset_textures_timer >= 0){
773 m_reset_textures_timer -= dtime;
774 if(m_reset_textures_timer <= 0){
775 m_reset_textures_timer = -1;
781 void updateTexturePos()
784 scene::ICameraSceneNode* camera =
785 m_spritenode->getSceneManager()->getActiveCamera();
788 v3f cam_to_entity = m_spritenode->getAbsolutePosition()
789 - camera->getAbsolutePosition();
790 cam_to_entity.normalize();
792 int row = m_tx_basepos.Y;
793 int col = m_tx_basepos.X;
795 if(m_tx_select_horiz_by_yawpitch)
797 if(cam_to_entity.Y > 0.75)
799 else if(cam_to_entity.Y < -0.75)
802 float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.;
803 float dir = mob_dir - m_yaw;
804 dir = wrapDegrees_180(dir);
805 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
806 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
808 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
810 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
812 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
819 // Animation goes downwards
822 float txs = m_tx_size.X;
823 float tys = m_tx_size.Y;
824 setBillboardTextureMatrix(m_spritenode,
829 void updateTextures(const std::string &mod)
831 ITextureSource *tsrc = m_gamedef->tsrc();
834 std::string texturestring = "unknown_block.png";
835 if(m_prop->textures.size() >= 1)
836 texturestring = m_prop->textures[0];
837 texturestring += mod;
838 m_spritenode->setMaterialTexture(0,
839 tsrc->getTextureRaw(texturestring));
842 for (u32 i = 0; i < 6; ++i)
844 std::string texturestring = "unknown_block.png";
845 if(m_prop->textures.size() > i)
846 texturestring = m_prop->textures[i];
847 texturestring += mod;
848 AtlasPointer ap = tsrc->getTexture(texturestring);
850 // Get the tile texture and atlas transformation
851 video::ITexture* atlas = ap.atlas;
855 // Set material flags and texture
856 video::SMaterial& material = m_meshnode->getMaterial(i);
857 material.setFlag(video::EMF_LIGHTING, false);
858 material.setFlag(video::EMF_BILINEAR_FILTER, false);
859 material.setTexture(0, atlas);
860 material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
861 material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
866 void processMessage(const std::string &data)
868 //infostream<<"LuaEntityCAO: Got message"<<std::endl;
869 std::istringstream is(data, std::ios::binary);
872 if(cmd == LUAENTITY_CMD_UPDATE_POSITION) // update position
875 bool do_interpolate = readU8(is);
877 m_position = readV3F1000(is);
879 m_velocity = readV3F1000(is);
881 m_acceleration = readV3F1000(is);
883 m_yaw = readF1000(is);
884 // is_end_position (for interpolation)
885 bool is_end_position = readU8(is);
887 float update_interval = readF1000(is);
890 if(!m_prop->physical)
891 pos_translator.update(m_position, is_end_position, update_interval);
893 pos_translator.init(m_position);
897 else if(cmd == LUAENTITY_CMD_SET_TEXTURE_MOD) // set texture modification
899 std::string mod = deSerializeString(is);
902 else if(cmd == LUAENTITY_CMD_SET_SPRITE) // set sprite
904 v2s16 p = readV2S16(is);
905 int num_frames = readU16(is);
906 float framelength = readF1000(is);
907 bool select_horiz_by_yawpitch = readU8(is);
910 m_anim_num_frames = num_frames;
911 m_anim_framelength = framelength;
912 m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
916 else if(cmd == LUAENTITY_CMD_PUNCHED)
918 /*s16 damage =*/ readS16(is);
919 s16 result_hp = readS16(is);
922 // TODO: Execute defined fast response
924 else if(cmd == LUAENTITY_CMD_UPDATE_ARMOR_GROUPS)
926 m_armor_groups.clear();
927 int armor_groups_size = readU16(is);
928 for(int i=0; i<armor_groups_size; i++){
929 std::string name = deSerializeString(is);
930 int rating = readS16(is);
931 m_armor_groups[name] = rating;
936 bool directReportPunch(v3f dir, const ItemStack *punchitem=NULL,
937 float time_from_last_punch=1000000)
940 const ToolCapabilities *toolcap =
941 &punchitem->getToolCapabilities(m_gamedef->idef());
942 PunchDamageResult result = getPunchDamage(
946 time_from_last_punch);
948 if(result.did_punch && result.damage != 0)
950 if(result.damage < m_hp)
951 m_hp -= result.damage;
954 // TODO: Execute defined fast response
955 // I guess flashing is fine as of now
956 updateTextures("^[brighten");
957 m_reset_textures_timer = 0.1;
963 std::string debugInfoText()
965 std::ostringstream os(std::ios::binary);
966 os<<"LuaEntityCAO hp="<<m_hp<<"\n";
968 for(ItemGroupList::const_iterator i = m_armor_groups.begin();
969 i != m_armor_groups.end(); i++){
970 os<<i->first<<"="<<i->second<<", ";
978 LuaEntityCAO proto_LuaEntityCAO(NULL, NULL);
984 class PlayerCAO : public ClientActiveObject
987 core::aabbox3d<f32> m_selection_box;
988 scene::IMeshSceneNode *m_node;
989 scene::ITextSceneNode* m_text;
993 SmoothTranslator pos_translator;
994 bool m_is_local_player;
995 LocalPlayer *m_local_player;
996 float m_damage_visual_timer;
1000 PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
1001 ClientActiveObject(0, gamedef, env),
1002 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.),
1005 m_position(v3f(0,10*BS,0)),
1007 m_is_local_player(false),
1008 m_local_player(NULL),
1009 m_damage_visual_timer(0),
1013 ClientActiveObject::registerType(getType(), create);
1016 void initialize(const std::string &data)
1018 infostream<<"PlayerCAO: Got init data"<<std::endl;
1020 std::istringstream is(data, std::ios::binary);
1022 u8 version = readU8(is);
1027 m_name = deSerializeString(is);
1029 m_position = readV3F1000(is);
1031 m_yaw = readF1000(is);
1033 m_dead = readU8(is);
1035 pos_translator.init(m_position);
1037 Player *player = m_env->getPlayer(m_name.c_str());
1038 if(player && player->isLocal()){
1039 m_is_local_player = true;
1040 m_local_player = (LocalPlayer*)player;
1050 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
1052 return new PlayerCAO(gamedef, env);
1057 return ACTIVEOBJECT_TYPE_PLAYER;
1059 core::aabbox3d<f32>* getSelectionBox()
1061 if(m_is_local_player)
1065 return &m_selection_box;
1069 return pos_translator.vect_show;
1072 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1073 IrrlichtDevice *irr)
1077 if(m_is_local_player)
1080 //video::IVideoDriver* driver = smgr->getVideoDriver();
1081 gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
1083 scene::SMesh *mesh = new scene::SMesh();
1085 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
1086 video::SColor c(255,255,255,255);
1087 video::S3DVertex vertices[4] =
1089 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
1090 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
1091 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
1092 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
1094 u16 indices[] = {0,1,2,2,3,0};
1095 buf->append(vertices, 4, indices, 6);
1097 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
1098 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
1099 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
1100 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
1102 mesh->addMeshBuffer(buf);
1106 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
1107 video::SColor c(255,255,255,255);
1108 video::S3DVertex vertices[4] =
1110 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
1111 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
1112 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
1113 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
1115 u16 indices[] = {0,1,2,2,3,0};
1116 buf->append(vertices, 4, indices, 6);
1118 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
1119 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
1120 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
1121 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
1123 mesh->addMeshBuffer(buf);
1126 m_node = smgr->addMeshSceneNode(mesh, NULL);
1128 // Set it to use the materials of the meshbuffers directly.
1129 // This is needed for changing the texture in the future
1130 m_node->setReadOnlyMaterials(true);
1133 // Add a text node for showing the name
1134 std::wstring wname = narrow_to_wide(m_name);
1135 m_text = smgr->addTextSceneNode(gui->getBuiltInFont(),
1136 wname.c_str(), video::SColor(255,255,255,255), m_node);
1137 m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
1144 void removeFromScene()
1153 void updateLight(u8 light_at_pos)
1158 u8 li = decode_light(light_at_pos);
1159 video::SColor color(255,li,li,li);
1160 setMeshColor(m_node->getMesh(), color);
1165 v3s16 getLightPosition()
1167 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
1170 void updateVisibility()
1175 m_node->setVisible(!m_dead);
1178 void updateNodePos()
1183 m_node->setPosition(pos_translator.vect_show);
1185 v3f rot = m_node->getRotation();
1187 m_node->setRotation(rot);
1190 void step(float dtime, ClientEnvironment *env)
1192 pos_translator.translate(dtime);
1196 if(m_damage_visual_timer > 0){
1197 m_damage_visual_timer -= dtime;
1198 if(m_damage_visual_timer <= 0){
1204 void processMessage(const std::string &data)
1206 //infostream<<"PlayerCAO: Got message"<<std::endl;
1207 std::istringstream is(data, std::ios::binary);
1209 u8 cmd = readU8(is);
1210 if(cmd == 0) // update position
1213 m_position = readV3F1000(is);
1215 m_yaw = readF1000(is);
1217 pos_translator.update(m_position, false);
1221 else if(cmd == 1) // punched
1224 s16 damage = readS16(is);
1225 m_damage_visual_timer = 0.05;
1227 m_damage_visual_timer += 0.05 * damage;
1228 updateTextures("^[brighten");
1230 else if(cmd == 2) // died or respawned
1232 m_dead = readU8(is);
1237 void updateTextures(const std::string &mod)
1241 ITextureSource *tsrc = m_gamedef->tsrc();
1242 scene::IMesh *mesh = m_node->getMesh();
1245 std::string tname = "player.png";
1247 scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
1248 buf->getMaterial().setTexture(0,
1249 tsrc->getTextureRaw(tname));
1252 std::string tname = "player_back.png";
1254 scene::IMeshBuffer *buf = mesh->getMeshBuffer(1);
1255 buf->getMaterial().setTexture(0,
1256 tsrc->getTextureRaw(tname));
1263 PlayerCAO proto_PlayerCAO(NULL, NULL);