Fix some remaining issues with attachments, now they work. Tested with object->player...
authorMirceaKitsune <sonichedgehog_hyperblast00@yahoo.com>
Sun, 28 Oct 2012 15:07:11 +0000 (17:07 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 25 Nov 2012 17:14:22 +0000 (19:14 +0200)
src/clientobject.h
src/content_cao.cpp
src/content_sao.cpp
src/nodedef.cpp

index 8b0b57147adb91fc3e2db4f1806404b40bd8ce09..e08b78c579dc05b9e852566bb0b730348440d8bd 100644 (file)
@@ -56,6 +56,11 @@ public:
        virtual core::aabbox3d<f32>* getSelectionBox(){return NULL;}
        virtual core::aabbox3d<f32>* getCollisionBox(){return NULL;}
        virtual v3f getPosition(){return v3f(0,0,0);}
+       virtual scene::IMeshSceneNode *getMeshSceneNode(){return NULL;}
+       virtual scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode(){return NULL;}
+       virtual scene::IBillboardSceneNode *getSpriteSceneNode(){return NULL;}
+       virtual bool isPlayer(){return false;}
+       virtual bool isLocalPlayer(){return false;}
        virtual bool doShowSelectionBox(){return true;}
        
        // Step object in time
index 613ec6153292628f2ba2a29a26b39798b9cac007..60d458318d7ce6a3816d6d30137ef6d3f6ca724b 100644 (file)
@@ -554,7 +554,7 @@ private:
        // Only set at initialization
        std::string m_name;
        bool m_is_player;
-       bool m_is_local_player; // determined locally
+       bool m_is_local_player;
        int m_id;
        // Property-ish things
        ObjectProperties m_prop;
@@ -594,6 +594,7 @@ private:
        bool m_visuals_expired;
        float m_step_distance_counter;
        u8 m_last_light;
+       bool m_is_visible;
 
 public:
        GenericCAO(IGameDef *gamedef, ClientEnvironment *env):
@@ -634,7 +635,8 @@ public:
                m_reset_textures_timer(-1),
                m_visuals_expired(false),
                m_step_distance_counter(0),
-               m_last_light(255)
+               m_last_light(255),
+               m_is_visible(false)
        {
                if(gamedef == NULL)
                        ClientActiveObject::registerType(getType(), create);
@@ -691,7 +693,7 @@ public:
        }
        core::aabbox3d<f32>* getSelectionBox()
        {
-               if(!m_prop.is_visible || m_is_local_player)
+               if(!m_prop.is_visible || !m_is_visible || m_is_local_player)
                        return NULL;
                return &m_selection_box;
        }
@@ -700,6 +702,31 @@ public:
                return pos_translator.vect_show;
        }
 
+       scene::IMeshSceneNode *getMeshSceneNode()
+       {
+               return m_meshnode;
+       }
+
+       scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode()
+       {
+               return m_animated_meshnode;
+       }
+
+       scene::IBillboardSceneNode *getSpriteSceneNode()
+       {
+               return m_spritenode;
+       }
+
+       bool isPlayer()
+       {
+               return m_is_player;
+       }
+
+       bool isLocalPlayer()
+       {
+               return m_is_local_player;
+       }
+
        void removeFromScene()
        {
                if(m_meshnode){
@@ -891,22 +918,27 @@ public:
                
        void updateLight(u8 light_at_pos)
        {
-               bool is_visible = (m_hp != 0);
+               // Objects attached to the local player should always be hidden
+               if(m_attachment_parent != NULL && m_attachment_parent->isLocalPlayer())
+                       m_is_visible = false;
+               else
+                       m_is_visible = (m_hp != 0);
                u8 li = decode_light(light_at_pos);
+
                if(li != m_last_light){
                        m_last_light = li;
                        video::SColor color(255,li,li,li);
                        if(m_meshnode){
                                setMeshColor(m_meshnode->getMesh(), color);
-                               m_meshnode->setVisible(is_visible);
+                               m_meshnode->setVisible(m_is_visible);
                        }
                        if(m_animated_meshnode){
                                setMeshColor(m_animated_meshnode->getMesh(), color);
-                               m_animated_meshnode->setVisible(is_visible);
+                               m_animated_meshnode->setVisible(m_is_visible);
                        }
                        if(m_spritenode){
                                m_spritenode->setColor(color);
-                               m_spritenode->setVisible(is_visible);
+                               m_spritenode->setVisible(m_is_visible);
                        }
                }
        }
@@ -948,6 +980,7 @@ public:
                        addToScene(m_smgr, m_gamedef->tsrc(), m_irr);
                        updateAnimations();
                        updateBonePosRot();
+                       updateAttachments();
                }
 
                if(m_attachment_parent == NULL) // Attachments should be glued to their parent by Irrlicht
@@ -1019,6 +1052,9 @@ public:
                        m_yaw += dtime * m_prop.automatic_rotate * 180 / M_PI;
                        updateNodePos();
                }
+
+               if(m_animated_meshnode)
+                       errorstream<<"Attachment position: "<<m_animated_meshnode->getPosition().X<<","<<m_animated_meshnode->getPosition().Y<<","<<m_animated_meshnode->getPosition().Z<<std::endl;
        }
 
        void updateTexturePos()
@@ -1241,7 +1277,120 @@ public:
                //Useful links:
                // http://irrlicht.sourceforge.net/forum/viewtopic.php?t=7514
                // http://www.irrlicht3d.org/wiki/index.php?n=Main.HowToUseTheNewAnimationSystem
+               // http://gamedev.stackexchange.com/questions/27363/finding-the-endpoint-of-a-named-bone-in-irrlicht
                // Irrlicht documentation: http://irrlicht.sourceforge.net/docu/
+
+               if (m_attachment_parent != NULL && !m_attachment_parent->isLocalPlayer())
+               {
+                       // REMAINING ATTACHMENT ISSUES:
+                       // The code below should cause the child to get attached, but for some reason it's not working
+                       // A debug print confirms both position and absolute position are set accordingly, but the object still shows at origin 0,0,0
+
+                       scene::IMeshSceneNode *parent_mesh = NULL;
+                       if(m_attachment_parent->getMeshSceneNode())
+                               parent_mesh = m_attachment_parent->getMeshSceneNode();
+                       scene::IAnimatedMeshSceneNode *parent_animated_mesh = NULL;
+                       if(m_attachment_parent->getAnimatedMeshSceneNode())
+                               parent_animated_mesh = m_attachment_parent->getAnimatedMeshSceneNode();
+                       scene::IBillboardSceneNode *parent_sprite = NULL;
+                       if(m_attachment_parent->getSpriteSceneNode())
+                               parent_sprite = m_attachment_parent->getSpriteSceneNode();
+
+                       scene::IBoneSceneNode *parent_bone = NULL;
+                       if(parent_animated_mesh && m_attachment_bone != "")
+                               parent_bone = parent_animated_mesh->getJointNode(m_attachment_bone.c_str());
+                       if(!parent_bone) // Should be false if the bone doesn't exist on the mesh
+                               parent_bone = NULL;
+
+                       // TODO: Perhaps use polymorphism here to save code duplication
+                       if(m_meshnode){
+                               if(parent_bone){
+                                       m_meshnode->setPosition(parent_bone->getPosition());
+                                       m_meshnode->setRotation(parent_bone->getRotation());
+                                       m_meshnode->updateAbsolutePosition();
+                                       //m_meshnode->setParent(parent_bone);
+                               }
+                               else
+                               {
+                                       if(parent_mesh){
+                                               m_meshnode->setPosition(parent_mesh->getPosition());
+                                               m_meshnode->setRotation(parent_mesh->getRotation());
+                                               m_meshnode->updateAbsolutePosition();
+                                               //m_meshnode->setParent(parent_mesh);
+                                       }
+                                       else if(parent_animated_mesh){
+                                               m_meshnode->setPosition(parent_animated_mesh->getPosition());
+                                               m_meshnode->setRotation(parent_animated_mesh->getRotation());
+                                               m_meshnode->updateAbsolutePosition();
+                                               //m_meshnode->setParent(parent_animated_mesh);
+                                       }
+                                       else if(parent_sprite){
+                                               m_meshnode->setPosition(parent_sprite->getPosition());
+                                               m_meshnode->setRotation(parent_sprite->getRotation());
+                                               m_meshnode->updateAbsolutePosition();
+                                               //m_meshnode->setParent(parent_sprite);
+                                       }
+                               }
+                       }
+                       if(m_animated_meshnode){
+                               if(parent_bone){
+                                       m_animated_meshnode->setPosition(parent_bone->getPosition());
+                                       m_animated_meshnode->setRotation(parent_bone->getRotation());
+                                       m_animated_meshnode->updateAbsolutePosition();
+                                       //m_animated_meshnode->setParent(parent_bone);
+                               }
+                               else
+                               {
+                                       if(parent_mesh){
+                                               m_animated_meshnode->setPosition(parent_mesh->getPosition());
+                                               m_animated_meshnode->setRotation(parent_mesh->getRotation());
+                                               m_animated_meshnode->updateAbsolutePosition();
+                                               //m_animated_meshnode->setParent(parent_mesh);
+                                       }
+                                       else if(parent_animated_mesh){
+                                               m_animated_meshnode->setPosition(parent_animated_mesh->getPosition());
+                                               m_animated_meshnode->setRotation(parent_animated_mesh->getRotation());
+                                               m_animated_meshnode->updateAbsolutePosition();
+                                               //m_animated_meshnode->setParent(parent_animated_mesh);
+                                       }
+                                       else if(parent_sprite){
+                                               m_animated_meshnode->setPosition(parent_sprite->getPosition());
+                                               m_animated_meshnode->setRotation(parent_sprite->getRotation());
+                                               m_animated_meshnode->updateAbsolutePosition();
+                                               //m_animated_meshnode->setParent(parent_sprite);
+                                       }
+                               }
+                       }
+                       if(m_spritenode){
+                               if(parent_bone){
+                                       m_spritenode->setPosition(parent_bone->getPosition());
+                                       m_spritenode->setRotation(parent_bone->getRotation());
+                                       m_spritenode->updateAbsolutePosition();
+                                       //m_spritenode->setParent(parent_bone);
+                               }
+                               else
+                               {
+                                       if(parent_mesh){
+                                               m_spritenode->setPosition(parent_mesh->getPosition());
+                                               m_spritenode->setRotation(parent_mesh->getRotation());
+                                               m_spritenode->updateAbsolutePosition();
+                                               //m_spritenode->setParent(parent_mesh);
+                                       }
+                                       else if(parent_animated_mesh){
+                                               m_spritenode->setPosition(parent_animated_mesh->getPosition());
+                                               m_spritenode->setRotation(parent_animated_mesh->getRotation());
+                                               m_spritenode->updateAbsolutePosition();
+                                               //m_spritenode->setParent(parent_animated_mesh);
+                                       }
+                                       else if(parent_sprite){
+                                               m_spritenode->setPosition(parent_sprite->getPosition());
+                                               m_spritenode->setRotation(parent_sprite->getRotation());
+                                               m_spritenode->updateAbsolutePosition();
+                                               //m_spritenode->setParent(parent_sprite);
+                                       }
+                               }
+                       }
+               }
        }
 
        void processMessage(const std::string &data)
@@ -1334,11 +1483,9 @@ public:
                }
                else if(cmd == GENERIC_CMD_SET_ATTACHMENT)
                {
-                       ClientActiveObject *obj;
                        int parent_id = readS16(is);
-                       if(parent_id > 0)
-                               obj = m_env->getActiveObject(parent_id);
-                       else
+                       ClientActiveObject *obj = m_env->getActiveObject(parent_id);
+                       if(!parent_id || !obj)
                                obj = NULL;
                        m_attachment_parent = obj;
                        m_attachment_bone = deSerializeString(is);
index 7787e33fba326881978e6309ef0b95000855b0fc..3289f9077f5ba8ac8641d6646635490b5aa3f81e 100644 (file)
@@ -444,11 +444,12 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
 
        m_last_sent_position_timer += dtime;
        
+       // Each frame, parent position is copied if the object is attached, otherwise it's calculated normally
+       // If the object gets detached this comes into effect automatically from the last known origin
        if(m_parent != NULL)
        {
-               // REMAINING ATTACHMENT ISSUES:
-               // This is causing a segmentation fault, investigate why!
-               //m_base_position = m_parent->getBasePosition();
+               v3f pos = m_parent->getBasePosition();
+               m_base_position = pos;
                m_velocity = v3f(0,0,0);
                m_acceleration = v3f(0,0,0);
        }
@@ -486,20 +487,23 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
 
        if(send_recommended == false)
                return;
-       
-       // TODO: force send when acceleration changes enough?
-       float minchange = 0.2*BS;
-       if(m_last_sent_position_timer > 1.0){
-               minchange = 0.01*BS;
-       } else if(m_last_sent_position_timer > 0.2){
-               minchange = 0.05*BS;
-       }
-       float move_d = m_base_position.getDistanceFrom(m_last_sent_position);
-       move_d += m_last_sent_move_precision;
-       float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity);
-       if(move_d > minchange || vel_d > minchange ||
-                       fabs(m_yaw - m_last_sent_yaw) > 1.0){
-               sendPosition(true, false);
+
+       if(m_parent != NULL)
+       {
+               // TODO: force send when acceleration changes enough?
+               float minchange = 0.2*BS;
+               if(m_last_sent_position_timer > 1.0){
+                       minchange = 0.01*BS;
+               } else if(m_last_sent_position_timer > 0.2){
+                       minchange = 0.05*BS;
+               }
+               float move_d = m_base_position.getDistanceFrom(m_last_sent_position);
+               move_d += m_last_sent_move_precision;
+               float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity);
+               if(move_d > minchange || vel_d > minchange ||
+                               fabs(m_yaw - m_last_sent_yaw) > 1.0){
+                       sendPosition(true, false);
+               }
        }
 
        if(m_armor_groups_sent == false){
@@ -686,11 +690,11 @@ void LuaEntitySAO::setAttachment(ServerActiveObject *parent, std::string bone, v
 {
        // Attachments need to be handled on both the server and client.
        // If we just attach on the server, we can only copy the position of the parent. Attachments
-       // are still sent to clients at an interval so players would see them following the parent
-       // instead of sticking to it, plus we can't read and attach to skeletal bones.
+       // are still sent to clients at an interval so players might see them lagging, plus we can't
+       // read and attach to skeletal bones.
        // If we just attach on the client, the server still sees the child at its original location.
-       // This can break some things, so we also give the server the most accurate representation
-       // even if players will only see the client changes since they override server-sent position.
+       // This breaks some things so we also give the server the most accurate representation
+       // even if players only see the client changes.
 
        // Server attachment:
        m_parent = parent;
@@ -776,6 +780,7 @@ std::string LuaEntitySAO::getPropertyPacket()
 
 void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
 {
+       // If the object is attached client-side, don't waste bandwidth sending its position to clients
        if(m_parent != NULL)
                return;
        
@@ -925,7 +930,7 @@ std::string PlayerSAO::getStaticData()
 }
 
 void PlayerSAO::step(float dtime, bool send_recommended)
-{      
+{
        if(!m_properties_sent)
        {
                m_properties_sent = true;
@@ -938,7 +943,16 @@ void PlayerSAO::step(float dtime, bool send_recommended)
        m_time_from_last_punch += dtime;
        m_nocheat_dig_time += dtime;
 
-       if(m_parent == NULL)
+       // Each frame, parent position is copied if the object is attached, otherwise it's calculated normally
+       // If the object gets detached this comes into effect automatically from the last known origin
+       if(m_parent != NULL)
+       {
+               v3f pos = m_parent->getBasePosition();
+               m_last_good_position = pos;
+               m_last_good_position_age = 0;
+               m_player->setPosition(pos);
+       }
+       else
        {
                if(m_is_singleplayer || g_settings->getBool("disable_anticheat"))
                {
@@ -999,15 +1013,13 @@ void PlayerSAO::step(float dtime, bool send_recommended)
        if(send_recommended == false)
                return;
 
-       // If the object is attached client-side, don't waste bandwidth and send its position to clients
+       // If the object is attached client-side, don't waste bandwidth sending its position to clients
        if(m_position_not_sent && m_parent == NULL)
        {
                m_position_not_sent = false;
                float update_interval = m_env->getSendRecommendedInterval();
                v3f pos;
-               // REMAINING ATTACHMENT ISSUES:
-               // This is causing a segmentation fault, investigate why!
-               if(m_parent != NULL)
+               if(m_parent != NULL) // Just in case we ever do send attachment position too
                        pos = m_parent->getBasePosition();
                else
                        pos = m_player->getPosition() + v3f(0,BS*1,0);
@@ -1043,8 +1055,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
 
 void PlayerSAO::setBasePosition(const v3f &position)
 {
-       if(m_parent != NULL)
-               return;
+       // This needs to be ran for attachments too
        ServerActiveObject::setBasePosition(position);
        m_position_not_sent = true;
 }
@@ -1183,11 +1194,11 @@ void PlayerSAO::setAttachment(ServerActiveObject *parent, std::string bone, v3f
 {
        // Attachments need to be handled on both the server and client.
        // If we just attach on the server, we can only copy the position of the parent. Attachments
-       // are still sent to clients at an interval so players would see them following the parent
-       // instead of sticking to it, plus we can't read and attach to skeletal bones.
+       // are still sent to clients at an interval so players might see them lagging, plus we can't
+       // read and attach to skeletal bones.
        // If we just attach on the client, the server still sees the child at its original location.
-       // This can break some things, so we also give the server the most accurate representation
-       // even if players will only see the client changes since they override server-sent position.
+       // This breaks some things so we also give the server the most accurate representation
+       // even if players only see the client changes.
 
        // Server attachment:
        m_parent = parent;
index 180219ba854f1c0dd8a17b732d74994c4958666c..53deea11b7940500be3f3b00616afdb9f50e6531 100644 (file)
@@ -254,6 +254,7 @@ void ContentFeatures::serialize(std::ostream &os)
        os<<serializeString(liquid_alternative_flowing);
        os<<serializeString(liquid_alternative_source);
        writeU8(os, liquid_viscosity);
+       writeU8(os, liquid_renewable);
        writeU8(os, light_source);
        writeU32(os, damage_per_second);
        node_box.serialize(os);
@@ -311,6 +312,7 @@ void ContentFeatures::deSerialize(std::istream &is)
        liquid_alternative_flowing = deSerializeString(is);
        liquid_alternative_source = deSerializeString(is);
        liquid_viscosity = readU8(is);
+       liquid_renewable = readU8(is);
        light_source = readU8(is);
        damage_per_second = readU32(is);
        node_box.deSerialize(is);