]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/content_sao.cpp
Mgv7, mgflat, mgfractal: Tunnel generation code optimisation
[dragonfireclient.git] / src / content_sao.cpp
index 26b721d39981030eb5e78fa53adb3e8b80ddac13..53bf3154f593fb39c429876e850fe9280c141da9 100644 (file)
@@ -23,12 +23,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "collision.h"
 #include "environment.h"
 #include "settings.h"
-#include "main.h" // For g_profiler
-#include "profiler.h"
 #include "serialization.h" // For compressZlib
 #include "tool.h" // For ToolCapabilities
 #include "gamedef.h"
 #include "player.h"
+#include "server.h"
 #include "scripting_game.h"
 #include "genericobject.h"
 #include "log.h"
@@ -90,7 +89,7 @@ class TestSAO : public ServerActiveObject
                        data += itos(m_base_position.Z);
 
                        ActiveObjectMessage aom(getId(), false, data);
-                       m_messages_out.push_back(aom);
+                       m_messages_out.push(aom);
                }
        }
 
@@ -136,6 +135,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
        m_armor_groups_sent(false),
        m_animation_speed(0),
        m_animation_blend(0),
+       m_animation_loop(true),
        m_animation_sent(false),
        m_bone_position_sent(false),
        m_attachment_parent_id(0),
@@ -232,7 +232,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
                std::string str = getPropertyPacket();
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
-               m_messages_out.push_back(aom);
+               m_messages_out.push(aom);
        }
 
        // If attached, check that our parent is still there. If it isn't, detach.
@@ -259,7 +259,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
        else
        {
                if(m_prop.physical){
-                       core::aabbox3d<f32> box = m_prop.collisionbox;
+                       aabb3f box = m_prop.collisionbox;
                        box.MinEdge *= BS;
                        box.MaxEdge *= BS;
                        collisionMoveResult moveresult;
@@ -269,7 +269,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
                        v3f p_acceleration = m_acceleration;
                        moveresult = collisionMoveSimple(m_env,m_env->getGameDef(),
                                        pos_max_d, box, m_prop.stepheight, dtime,
-                                       p_pos, p_velocity, p_acceleration,
+                                       &p_pos, &p_velocity, p_acceleration,
                                        this, m_prop.collideWithObjects);
 
                        // Apply results
@@ -283,8 +283,20 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
                }
 
                if((m_prop.automatic_face_movement_dir) &&
-                               (fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)){
-                       m_yaw = atan2(m_velocity.Z,m_velocity.X) * 180 / M_PI + m_prop.automatic_face_movement_dir_offset;
+                               (fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001))
+               {
+                       float optimal_yaw = atan2(m_velocity.Z,m_velocity.X) * 180 / M_PI
+                                       + m_prop.automatic_face_movement_dir_offset;
+                       float max_rotation_delta =
+                                       dtime * m_prop.automatic_face_movement_max_rotation_per_sec;
+
+                       if ((m_prop.automatic_face_movement_max_rotation_per_sec > 0) &&
+                               (fabs(m_yaw - optimal_yaw) > max_rotation_delta)) {
+
+                               m_yaw = optimal_yaw < m_yaw ? m_yaw - max_rotation_delta : m_yaw + max_rotation_delta;
+                       } else {
+                               m_yaw = optimal_yaw;
+                       }
                }
        }
 
@@ -319,15 +331,16 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
                                m_armor_groups);
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
-               m_messages_out.push_back(aom);
+               m_messages_out.push(aom);
        }
 
        if(m_animation_sent == false){
                m_animation_sent = true;
-               std::string str = gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend);
+               std::string str = gob_cmd_update_animation(
+                       m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop);
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
-               m_messages_out.push_back(aom);
+               m_messages_out.push(aom);
        }
 
        if(m_bone_position_sent == false){
@@ -336,7 +349,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
                        std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y);
                        // create message and add to list
                        ActiveObjectMessage aom(getId(), true, str);
-                       m_messages_out.push_back(aom);
+                       m_messages_out.push(aom);
                }
        }
 
@@ -345,7 +358,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
                std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation);
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
-               m_messages_out.push_back(aom);
+               m_messages_out.push(aom);
        }
 }
 
@@ -366,7 +379,8 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version)
                writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
                os<<serializeLongString(getPropertyPacket()); // message 1
                os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
-               os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
+               os<<serializeLongString(gob_cmd_update_animation(
+                       m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3
                for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
                        os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
                }
@@ -391,7 +405,7 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version)
 
 std::string LuaEntitySAO::getStaticData()
 {
-       verbosestream<<__FUNCTION_NAME<<std::endl;
+       verbosestream<<FUNCTION_NAME<<std::endl;
        std::ostringstream os(std::ios::binary);
        // version
        writeU8(os, 1);
@@ -419,19 +433,19 @@ int LuaEntitySAO::punch(v3f dir,
                ServerActiveObject *puncher,
                float time_from_last_punch)
 {
-       if(!m_registered){
+       if (!m_registered){
                // Delete unknown LuaEntities when punched
                m_removed = true;
                return 0;
        }
 
        // It's best that attachments cannot be punched
-       if(isAttached())
+       if (isAttached())
                return 0;
 
        ItemStack *punchitem = NULL;
        ItemStack punchitem_static;
-       if(puncher){
+       if (puncher) {
                punchitem_static = puncher->getWieldedItem();
                punchitem = &punchitem_static;
        }
@@ -442,31 +456,26 @@ int LuaEntitySAO::punch(v3f dir,
                        punchitem,
                        time_from_last_punch);
 
-       if(result.did_punch)
-       {
+       if (result.did_punch) {
                setHP(getHP() - result.damage);
 
+               if (result.damage > 0) {
+                       std::string punchername = puncher ? puncher->getDescription() : "nil";
 
-               std::string punchername = "nil";
-
-               if ( puncher != 0 )
-                       punchername = puncher->getDescription();
-
-               actionstream<<getDescription()<<" punched by "
-                               <<punchername<<", damage "<<result.damage
-                               <<" hp, health now "<<getHP()<<" hp"<<std::endl;
-
-               {
-                       std::string str = gob_cmd_punched(result.damage, getHP());
-                       // create message and add to list
-                       ActiveObjectMessage aom(getId(), true, str);
-                       m_messages_out.push_back(aom);
+                       actionstream << getDescription() << " punched by "
+                                       << punchername << ", damage " << result.damage
+                                       << " hp, health now " << getHP() << " hp" << std::endl;
                }
 
-               if(getHP() == 0)
-                       m_removed = true;
+               std::string str = gob_cmd_punched(result.damage, getHP());
+               // create message and add to list
+               ActiveObjectMessage aom(getId(), true, str);
+               m_messages_out.push(aom);
        }
 
+       if (getHP() == 0)
+               m_removed = true;
+
        m_env->getScriptIface()->luaentity_Punch(m_id, puncher,
                        time_from_last_punch, toolcap, dir);
 
@@ -475,10 +484,10 @@ int LuaEntitySAO::punch(v3f dir,
 
 void LuaEntitySAO::rightClick(ServerActiveObject *clicker)
 {
-       if(!m_registered)
+       if (!m_registered)
                return;
        // It's best that attachments cannot be clicked
-       if(isAttached())
+       if (isAttached())
                return;
        m_env->getScriptIface()->luaentity_Rightclick(m_id, clicker);
 }
@@ -533,21 +542,41 @@ void LuaEntitySAO::setArmorGroups(const ItemGroupList &armor_groups)
        m_armor_groups_sent = false;
 }
 
-void LuaEntitySAO::setAnimation(v2f frame_range, float frame_speed, float frame_blend)
+ItemGroupList LuaEntitySAO::getArmorGroups()
+{
+       return m_armor_groups;
+}
+
+void LuaEntitySAO::setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop)
 {
        m_animation_range = frame_range;
        m_animation_speed = frame_speed;
        m_animation_blend = frame_blend;
+       m_animation_loop = frame_loop;
        m_animation_sent = false;
 }
 
-void LuaEntitySAO::setBonePosition(std::string bone, v3f position, v3f rotation)
+void LuaEntitySAO::getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend, bool *frame_loop)
+{
+       *frame_range = m_animation_range;
+       *frame_speed = m_animation_speed;
+       *frame_blend = m_animation_blend;
+       *frame_loop = m_animation_loop;
+}
+
+void LuaEntitySAO::setBonePosition(const std::string &bone, v3f position, v3f rotation)
 {
        m_bone_position[bone] = core::vector2d<v3f>(position, rotation);
        m_bone_position_sent = false;
 }
 
-void LuaEntitySAO::setAttachment(int parent_id, std::string bone, v3f position, v3f rotation)
+void LuaEntitySAO::getBonePosition(const std::string &bone, v3f *position, v3f *rotation)
+{
+       *position = m_bone_position[bone].X;
+       *rotation = m_bone_position[bone].Y;
+}
+
+void LuaEntitySAO::setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation)
 {
        // 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
@@ -564,6 +593,30 @@ void LuaEntitySAO::setAttachment(int parent_id, std::string bone, v3f position,
        m_attachment_sent = false;
 }
 
+void LuaEntitySAO::getAttachment(int *parent_id, std::string *bone, v3f *position,
+       v3f *rotation)
+{
+       *parent_id = m_attachment_parent_id;
+       *bone = m_attachment_bone;
+       *position = m_attachment_position;
+       *rotation = m_attachment_rotation;
+}
+
+void LuaEntitySAO::addAttachmentChild(int child_id)
+{
+       m_attachment_child_ids.insert(child_id);
+}
+
+void LuaEntitySAO::removeAttachmentChild(int child_id)
+{
+       m_attachment_child_ids.erase(child_id);
+}
+
+std::set<int> LuaEntitySAO::getAttachmentChildIds()
+{
+       return m_attachment_child_ids;
+}
+
 ObjectProperties* LuaEntitySAO::accessObjectProperties()
 {
        return &m_prop;
@@ -609,7 +662,7 @@ void LuaEntitySAO::setTextureMod(const std::string &mod)
        std::string str = gob_cmd_set_texture_mod(mod);
        // create message and add to list
        ActiveObjectMessage aom(getId(), true, str);
-       m_messages_out.push_back(aom);
+       m_messages_out.push(aom);
 }
 
 void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength,
@@ -623,7 +676,7 @@ void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength,
        );
        // create message and add to list
        ActiveObjectMessage aom(getId(), true, str);
-       m_messages_out.push_back(aom);
+       m_messages_out.push(aom);
 }
 
 std::string LuaEntitySAO::getName()
@@ -663,7 +716,7 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
        );
        // create message and add to list
        ActiveObjectMessage aom(getId(), false, str);
-       m_messages_out.push_back(aom);
+       m_messages_out.push(aom);
 }
 
 bool LuaEntitySAO::getCollisionBox(aabb3f *toset) {
@@ -711,14 +764,12 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
        m_is_singleplayer(is_singleplayer),
        m_animation_speed(0),
        m_animation_blend(0),
+       m_animation_loop(true),
        m_animation_sent(false),
        m_bone_position_sent(false),
        m_attachment_parent_id(0),
        m_attachment_sent(false),
        // public
-       m_moved(false),
-       m_inventory_not_sent(false),
-       m_wielded_item_not_sent(false),
        m_physics_override_speed(1),
        m_physics_override_jump(1),
        m_physics_override_gravity(1),
@@ -726,8 +777,8 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
        m_physics_override_sneak_glitch(true),
        m_physics_override_sent(false)
 {
-       assert(m_player);
-       assert(m_peer_id != 0);
+       assert(m_player);       // pre-condition
+       assert(m_peer_id != 0); // pre-condition
        setBasePosition(m_player->getPosition());
        m_inventory = &m_player->inventory;
        m_armor_groups["fleshy"] = 100;
@@ -735,7 +786,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
        m_prop.hp_max = PLAYER_MAX_HP;
        m_prop.physical = false;
        m_prop.weight = 75;
-       m_prop.collisionbox = core::aabbox3d<f32>(-1/3.,-1.0,-1/3., 1/3.,1.0,1/3.);
+       m_prop.collisionbox = aabb3f(-1/3.,-1.0,-1/3., 1/3.,1.0,1/3.);
        // start of default appearance, this should be overwritten by LUA
        m_prop.visual = "upright_sprite";
        m_prop.visual_size = v2f(1, 2);
@@ -780,8 +831,8 @@ void PlayerSAO::removingFromEnvironment()
        {
                m_player->setPlayerSAO(NULL);
                m_player->peer_id = 0;
-               m_env->savePlayer(m_player->getName());
-               m_env->removePlayer(m_player->getName());
+               m_env->savePlayer((RemotePlayer*)m_player);
+               m_env->removePlayer(m_player);
        }
 }
 
@@ -804,10 +855,11 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
                writeF1000(os, m_player->getYaw());
                writeS16(os, getHP());
 
-               writeU8(os, 5 + m_bone_position.size()); // number of messages stuffed in here
+               writeU8(os, 6 + m_bone_position.size()); // number of messages stuffed in here
                os<<serializeLongString(getPropertyPacket()); // message 1
                os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
-               os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
+               os<<serializeLongString(gob_cmd_update_animation(
+                       m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3
                for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
                        os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
                }
@@ -815,6 +867,7 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
                os<<serializeLongString(gob_cmd_update_physics_override(m_physics_override_speed,
                                m_physics_override_jump, m_physics_override_gravity, m_physics_override_sneak,
                                m_physics_override_sneak_glitch)); // 5
+               os << serializeLongString(gob_cmd_update_nametag_attributes(m_prop.nametag_color)); // 6 (GENERIC_CMD_UPDATE_NAMETAG_ATTRIBUTES) : Deprecated, for backwards compatibility only.
        }
        else
        {
@@ -835,7 +888,7 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
 
 std::string PlayerSAO::getStaticData()
 {
-       assert(0);
+       FATAL_ERROR("Deprecated function (?)");
        return "";
 }
 
@@ -858,7 +911,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
                std::string str = getPropertyPacket();
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
-               m_messages_out.push_back(aom);
+               m_messages_out.push(aom);
        }
 
        // If attached, check that our parent is still there. If it isn't, detach.
@@ -869,7 +922,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
                m_attachment_position = v3f(0,0,0);
                m_attachment_rotation = v3f(0,0,0);
                m_player->setPosition(m_last_good_position);
-               m_moved = true;
+               ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
        }
 
        //dstream<<"PlayerSAO::step: dtime: "<<dtime<<std::endl;
@@ -921,22 +974,16 @@ void PlayerSAO::step(float dtime, bool send_recommended)
                );
                // create message and add to list
                ActiveObjectMessage aom(getId(), false, str);
-               m_messages_out.push_back(aom);
+               m_messages_out.push(aom);
        }
 
-       if(m_wielded_item_not_sent)
-       {
-               m_wielded_item_not_sent = false;
-               // GenericCAO has no special way to show this
-       }
-
-       if(m_armor_groups_sent == false){
+       if(m_armor_groups_sent == false) {
                m_armor_groups_sent = true;
                std::string str = gob_cmd_update_armor_groups(
                                m_armor_groups);
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
-               m_messages_out.push_back(aom);
+               m_messages_out.push(aom);
        }
 
        if(m_physics_override_sent == false){
@@ -946,15 +993,16 @@ void PlayerSAO::step(float dtime, bool send_recommended)
                                m_physics_override_sneak, m_physics_override_sneak_glitch);
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
-               m_messages_out.push_back(aom);
+               m_messages_out.push(aom);
        }
 
        if(m_animation_sent == false){
                m_animation_sent = true;
-               std::string str = gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend);
+               std::string str = gob_cmd_update_animation(
+                       m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop);
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
-               m_messages_out.push_back(aom);
+               m_messages_out.push(aom);
        }
 
        if(m_bone_position_sent == false){
@@ -963,7 +1011,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
                        std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y);
                        // create message and add to list
                        ActiveObjectMessage aom(getId(), true, str);
-                       m_messages_out.push_back(aom);
+                       m_messages_out.push(aom);
                }
        }
 
@@ -972,7 +1020,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
                std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation);
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
-               m_messages_out.push_back(aom);
+               m_messages_out.push(aom);
        }
 }
 
@@ -990,8 +1038,7 @@ void PlayerSAO::setPos(v3f pos)
        m_player->setPosition(pos);
        // Movement caused by this command is always valid
        m_last_good_position = pos;
-       // Force position change on client
-       m_moved = true;
+       ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
 }
 
 void PlayerSAO::moveTo(v3f pos, bool continuous)
@@ -1001,22 +1048,19 @@ void PlayerSAO::moveTo(v3f pos, bool continuous)
        m_player->setPosition(pos);
        // Movement caused by this command is always valid
        m_last_good_position = pos;
-       // Force position change on client
-       m_moved = true;
+       ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
 }
 
 void PlayerSAO::setYaw(float yaw)
 {
        m_player->setYaw(yaw);
-       // Force change on client
-       m_moved = true;
+       ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
 }
 
 void PlayerSAO::setPitch(float pitch)
 {
        m_player->setPitch(pitch);
-       // Force change on client
-       m_moved = true;
+       ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
 }
 
 int PlayerSAO::punch(v3f dir,
@@ -1025,19 +1069,19 @@ int PlayerSAO::punch(v3f dir,
        float time_from_last_punch)
 {
        // It's best that attachments cannot be punched
-       if(isAttached())
+       if (isAttached())
                return 0;
 
-       if(!toolcap)
+       if (!toolcap)
                return 0;
 
        // No effect if PvP disabled
-       if(g_settings->getBool("enable_pvp") == false){
-               if(puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER){
+       if (g_settings->getBool("enable_pvp") == false) {
+               if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
                        std::string str = gob_cmd_punched(0, getHP());
                        // create message and add to list
                        ActiveObjectMessage aom(getId(), true, str);
-                       m_messages_out.push_back(aom);
+                       m_messages_out.push(aom);
                        return 0;
                }
        }
@@ -1047,14 +1091,35 @@ int PlayerSAO::punch(v3f dir,
 
        std::string punchername = "nil";
 
-       if ( puncher != 0 )
+       if (puncher != 0)
                punchername = puncher->getDescription();
 
-       actionstream<<"Player "<<m_player->getName()<<" punched by "
-                       <<punchername<<", damage "<<hitparams.hp
-                       <<" HP"<<std::endl;
+       PlayerSAO *playersao = m_player->getPlayerSAO();
 
-       setHP(getHP() - hitparams.hp);
+       bool damage_handled = m_env->getScriptIface()->on_punchplayer(playersao,
+                               puncher, time_from_last_punch, toolcap, dir,
+                               hitparams.hp);
+
+       if (!damage_handled) {
+               setHP(getHP() - hitparams.hp);
+       } else { // override client prediction
+               if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
+                       std::string str = gob_cmd_punched(0, getHP());
+                       // create message and add to list
+                       ActiveObjectMessage aom(getId(), true, str);
+                       m_messages_out.push(aom);
+               }
+       }
+
+
+       actionstream << "Player " << m_player->getName() << " punched by "
+                       << punchername;
+       if (!damage_handled) {
+               actionstream << ", damage " << hitparams.hp << " HP";
+       } else {
+               actionstream << ", damage handled by lua";
+       }
+       actionstream << std::endl;
 
        return hitparams.wear;
 }
@@ -1079,11 +1144,21 @@ void PlayerSAO::setHP(s16 hp)
 {
        s16 oldhp = m_player->hp;
 
+       s16 hp_change = m_env->getScriptIface()->on_player_hpchange(this,
+               hp - oldhp);
+       if (hp_change == 0)
+               return;
+       hp = oldhp + hp_change;
+
        if (hp < 0)
                hp = 0;
        else if (hp > PLAYER_MAX_HP)
                hp = PLAYER_MAX_HP;
 
+       if(hp < oldhp && g_settings->getBool("enable_damage") == false) {
+               return;
+       }
+
        m_player->hp = hp;
 
        if (oldhp > hp)
@@ -1110,23 +1185,43 @@ void PlayerSAO::setArmorGroups(const ItemGroupList &armor_groups)
        m_armor_groups_sent = false;
 }
 
-void PlayerSAO::setAnimation(v2f frame_range, float frame_speed, float frame_blend)
+ItemGroupList PlayerSAO::getArmorGroups()
+{
+       return m_armor_groups;
+}
+
+void PlayerSAO::setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop)
 {
        // store these so they can be updated to clients
        m_animation_range = frame_range;
        m_animation_speed = frame_speed;
        m_animation_blend = frame_blend;
+       m_animation_loop = frame_loop;
        m_animation_sent = false;
 }
 
-void PlayerSAO::setBonePosition(std::string bone, v3f position, v3f rotation)
+void PlayerSAO::getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend, bool *frame_loop)
+{
+       *frame_range = m_animation_range;
+       *frame_speed = m_animation_speed;
+       *frame_blend = m_animation_blend;
+       *frame_loop = m_animation_loop;
+}
+
+void PlayerSAO::setBonePosition(const std::string &bone, v3f position, v3f rotation)
 {
        // store these so they can be updated to clients
        m_bone_position[bone] = core::vector2d<v3f>(position, rotation);
        m_bone_position_sent = false;
 }
 
-void PlayerSAO::setAttachment(int parent_id, std::string bone, v3f position, v3f rotation)
+void PlayerSAO::getBonePosition(const std::string &bone, v3f *position, v3f *rotation)
+{
+       *position = m_bone_position[bone].X;
+       *rotation = m_bone_position[bone].Y;
+}
+
+void PlayerSAO::setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation)
 {
        // 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
@@ -1143,6 +1238,30 @@ void PlayerSAO::setAttachment(int parent_id, std::string bone, v3f position, v3f
        m_attachment_sent = false;
 }
 
+void PlayerSAO::getAttachment(int *parent_id, std::string *bone, v3f *position,
+       v3f *rotation)
+{
+       *parent_id = m_attachment_parent_id;
+       *bone = m_attachment_bone;
+       *position = m_attachment_position;
+       *rotation = m_attachment_rotation;
+}
+
+void PlayerSAO::addAttachmentChild(int child_id)
+{
+       m_attachment_child_ids.insert(child_id);
+}
+
+void PlayerSAO::removeAttachmentChild(int child_id)
+{
+       m_attachment_child_ids.erase(child_id);
+}
+
+std::set<int> PlayerSAO::getAttachmentChildIds()
+{
+       return m_attachment_child_ids;
+}
+
 ObjectProperties* PlayerSAO::accessObjectProperties()
 {
        return &m_prop;
@@ -1169,11 +1288,6 @@ InventoryLocation PlayerSAO::getInventoryLocation() const
        return loc;
 }
 
-void PlayerSAO::setInventoryModified()
-{
-       m_inventory_not_sent = true;
-}
-
 std::string PlayerSAO::getWieldList() const
 {
        return "main";
@@ -1186,10 +1300,8 @@ int PlayerSAO::getWieldIndex() const
 
 void PlayerSAO::setWieldIndex(int i)
 {
-       if(i != m_wield_index)
-       {
+       if(i != m_wield_index) {
                m_wield_index = i;
-               m_wielded_item_not_sent = true;
        }
 }
 
@@ -1256,7 +1368,6 @@ bool PlayerSAO::checkMovementCheat()
                                        <<" moved too fast; resetting position"
                                        <<std::endl;
                        m_player->setPosition(m_last_good_position);
-                       m_moved = true;
                        cheated = true;
                }
        }
@@ -1276,4 +1387,3 @@ bool PlayerSAO::getCollisionBox(aabb3f *toset) {
 bool PlayerSAO::collideWithObjects(){
        return true;
 }
-