LCOV - code coverage report
Current view: top level - src - content_sao.cpp (source / functions) Hit Total Coverage
Test: report Lines: 19 716 2.7 %
Date: 2015-07-11 18:23:49 Functions: 7 96 7.3 %

          Line data    Source code
       1             : /*
       2             : Minetest
       3             : Copyright (C) 2010-2013 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 Lesser General Public License as published by
       7             : the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
      14             : 
      15             : You should have received a copy of the GNU Lesser 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_sao.h"
      21             : #include "util/serialize.h"
      22             : #include "util/mathconstants.h"
      23             : #include "collision.h"
      24             : #include "environment.h"
      25             : #include "settings.h"
      26             : #include "profiler.h"
      27             : #include "serialization.h" // For compressZlib
      28             : #include "tool.h" // For ToolCapabilities
      29             : #include "gamedef.h"
      30             : #include "player.h"
      31             : #include "server.h"
      32             : #include "scripting_game.h"
      33             : #include "genericobject.h"
      34             : #include "log.h"
      35             : 
      36           1 : std::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
      37             : 
      38             : /*
      39             :         TestSAO
      40             : */
      41             : 
      42           1 : class TestSAO : public ServerActiveObject
      43             : {
      44             : public:
      45           1 :         TestSAO(ServerEnvironment *env, v3f pos):
      46             :                 ServerActiveObject(env, pos),
      47             :                 m_timer1(0),
      48           1 :                 m_age(0)
      49             :         {
      50           1 :                 ServerActiveObject::registerType(getType(), create);
      51           1 :         }
      52           1 :         ActiveObjectType getType() const
      53           1 :         { return ACTIVEOBJECT_TYPE_TEST; }
      54             : 
      55           0 :         static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
      56             :                         const std::string &data)
      57             :         {
      58           0 :                 return new TestSAO(env, pos);
      59             :         }
      60             : 
      61           0 :         void step(float dtime, bool send_recommended)
      62             :         {
      63           0 :                 m_age += dtime;
      64           0 :                 if(m_age > 10)
      65             :                 {
      66           0 :                         m_removed = true;
      67           0 :                         return;
      68             :                 }
      69             : 
      70           0 :                 m_base_position.Y += dtime * BS * 2;
      71           0 :                 if(m_base_position.Y > 8*BS)
      72           0 :                         m_base_position.Y = 2*BS;
      73             : 
      74           0 :                 if(send_recommended == false)
      75           0 :                         return;
      76             : 
      77           0 :                 m_timer1 -= dtime;
      78           0 :                 if(m_timer1 < 0.0)
      79             :                 {
      80           0 :                         m_timer1 += 0.125;
      81             : 
      82           0 :                         std::string data;
      83             : 
      84           0 :                         data += itos(0); // 0 = position
      85           0 :                         data += " ";
      86           0 :                         data += itos(m_base_position.X);
      87           0 :                         data += " ";
      88           0 :                         data += itos(m_base_position.Y);
      89           0 :                         data += " ";
      90           0 :                         data += itos(m_base_position.Z);
      91             : 
      92           0 :                         ActiveObjectMessage aom(getId(), false, data);
      93           0 :                         m_messages_out.push(aom);
      94             :                 }
      95             :         }
      96             : 
      97           0 :         bool getCollisionBox(aabb3f *toset) {
      98           0 :                 return false;
      99             :         }
     100             : 
     101           0 :         bool collideWithObjects() {
     102           0 :                 return false;
     103             :         }
     104             : 
     105             : private:
     106             :         float m_timer1;
     107             :         float m_age;
     108             : };
     109             : 
     110             : // Prototype (registers item for deserialization)
     111           1 : TestSAO proto_TestSAO(NULL, v3f(0,0,0));
     112             : 
     113             : /*
     114             :         LuaEntitySAO
     115             : */
     116             : 
     117             : // Prototype (registers item for deserialization)
     118           1 : LuaEntitySAO proto_LuaEntitySAO(NULL, v3f(0,0,0), "_prototype", "");
     119             : 
     120           1 : LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
     121             :                 const std::string &name, const std::string &state):
     122             :         ServerActiveObject(env, pos),
     123             :         m_init_name(name),
     124             :         m_init_state(state),
     125             :         m_registered(false),
     126             :         m_hp(-1),
     127             :         m_velocity(0,0,0),
     128             :         m_acceleration(0,0,0),
     129             :         m_yaw(0),
     130             :         m_properties_sent(true),
     131             :         m_last_sent_yaw(0),
     132             :         m_last_sent_position(0,0,0),
     133             :         m_last_sent_velocity(0,0,0),
     134             :         m_last_sent_position_timer(0),
     135             :         m_last_sent_move_precision(0),
     136             :         m_armor_groups_sent(false),
     137             :         m_animation_speed(0),
     138             :         m_animation_blend(0),
     139             :         m_animation_loop(true),
     140             :         m_animation_sent(false),
     141             :         m_bone_position_sent(false),
     142             :         m_attachment_parent_id(0),
     143           1 :         m_attachment_sent(false)
     144             : {
     145             :         // Only register type if no environment supplied
     146           1 :         if(env == NULL){
     147           1 :                 ServerActiveObject::registerType(getType(), create);
     148           1 :                 return;
     149             :         }
     150             : 
     151             :         // Initialize something to armor groups
     152           0 :         m_armor_groups["fleshy"] = 100;
     153             : }
     154             : 
     155           2 : LuaEntitySAO::~LuaEntitySAO()
     156             : {
     157           1 :         if(m_registered){
     158           0 :                 m_env->getScriptIface()->luaentity_Remove(m_id);
     159             :         }
     160           1 : }
     161             : 
     162           0 : void LuaEntitySAO::addedToEnvironment(u32 dtime_s)
     163             : {
     164           0 :         ServerActiveObject::addedToEnvironment(dtime_s);
     165             : 
     166             :         // Create entity from name
     167           0 :         m_registered = m_env->getScriptIface()->
     168           0 :                 luaentity_Add(m_id, m_init_name.c_str());
     169             : 
     170           0 :         if(m_registered){
     171             :                 // Get properties
     172           0 :                 m_env->getScriptIface()->
     173           0 :                         luaentity_GetProperties(m_id, &m_prop);
     174             :                 // Initialize HP from properties
     175           0 :                 m_hp = m_prop.hp_max;
     176             :                 // Activate entity, supplying serialized state
     177           0 :                 m_env->getScriptIface()->
     178           0 :                         luaentity_Activate(m_id, m_init_state.c_str(), dtime_s);
     179             :         }
     180           0 : }
     181             : 
     182           0 : ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos,
     183             :                 const std::string &data)
     184             : {
     185           0 :         std::string name;
     186           0 :         std::string state;
     187           0 :         s16 hp = 1;
     188           0 :         v3f velocity;
     189           0 :         float yaw = 0;
     190           0 :         if(data != ""){
     191           0 :                 std::istringstream is(data, std::ios::binary);
     192             :                 // read version
     193           0 :                 u8 version = readU8(is);
     194             :                 // check if version is supported
     195           0 :                 if(version == 0){
     196           0 :                         name = deSerializeString(is);
     197           0 :                         state = deSerializeLongString(is);
     198             :                 }
     199           0 :                 else if(version == 1){
     200           0 :                         name = deSerializeString(is);
     201           0 :                         state = deSerializeLongString(is);
     202           0 :                         hp = readS16(is);
     203           0 :                         velocity = readV3F1000(is);
     204           0 :                         yaw = readF1000(is);
     205             :                 }
     206             :         }
     207             :         // create object
     208           0 :         infostream<<"LuaEntitySAO::create(name=\""<<name<<"\" state=\""
     209           0 :                         <<state<<"\")"<<std::endl;
     210           0 :         LuaEntitySAO *sao = new LuaEntitySAO(env, pos, name, state);
     211           0 :         sao->m_hp = hp;
     212           0 :         sao->m_velocity = velocity;
     213           0 :         sao->m_yaw = yaw;
     214           0 :         return sao;
     215             : }
     216             : 
     217           0 : bool LuaEntitySAO::isAttached()
     218             : {
     219           0 :         if(!m_attachment_parent_id)
     220           0 :                 return false;
     221             :         // Check if the parent still exists
     222           0 :         ServerActiveObject *obj = m_env->getActiveObject(m_attachment_parent_id);
     223           0 :         if(obj)
     224           0 :                 return true;
     225           0 :         return false;
     226             : }
     227             : 
     228           0 : void LuaEntitySAO::step(float dtime, bool send_recommended)
     229             : {
     230           0 :         if(!m_properties_sent)
     231             :         {
     232           0 :                 m_properties_sent = true;
     233           0 :                 std::string str = getPropertyPacket();
     234             :                 // create message and add to list
     235           0 :                 ActiveObjectMessage aom(getId(), true, str);
     236           0 :                 m_messages_out.push(aom);
     237             :         }
     238             : 
     239             :         // If attached, check that our parent is still there. If it isn't, detach.
     240           0 :         if(m_attachment_parent_id && !isAttached())
     241             :         {
     242           0 :                 m_attachment_parent_id = 0;
     243           0 :                 m_attachment_bone = "";
     244           0 :                 m_attachment_position = v3f(0,0,0);
     245           0 :                 m_attachment_rotation = v3f(0,0,0);
     246           0 :                 sendPosition(false, true);
     247             :         }
     248             : 
     249           0 :         m_last_sent_position_timer += dtime;
     250             : 
     251             :         // Each frame, parent position is copied if the object is attached, otherwise it's calculated normally
     252             :         // If the object gets detached this comes into effect automatically from the last known origin
     253           0 :         if(isAttached())
     254             :         {
     255           0 :                 v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition();
     256           0 :                 m_base_position = pos;
     257           0 :                 m_velocity = v3f(0,0,0);
     258           0 :                 m_acceleration = v3f(0,0,0);
     259             :         }
     260             :         else
     261             :         {
     262           0 :                 if(m_prop.physical){
     263           0 :                         core::aabbox3d<f32> box = m_prop.collisionbox;
     264           0 :                         box.MinEdge *= BS;
     265           0 :                         box.MaxEdge *= BS;
     266           0 :                         collisionMoveResult moveresult;
     267           0 :                         f32 pos_max_d = BS*0.25; // Distance per iteration
     268           0 :                         v3f p_pos = m_base_position;
     269           0 :                         v3f p_velocity = m_velocity;
     270           0 :                         v3f p_acceleration = m_acceleration;
     271           0 :                         moveresult = collisionMoveSimple(m_env,m_env->getGameDef(),
     272             :                                         pos_max_d, box, m_prop.stepheight, dtime,
     273             :                                         p_pos, p_velocity, p_acceleration,
     274           0 :                                         this, m_prop.collideWithObjects);
     275             : 
     276             :                         // Apply results
     277           0 :                         m_base_position = p_pos;
     278           0 :                         m_velocity = p_velocity;
     279           0 :                         m_acceleration = p_acceleration;
     280             :                 } else {
     281           0 :                         m_base_position += dtime * m_velocity + 0.5 * dtime
     282           0 :                                         * dtime * m_acceleration;
     283           0 :                         m_velocity += dtime * m_acceleration;
     284             :                 }
     285             : 
     286           0 :                 if((m_prop.automatic_face_movement_dir) &&
     287           0 :                                 (fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)){
     288           0 :                         m_yaw = atan2(m_velocity.Z,m_velocity.X) * 180 / M_PI + m_prop.automatic_face_movement_dir_offset;
     289             :                 }
     290             :         }
     291             : 
     292           0 :         if(m_registered){
     293           0 :                 m_env->getScriptIface()->luaentity_Step(m_id, dtime);
     294             :         }
     295             : 
     296           0 :         if(send_recommended == false)
     297           0 :                 return;
     298             : 
     299           0 :         if(!isAttached())
     300             :         {
     301             :                 // TODO: force send when acceleration changes enough?
     302           0 :                 float minchange = 0.2*BS;
     303           0 :                 if(m_last_sent_position_timer > 1.0){
     304           0 :                         minchange = 0.01*BS;
     305           0 :                 } else if(m_last_sent_position_timer > 0.2){
     306           0 :                         minchange = 0.05*BS;
     307             :                 }
     308           0 :                 float move_d = m_base_position.getDistanceFrom(m_last_sent_position);
     309           0 :                 move_d += m_last_sent_move_precision;
     310           0 :                 float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity);
     311           0 :                 if(move_d > minchange || vel_d > minchange ||
     312           0 :                                 fabs(m_yaw - m_last_sent_yaw) > 1.0){
     313           0 :                         sendPosition(true, false);
     314             :                 }
     315             :         }
     316             : 
     317           0 :         if(m_armor_groups_sent == false){
     318           0 :                 m_armor_groups_sent = true;
     319             :                 std::string str = gob_cmd_update_armor_groups(
     320           0 :                                 m_armor_groups);
     321             :                 // create message and add to list
     322           0 :                 ActiveObjectMessage aom(getId(), true, str);
     323           0 :                 m_messages_out.push(aom);
     324             :         }
     325             : 
     326           0 :         if(m_animation_sent == false){
     327           0 :                 m_animation_sent = true;
     328             :                 std::string str = gob_cmd_update_animation(
     329           0 :                         m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop);
     330             :                 // create message and add to list
     331           0 :                 ActiveObjectMessage aom(getId(), true, str);
     332           0 :                 m_messages_out.push(aom);
     333             :         }
     334             : 
     335           0 :         if(m_bone_position_sent == false){
     336           0 :                 m_bone_position_sent = true;
     337           0 :                 for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
     338           0 :                         std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y);
     339             :                         // create message and add to list
     340           0 :                         ActiveObjectMessage aom(getId(), true, str);
     341           0 :                         m_messages_out.push(aom);
     342             :                 }
     343             :         }
     344             : 
     345           0 :         if(m_attachment_sent == false){
     346           0 :                 m_attachment_sent = true;
     347           0 :                 std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation);
     348             :                 // create message and add to list
     349           0 :                 ActiveObjectMessage aom(getId(), true, str);
     350           0 :                 m_messages_out.push(aom);
     351             :         }
     352             : }
     353             : 
     354           0 : std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version)
     355             : {
     356           0 :         std::ostringstream os(std::ios::binary);
     357             : 
     358           0 :         if(protocol_version >= 14)
     359             :         {
     360           0 :                 writeU8(os, 1); // version
     361           0 :                 os<<serializeString(""); // name
     362           0 :                 writeU8(os, 0); // is_player
     363           0 :                 writeS16(os, getId()); //id
     364           0 :                 writeV3F1000(os, m_base_position);
     365           0 :                 writeF1000(os, m_yaw);
     366           0 :                 writeS16(os, m_hp);
     367             : 
     368           0 :                 writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
     369           0 :                 os<<serializeLongString(getPropertyPacket()); // message 1
     370           0 :                 os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
     371           0 :                 os<<serializeLongString(gob_cmd_update_animation(
     372           0 :                         m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3
     373           0 :                 for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
     374           0 :                         os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
     375             :                 }
     376           0 :                 os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
     377             :         }
     378             :         else
     379             :         {
     380           0 :                 writeU8(os, 0); // version
     381           0 :                 os<<serializeString(""); // name
     382           0 :                 writeU8(os, 0); // is_player
     383           0 :                 writeV3F1000(os, m_base_position);
     384           0 :                 writeF1000(os, m_yaw);
     385           0 :                 writeS16(os, m_hp);
     386           0 :                 writeU8(os, 2); // number of messages stuffed in here
     387           0 :                 os<<serializeLongString(getPropertyPacket()); // message 1
     388           0 :                 os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
     389             :         }
     390             : 
     391             :         // return result
     392           0 :         return os.str();
     393             : }
     394             : 
     395           0 : std::string LuaEntitySAO::getStaticData()
     396             : {
     397           0 :         verbosestream<<__FUNCTION_NAME<<std::endl;
     398           0 :         std::ostringstream os(std::ios::binary);
     399             :         // version
     400           0 :         writeU8(os, 1);
     401             :         // name
     402           0 :         os<<serializeString(m_init_name);
     403             :         // state
     404           0 :         if(m_registered){
     405           0 :                 std::string state = m_env->getScriptIface()->
     406           0 :                         luaentity_GetStaticdata(m_id);
     407           0 :                 os<<serializeLongString(state);
     408             :         } else {
     409           0 :                 os<<serializeLongString(m_init_state);
     410             :         }
     411             :         // hp
     412           0 :         writeS16(os, m_hp);
     413             :         // velocity
     414           0 :         writeV3F1000(os, m_velocity);
     415             :         // yaw
     416           0 :         writeF1000(os, m_yaw);
     417           0 :         return os.str();
     418             : }
     419             : 
     420           0 : int LuaEntitySAO::punch(v3f dir,
     421             :                 const ToolCapabilities *toolcap,
     422             :                 ServerActiveObject *puncher,
     423             :                 float time_from_last_punch)
     424             : {
     425           0 :         if (!m_registered){
     426             :                 // Delete unknown LuaEntities when punched
     427           0 :                 m_removed = true;
     428           0 :                 return 0;
     429             :         }
     430             : 
     431             :         // It's best that attachments cannot be punched
     432           0 :         if (isAttached())
     433           0 :                 return 0;
     434             : 
     435           0 :         ItemStack *punchitem = NULL;
     436           0 :         ItemStack punchitem_static;
     437           0 :         if (puncher) {
     438           0 :                 punchitem_static = puncher->getWieldedItem();
     439           0 :                 punchitem = &punchitem_static;
     440             :         }
     441             : 
     442             :         PunchDamageResult result = getPunchDamage(
     443             :                         m_armor_groups,
     444             :                         toolcap,
     445             :                         punchitem,
     446           0 :                         time_from_last_punch);
     447             : 
     448           0 :         if (result.did_punch) {
     449           0 :                 setHP(getHP() - result.damage);
     450             : 
     451           0 :                 if (result.damage > 0) {
     452           0 :                         std::string punchername = puncher ? puncher->getDescription() : "nil";
     453             : 
     454           0 :                         actionstream << getDescription() << " punched by "
     455           0 :                                         << punchername << ", damage " << result.damage
     456           0 :                                         << " hp, health now " << getHP() << " hp" << std::endl;
     457             :                 }
     458             : 
     459           0 :                 std::string str = gob_cmd_punched(result.damage, getHP());
     460             :                 // create message and add to list
     461           0 :                 ActiveObjectMessage aom(getId(), true, str);
     462           0 :                 m_messages_out.push(aom);
     463             :         }
     464             : 
     465           0 :         if (getHP() == 0)
     466           0 :                 m_removed = true;
     467             : 
     468           0 :         m_env->getScriptIface()->luaentity_Punch(m_id, puncher,
     469           0 :                         time_from_last_punch, toolcap, dir);
     470             : 
     471           0 :         return result.wear;
     472             : }
     473             : 
     474           0 : void LuaEntitySAO::rightClick(ServerActiveObject *clicker)
     475             : {
     476           0 :         if (!m_registered)
     477           0 :                 return;
     478             :         // It's best that attachments cannot be clicked
     479           0 :         if (isAttached())
     480           0 :                 return;
     481           0 :         m_env->getScriptIface()->luaentity_Rightclick(m_id, clicker);
     482             : }
     483             : 
     484           0 : void LuaEntitySAO::setPos(v3f pos)
     485             : {
     486           0 :         if(isAttached())
     487           0 :                 return;
     488           0 :         m_base_position = pos;
     489           0 :         sendPosition(false, true);
     490             : }
     491             : 
     492           0 : void LuaEntitySAO::moveTo(v3f pos, bool continuous)
     493             : {
     494           0 :         if(isAttached())
     495           0 :                 return;
     496           0 :         m_base_position = pos;
     497           0 :         if(!continuous)
     498           0 :                 sendPosition(true, true);
     499             : }
     500             : 
     501           0 : float LuaEntitySAO::getMinimumSavedMovement()
     502             : {
     503           0 :         return 0.1 * BS;
     504             : }
     505             : 
     506           0 : std::string LuaEntitySAO::getDescription()
     507             : {
     508           0 :         std::ostringstream os(std::ios::binary);
     509           0 :         os<<"LuaEntitySAO at (";
     510           0 :         os<<(m_base_position.X/BS)<<",";
     511           0 :         os<<(m_base_position.Y/BS)<<",";
     512           0 :         os<<(m_base_position.Z/BS);
     513           0 :         os<<")";
     514           0 :         return os.str();
     515             : }
     516             : 
     517           0 : void LuaEntitySAO::setHP(s16 hp)
     518             : {
     519           0 :         if(hp < 0) hp = 0;
     520           0 :         m_hp = hp;
     521           0 : }
     522             : 
     523           0 : s16 LuaEntitySAO::getHP() const
     524             : {
     525           0 :         return m_hp;
     526             : }
     527             : 
     528           0 : void LuaEntitySAO::setArmorGroups(const ItemGroupList &armor_groups)
     529             : {
     530           0 :         m_armor_groups = armor_groups;
     531           0 :         m_armor_groups_sent = false;
     532           0 : }
     533             : 
     534           0 : ItemGroupList LuaEntitySAO::getArmorGroups()
     535             : {
     536           0 :         return m_armor_groups;
     537             : }
     538             : 
     539           0 : void LuaEntitySAO::setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop)
     540             : {
     541           0 :         m_animation_range = frame_range;
     542           0 :         m_animation_speed = frame_speed;
     543           0 :         m_animation_blend = frame_blend;
     544           0 :         m_animation_loop = frame_loop;
     545           0 :         m_animation_sent = false;
     546           0 : }
     547             : 
     548           0 : void LuaEntitySAO::getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend, bool *frame_loop)
     549             : {
     550           0 :         *frame_range = m_animation_range;
     551           0 :         *frame_speed = m_animation_speed;
     552           0 :         *frame_blend = m_animation_blend;
     553           0 :         *frame_loop = m_animation_loop;
     554           0 : }
     555             : 
     556           0 : void LuaEntitySAO::setBonePosition(const std::string &bone, v3f position, v3f rotation)
     557             : {
     558           0 :         m_bone_position[bone] = core::vector2d<v3f>(position, rotation);
     559           0 :         m_bone_position_sent = false;
     560           0 : }
     561             : 
     562           0 : void LuaEntitySAO::getBonePosition(const std::string &bone, v3f *position, v3f *rotation)
     563             : {
     564           0 :         *position = m_bone_position[bone].X;
     565           0 :         *rotation = m_bone_position[bone].Y;
     566           0 : }
     567             : 
     568           0 : void LuaEntitySAO::setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation)
     569             : {
     570             :         // Attachments need to be handled on both the server and client.
     571             :         // If we just attach on the server, we can only copy the position of the parent. Attachments
     572             :         // are still sent to clients at an interval so players might see them lagging, plus we can't
     573             :         // read and attach to skeletal bones.
     574             :         // If we just attach on the client, the server still sees the child at its original location.
     575             :         // This breaks some things so we also give the server the most accurate representation
     576             :         // even if players only see the client changes.
     577             : 
     578           0 :         m_attachment_parent_id = parent_id;
     579           0 :         m_attachment_bone = bone;
     580           0 :         m_attachment_position = position;
     581           0 :         m_attachment_rotation = rotation;
     582           0 :         m_attachment_sent = false;
     583           0 : }
     584             : 
     585           0 : void LuaEntitySAO::getAttachment(int *parent_id, std::string *bone, v3f *position,
     586             :         v3f *rotation)
     587             : {
     588           0 :         *parent_id = m_attachment_parent_id;
     589           0 :         *bone = m_attachment_bone;
     590           0 :         *position = m_attachment_position;
     591           0 :         *rotation = m_attachment_rotation;
     592           0 : }
     593             : 
     594           0 : ObjectProperties* LuaEntitySAO::accessObjectProperties()
     595             : {
     596           0 :         return &m_prop;
     597             : }
     598             : 
     599           0 : void LuaEntitySAO::notifyObjectPropertiesModified()
     600             : {
     601           0 :         m_properties_sent = false;
     602           0 : }
     603             : 
     604           0 : void LuaEntitySAO::setVelocity(v3f velocity)
     605             : {
     606           0 :         m_velocity = velocity;
     607           0 : }
     608             : 
     609           0 : v3f LuaEntitySAO::getVelocity()
     610             : {
     611           0 :         return m_velocity;
     612             : }
     613             : 
     614           0 : void LuaEntitySAO::setAcceleration(v3f acceleration)
     615             : {
     616           0 :         m_acceleration = acceleration;
     617           0 : }
     618             : 
     619           0 : v3f LuaEntitySAO::getAcceleration()
     620             : {
     621           0 :         return m_acceleration;
     622             : }
     623             : 
     624           0 : void LuaEntitySAO::setYaw(float yaw)
     625             : {
     626           0 :         m_yaw = yaw;
     627           0 : }
     628             : 
     629           0 : float LuaEntitySAO::getYaw()
     630             : {
     631           0 :         return m_yaw;
     632             : }
     633             : 
     634           0 : void LuaEntitySAO::setTextureMod(const std::string &mod)
     635             : {
     636           0 :         std::string str = gob_cmd_set_texture_mod(mod);
     637             :         // create message and add to list
     638           0 :         ActiveObjectMessage aom(getId(), true, str);
     639           0 :         m_messages_out.push(aom);
     640           0 : }
     641             : 
     642           0 : void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength,
     643             :                 bool select_horiz_by_yawpitch)
     644             : {
     645             :         std::string str = gob_cmd_set_sprite(
     646             :                 p,
     647             :                 num_frames,
     648             :                 framelength,
     649             :                 select_horiz_by_yawpitch
     650           0 :         );
     651             :         // create message and add to list
     652           0 :         ActiveObjectMessage aom(getId(), true, str);
     653           0 :         m_messages_out.push(aom);
     654           0 : }
     655             : 
     656           0 : std::string LuaEntitySAO::getName()
     657             : {
     658           0 :         return m_init_name;
     659             : }
     660             : 
     661           0 : std::string LuaEntitySAO::getPropertyPacket()
     662             : {
     663           0 :         return gob_cmd_set_properties(m_prop);
     664             : }
     665             : 
     666           0 : void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
     667             : {
     668             :         // If the object is attached client-side, don't waste bandwidth sending its position to clients
     669           0 :         if(isAttached())
     670           0 :                 return;
     671             : 
     672           0 :         m_last_sent_move_precision = m_base_position.getDistanceFrom(
     673           0 :                         m_last_sent_position);
     674           0 :         m_last_sent_position_timer = 0;
     675           0 :         m_last_sent_yaw = m_yaw;
     676           0 :         m_last_sent_position = m_base_position;
     677           0 :         m_last_sent_velocity = m_velocity;
     678             :         //m_last_sent_acceleration = m_acceleration;
     679             : 
     680           0 :         float update_interval = m_env->getSendRecommendedInterval();
     681             : 
     682             :         std::string str = gob_cmd_update_position(
     683             :                 m_base_position,
     684             :                 m_velocity,
     685             :                 m_acceleration,
     686             :                 m_yaw,
     687             :                 do_interpolate,
     688             :                 is_movement_end,
     689             :                 update_interval
     690           0 :         );
     691             :         // create message and add to list
     692           0 :         ActiveObjectMessage aom(getId(), false, str);
     693           0 :         m_messages_out.push(aom);
     694             : }
     695             : 
     696           0 : bool LuaEntitySAO::getCollisionBox(aabb3f *toset) {
     697           0 :         if (m_prop.physical)
     698             :         {
     699             :                 //update collision box
     700           0 :                 toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
     701           0 :                 toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
     702             : 
     703           0 :                 toset->MinEdge += m_base_position;
     704           0 :                 toset->MaxEdge += m_base_position;
     705             : 
     706           0 :                 return true;
     707             :         }
     708             : 
     709           0 :         return false;
     710             : }
     711             : 
     712           0 : bool LuaEntitySAO::collideWithObjects(){
     713           0 :         return m_prop.collideWithObjects;
     714             : }
     715             : 
     716             : /*
     717             :         PlayerSAO
     718             : */
     719             : 
     720             : // No prototype, PlayerSAO does not need to be deserialized
     721             : 
     722           0 : PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
     723             :                 const std::set<std::string> &privs, bool is_singleplayer):
     724             :         ServerActiveObject(env_, v3f(0,0,0)),
     725             :         m_player(player_),
     726             :         m_peer_id(peer_id_),
     727             :         m_inventory(NULL),
     728             :         m_damage(0),
     729             :         m_last_good_position(0,0,0),
     730             :         m_time_from_last_punch(0),
     731             :         m_nocheat_dig_pos(32767, 32767, 32767),
     732             :         m_nocheat_dig_time(0),
     733             :         m_wield_index(0),
     734             :         m_position_not_sent(false),
     735             :         m_armor_groups_sent(false),
     736             :         m_properties_sent(true),
     737             :         m_privs(privs),
     738             :         m_is_singleplayer(is_singleplayer),
     739             :         m_animation_speed(0),
     740             :         m_animation_blend(0),
     741             :         m_animation_loop(true),
     742             :         m_animation_sent(false),
     743             :         m_bone_position_sent(false),
     744             :         m_attachment_parent_id(0),
     745             :         m_attachment_sent(false),
     746             :         m_nametag_color(video::SColor(255, 255, 255, 255)),
     747             :         m_nametag_sent(false),
     748             :         // public
     749             :         m_physics_override_speed(1),
     750             :         m_physics_override_jump(1),
     751             :         m_physics_override_gravity(1),
     752             :         m_physics_override_sneak(true),
     753             :         m_physics_override_sneak_glitch(true),
     754           0 :         m_physics_override_sent(false)
     755             : {
     756             :         assert(m_player);       // pre-condition
     757             :         assert(m_peer_id != 0); // pre-condition
     758           0 :         setBasePosition(m_player->getPosition());
     759           0 :         m_inventory = &m_player->inventory;
     760           0 :         m_armor_groups["fleshy"] = 100;
     761             : 
     762           0 :         m_prop.hp_max = PLAYER_MAX_HP;
     763           0 :         m_prop.physical = false;
     764           0 :         m_prop.weight = 75;
     765           0 :         m_prop.collisionbox = core::aabbox3d<f32>(-1/3.,-1.0,-1/3., 1/3.,1.0,1/3.);
     766             :         // start of default appearance, this should be overwritten by LUA
     767           0 :         m_prop.visual = "upright_sprite";
     768           0 :         m_prop.visual_size = v2f(1, 2);
     769           0 :         m_prop.textures.clear();
     770           0 :         m_prop.textures.push_back("player.png");
     771           0 :         m_prop.textures.push_back("player_back.png");
     772           0 :         m_prop.colors.clear();
     773           0 :         m_prop.colors.push_back(video::SColor(255, 255, 255, 255));
     774           0 :         m_prop.spritediv = v2s16(1,1);
     775             :         // end of default appearance
     776           0 :         m_prop.is_visible = true;
     777           0 :         m_prop.makes_footstep_sound = true;
     778           0 : }
     779             : 
     780           0 : PlayerSAO::~PlayerSAO()
     781             : {
     782           0 :         if(m_inventory != &m_player->inventory)
     783           0 :                 delete m_inventory;
     784             : 
     785           0 : }
     786             : 
     787           0 : std::string PlayerSAO::getDescription()
     788             : {
     789           0 :         return std::string("player ") + m_player->getName();
     790             : }
     791             : 
     792             : // Called after id has been set and has been inserted in environment
     793           0 : void PlayerSAO::addedToEnvironment(u32 dtime_s)
     794             : {
     795           0 :         ServerActiveObject::addedToEnvironment(dtime_s);
     796           0 :         ServerActiveObject::setBasePosition(m_player->getPosition());
     797           0 :         m_player->setPlayerSAO(this);
     798           0 :         m_player->peer_id = m_peer_id;
     799           0 :         m_last_good_position = m_player->getPosition();
     800           0 : }
     801             : 
     802             : // Called before removing from environment
     803           0 : void PlayerSAO::removingFromEnvironment()
     804             : {
     805           0 :         ServerActiveObject::removingFromEnvironment();
     806           0 :         if(m_player->getPlayerSAO() == this)
     807             :         {
     808           0 :                 m_player->setPlayerSAO(NULL);
     809           0 :                 m_player->peer_id = 0;
     810           0 :                 m_env->savePlayer(m_player->getName());
     811           0 :                 m_env->removePlayer(m_player->getName());
     812             :         }
     813           0 : }
     814             : 
     815           0 : bool PlayerSAO::isStaticAllowed() const
     816             : {
     817           0 :         return false;
     818             : }
     819             : 
     820           0 : std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
     821             : {
     822           0 :         std::ostringstream os(std::ios::binary);
     823             : 
     824           0 :         if(protocol_version >= 15)
     825             :         {
     826           0 :                 writeU8(os, 1); // version
     827           0 :                 os<<serializeString(m_player->getName()); // name
     828           0 :                 writeU8(os, 1); // is_player
     829           0 :                 writeS16(os, getId()); //id
     830           0 :                 writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0));
     831           0 :                 writeF1000(os, m_player->getYaw());
     832           0 :                 writeS16(os, getHP());
     833             : 
     834           0 :                 writeU8(os, 6 + m_bone_position.size()); // number of messages stuffed in here
     835           0 :                 os<<serializeLongString(getPropertyPacket()); // message 1
     836           0 :                 os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
     837           0 :                 os<<serializeLongString(gob_cmd_update_animation(
     838           0 :                         m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3
     839           0 :                 for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
     840           0 :                         os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
     841             :                 }
     842           0 :                 os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
     843           0 :                 os<<serializeLongString(gob_cmd_update_physics_override(m_physics_override_speed,
     844           0 :                                 m_physics_override_jump, m_physics_override_gravity, m_physics_override_sneak,
     845           0 :                                 m_physics_override_sneak_glitch)); // 5
     846           0 :                 os << serializeLongString(gob_cmd_update_nametag_attributes(m_nametag_color)); // 6
     847             :         }
     848             :         else
     849             :         {
     850           0 :                 writeU8(os, 0); // version
     851           0 :                 os<<serializeString(m_player->getName()); // name
     852           0 :                 writeU8(os, 1); // is_player
     853           0 :                 writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0));
     854           0 :                 writeF1000(os, m_player->getYaw());
     855           0 :                 writeS16(os, getHP());
     856           0 :                 writeU8(os, 2); // number of messages stuffed in here
     857           0 :                 os<<serializeLongString(getPropertyPacket()); // message 1
     858           0 :                 os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
     859             :         }
     860             : 
     861             :         // return result
     862           0 :         return os.str();
     863             : }
     864             : 
     865           0 : std::string PlayerSAO::getStaticData()
     866             : {
     867           0 :         FATAL_ERROR("Deprecated function (?)");
     868             :         return "";
     869             : }
     870             : 
     871           0 : bool PlayerSAO::isAttached()
     872             : {
     873           0 :         if(!m_attachment_parent_id)
     874           0 :                 return false;
     875             :         // Check if the parent still exists
     876           0 :         ServerActiveObject *obj = m_env->getActiveObject(m_attachment_parent_id);
     877           0 :         if(obj)
     878           0 :                 return true;
     879           0 :         return false;
     880             : }
     881             : 
     882           0 : void PlayerSAO::step(float dtime, bool send_recommended)
     883             : {
     884           0 :         if(!m_properties_sent)
     885             :         {
     886           0 :                 m_properties_sent = true;
     887           0 :                 std::string str = getPropertyPacket();
     888             :                 // create message and add to list
     889           0 :                 ActiveObjectMessage aom(getId(), true, str);
     890           0 :                 m_messages_out.push(aom);
     891             :         }
     892             : 
     893             :         // If attached, check that our parent is still there. If it isn't, detach.
     894           0 :         if(m_attachment_parent_id && !isAttached())
     895             :         {
     896           0 :                 m_attachment_parent_id = 0;
     897           0 :                 m_attachment_bone = "";
     898           0 :                 m_attachment_position = v3f(0,0,0);
     899           0 :                 m_attachment_rotation = v3f(0,0,0);
     900           0 :                 m_player->setPosition(m_last_good_position);
     901           0 :                 ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
     902             :         }
     903             : 
     904             :         //dstream<<"PlayerSAO::step: dtime: "<<dtime<<std::endl;
     905             : 
     906             :         // Set lag pool maximums based on estimated lag
     907           0 :         const float LAG_POOL_MIN = 5.0;
     908           0 :         float lag_pool_max = m_env->getMaxLagEstimate() * 2.0;
     909           0 :         if(lag_pool_max < LAG_POOL_MIN)
     910           0 :                 lag_pool_max = LAG_POOL_MIN;
     911           0 :         m_dig_pool.setMax(lag_pool_max);
     912           0 :         m_move_pool.setMax(lag_pool_max);
     913             : 
     914             :         // Increment cheat prevention timers
     915           0 :         m_dig_pool.add(dtime);
     916           0 :         m_move_pool.add(dtime);
     917           0 :         m_time_from_last_punch += dtime;
     918           0 :         m_nocheat_dig_time += dtime;
     919             : 
     920             :         // Each frame, parent position is copied if the object is attached, otherwise it's calculated normally
     921             :         // If the object gets detached this comes into effect automatically from the last known origin
     922           0 :         if(isAttached())
     923             :         {
     924           0 :                 v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition();
     925           0 :                 m_last_good_position = pos;
     926           0 :                 m_player->setPosition(pos);
     927             :         }
     928             : 
     929           0 :         if(send_recommended == false)
     930           0 :                 return;
     931             : 
     932             :         // If the object is attached client-side, don't waste bandwidth sending its position to clients
     933           0 :         if(m_position_not_sent && !isAttached())
     934             :         {
     935           0 :                 m_position_not_sent = false;
     936           0 :                 float update_interval = m_env->getSendRecommendedInterval();
     937           0 :                 v3f pos;
     938           0 :                 if(isAttached()) // Just in case we ever do send attachment position too
     939           0 :                         pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition();
     940             :                 else
     941           0 :                         pos = m_player->getPosition() + v3f(0,BS*1,0);
     942             :                 std::string str = gob_cmd_update_position(
     943             :                         pos,
     944             :                         v3f(0,0,0),
     945             :                         v3f(0,0,0),
     946           0 :                         m_player->getYaw(),
     947             :                         true,
     948             :                         false,
     949             :                         update_interval
     950           0 :                 );
     951             :                 // create message and add to list
     952           0 :                 ActiveObjectMessage aom(getId(), false, str);
     953           0 :                 m_messages_out.push(aom);
     954             :         }
     955             : 
     956           0 :         if(m_armor_groups_sent == false) {
     957           0 :                 m_armor_groups_sent = true;
     958             :                 std::string str = gob_cmd_update_armor_groups(
     959           0 :                                 m_armor_groups);
     960             :                 // create message and add to list
     961           0 :                 ActiveObjectMessage aom(getId(), true, str);
     962           0 :                 m_messages_out.push(aom);
     963             :         }
     964             : 
     965           0 :         if(m_physics_override_sent == false){
     966           0 :                 m_physics_override_sent = true;
     967             :                 std::string str = gob_cmd_update_physics_override(m_physics_override_speed,
     968             :                                 m_physics_override_jump, m_physics_override_gravity,
     969           0 :                                 m_physics_override_sneak, m_physics_override_sneak_glitch);
     970             :                 // create message and add to list
     971           0 :                 ActiveObjectMessage aom(getId(), true, str);
     972           0 :                 m_messages_out.push(aom);
     973             :         }
     974             : 
     975           0 :         if(m_animation_sent == false){
     976           0 :                 m_animation_sent = true;
     977             :                 std::string str = gob_cmd_update_animation(
     978           0 :                         m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop);
     979             :                 // create message and add to list
     980           0 :                 ActiveObjectMessage aom(getId(), true, str);
     981           0 :                 m_messages_out.push(aom);
     982             :         }
     983             : 
     984           0 :         if(m_bone_position_sent == false){
     985           0 :                 m_bone_position_sent = true;
     986           0 :                 for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
     987           0 :                         std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y);
     988             :                         // create message and add to list
     989           0 :                         ActiveObjectMessage aom(getId(), true, str);
     990           0 :                         m_messages_out.push(aom);
     991             :                 }
     992             :         }
     993             : 
     994           0 :         if(m_attachment_sent == false){
     995           0 :                 m_attachment_sent = true;
     996           0 :                 std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation);
     997             :                 // create message and add to list
     998           0 :                 ActiveObjectMessage aom(getId(), true, str);
     999           0 :                 m_messages_out.push(aom);
    1000             :         }
    1001             : 
    1002           0 :         if (m_nametag_sent == false) {
    1003           0 :                 m_nametag_sent = true;
    1004           0 :                 std::string str = gob_cmd_update_nametag_attributes(m_nametag_color);
    1005             :                 // create message and add to list
    1006           0 :                 ActiveObjectMessage aom(getId(), true, str);
    1007           0 :                 m_messages_out.push(aom);
    1008             :         }
    1009             : }
    1010             : 
    1011           0 : void PlayerSAO::setBasePosition(const v3f &position)
    1012             : {
    1013             :         // This needs to be ran for attachments too
    1014           0 :         ServerActiveObject::setBasePosition(position);
    1015           0 :         m_position_not_sent = true;
    1016           0 : }
    1017             : 
    1018           0 : void PlayerSAO::setPos(v3f pos)
    1019             : {
    1020           0 :         if(isAttached())
    1021           0 :                 return;
    1022           0 :         m_player->setPosition(pos);
    1023             :         // Movement caused by this command is always valid
    1024           0 :         m_last_good_position = pos;
    1025           0 :         ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
    1026             : }
    1027             : 
    1028           0 : void PlayerSAO::moveTo(v3f pos, bool continuous)
    1029             : {
    1030           0 :         if(isAttached())
    1031           0 :                 return;
    1032           0 :         m_player->setPosition(pos);
    1033             :         // Movement caused by this command is always valid
    1034           0 :         m_last_good_position = pos;
    1035           0 :         ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
    1036             : }
    1037             : 
    1038           0 : void PlayerSAO::setYaw(float yaw)
    1039             : {
    1040           0 :         m_player->setYaw(yaw);
    1041           0 :         ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
    1042           0 : }
    1043             : 
    1044           0 : void PlayerSAO::setPitch(float pitch)
    1045             : {
    1046           0 :         m_player->setPitch(pitch);
    1047           0 :         ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
    1048           0 : }
    1049             : 
    1050           0 : int PlayerSAO::punch(v3f dir,
    1051             :         const ToolCapabilities *toolcap,
    1052             :         ServerActiveObject *puncher,
    1053             :         float time_from_last_punch)
    1054             : {
    1055             :         // It's best that attachments cannot be punched
    1056           0 :         if (isAttached())
    1057           0 :                 return 0;
    1058             : 
    1059           0 :         if (!toolcap)
    1060           0 :                 return 0;
    1061             : 
    1062             :         // No effect if PvP disabled
    1063           0 :         if (g_settings->getBool("enable_pvp") == false) {
    1064           0 :                 if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
    1065           0 :                         std::string str = gob_cmd_punched(0, getHP());
    1066             :                         // create message and add to list
    1067           0 :                         ActiveObjectMessage aom(getId(), true, str);
    1068           0 :                         m_messages_out.push(aom);
    1069           0 :                         return 0;
    1070             :                 }
    1071             :         }
    1072             : 
    1073             :         HitParams hitparams = getHitParams(m_armor_groups, toolcap,
    1074           0 :                         time_from_last_punch);
    1075             : 
    1076           0 :         std::string punchername = "nil";
    1077             : 
    1078           0 :         if (puncher != 0)
    1079           0 :                 punchername = puncher->getDescription();
    1080             : 
    1081           0 :         PlayerSAO *playersao = m_player->getPlayerSAO();
    1082             : 
    1083           0 :         bool damage_handled = m_env->getScriptIface()->on_punchplayer(playersao,
    1084             :                                 puncher, time_from_last_punch, toolcap, dir,
    1085           0 :                                 hitparams.hp);
    1086             : 
    1087           0 :         if (!damage_handled) {
    1088           0 :                 setHP(getHP() - hitparams.hp);
    1089             :         } else { // override client prediction
    1090           0 :                 if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
    1091           0 :                         std::string str = gob_cmd_punched(0, getHP());
    1092             :                         // create message and add to list
    1093           0 :                         ActiveObjectMessage aom(getId(), true, str);
    1094           0 :                         m_messages_out.push(aom);
    1095             :                 }
    1096             :         }
    1097             : 
    1098             : 
    1099           0 :         actionstream << "Player " << m_player->getName() << " punched by "
    1100           0 :                         << punchername;
    1101           0 :         if (!damage_handled) {
    1102           0 :                 actionstream << ", damage " << hitparams.hp << " HP";
    1103             :         } else {
    1104           0 :                 actionstream << ", damage handled by lua";
    1105             :         }
    1106           0 :         actionstream << std::endl;
    1107             : 
    1108           0 :         return hitparams.wear;
    1109             : }
    1110             : 
    1111           0 : void PlayerSAO::rightClick(ServerActiveObject *clicker)
    1112             : {
    1113           0 : }
    1114             : 
    1115           0 : s16 PlayerSAO::getHP() const
    1116             : {
    1117           0 :         return m_player->hp;
    1118             : }
    1119             : 
    1120           0 : s16 PlayerSAO::readDamage()
    1121             : {
    1122           0 :         s16 damage = m_damage;
    1123           0 :         m_damage = 0;
    1124           0 :         return damage;
    1125             : }
    1126             : 
    1127           0 : void PlayerSAO::setHP(s16 hp)
    1128             : {
    1129           0 :         s16 oldhp = m_player->hp;
    1130             : 
    1131           0 :         s16 hp_change = m_env->getScriptIface()->on_player_hpchange(this,
    1132           0 :                 hp - oldhp);
    1133           0 :         if (hp_change == 0)
    1134           0 :                 return;
    1135           0 :         hp = oldhp + hp_change;
    1136             : 
    1137           0 :         if (hp < 0)
    1138           0 :                 hp = 0;
    1139           0 :         else if (hp > PLAYER_MAX_HP)
    1140           0 :                 hp = PLAYER_MAX_HP;
    1141             : 
    1142           0 :         if(hp < oldhp && g_settings->getBool("enable_damage") == false) {
    1143           0 :                 return;
    1144             :         }
    1145             : 
    1146           0 :         m_player->hp = hp;
    1147             : 
    1148           0 :         if (oldhp > hp)
    1149           0 :                 m_damage += (oldhp - hp);
    1150             : 
    1151             :         // Update properties on death
    1152           0 :         if ((hp == 0) != (oldhp == 0))
    1153           0 :                 m_properties_sent = false;
    1154             : }
    1155             : 
    1156           0 : u16 PlayerSAO::getBreath() const
    1157             : {
    1158           0 :         return m_player->getBreath();
    1159             : }
    1160             : 
    1161           0 : void PlayerSAO::setBreath(u16 breath)
    1162             : {
    1163           0 :         m_player->setBreath(breath);
    1164           0 : }
    1165             : 
    1166           0 : void PlayerSAO::setArmorGroups(const ItemGroupList &armor_groups)
    1167             : {
    1168           0 :         m_armor_groups = armor_groups;
    1169           0 :         m_armor_groups_sent = false;
    1170           0 : }
    1171             : 
    1172           0 : ItemGroupList PlayerSAO::getArmorGroups()
    1173             : {
    1174           0 :         return m_armor_groups;
    1175             : }
    1176             : 
    1177           0 : void PlayerSAO::setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop)
    1178             : {
    1179             :         // store these so they can be updated to clients
    1180           0 :         m_animation_range = frame_range;
    1181           0 :         m_animation_speed = frame_speed;
    1182           0 :         m_animation_blend = frame_blend;
    1183           0 :         m_animation_loop = frame_loop;
    1184           0 :         m_animation_sent = false;
    1185           0 : }
    1186             : 
    1187           0 : void PlayerSAO::getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend, bool *frame_loop)
    1188             : {
    1189           0 :         *frame_range = m_animation_range;
    1190           0 :         *frame_speed = m_animation_speed;
    1191           0 :         *frame_blend = m_animation_blend;
    1192           0 :         *frame_loop = m_animation_loop;
    1193           0 : }
    1194             : 
    1195           0 : void PlayerSAO::setBonePosition(const std::string &bone, v3f position, v3f rotation)
    1196             : {
    1197             :         // store these so they can be updated to clients
    1198           0 :         m_bone_position[bone] = core::vector2d<v3f>(position, rotation);
    1199           0 :         m_bone_position_sent = false;
    1200           0 : }
    1201             : 
    1202           0 : void PlayerSAO::getBonePosition(const std::string &bone, v3f *position, v3f *rotation)
    1203             : {
    1204           0 :         *position = m_bone_position[bone].X;
    1205           0 :         *rotation = m_bone_position[bone].Y;
    1206           0 : }
    1207             : 
    1208           0 : void PlayerSAO::setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation)
    1209             : {
    1210             :         // Attachments need to be handled on both the server and client.
    1211             :         // If we just attach on the server, we can only copy the position of the parent. Attachments
    1212             :         // are still sent to clients at an interval so players might see them lagging, plus we can't
    1213             :         // read and attach to skeletal bones.
    1214             :         // If we just attach on the client, the server still sees the child at its original location.
    1215             :         // This breaks some things so we also give the server the most accurate representation
    1216             :         // even if players only see the client changes.
    1217             : 
    1218           0 :         m_attachment_parent_id = parent_id;
    1219           0 :         m_attachment_bone = bone;
    1220           0 :         m_attachment_position = position;
    1221           0 :         m_attachment_rotation = rotation;
    1222           0 :         m_attachment_sent = false;
    1223           0 : }
    1224             : 
    1225           0 : void PlayerSAO::getAttachment(int *parent_id, std::string *bone, v3f *position,
    1226             :         v3f *rotation)
    1227             : {
    1228           0 :         *parent_id = m_attachment_parent_id;
    1229           0 :         *bone = m_attachment_bone;
    1230           0 :         *position = m_attachment_position;
    1231           0 :         *rotation = m_attachment_rotation;
    1232           0 : }
    1233             : 
    1234           0 : ObjectProperties* PlayerSAO::accessObjectProperties()
    1235             : {
    1236           0 :         return &m_prop;
    1237             : }
    1238             : 
    1239           0 : void PlayerSAO::notifyObjectPropertiesModified()
    1240             : {
    1241           0 :         m_properties_sent = false;
    1242           0 : }
    1243             : 
    1244           0 : void PlayerSAO::setNametagColor(video::SColor color)
    1245             : {
    1246           0 :         m_nametag_color = color;
    1247           0 :         m_nametag_sent = false;
    1248           0 : }
    1249             : 
    1250           0 : video::SColor PlayerSAO::getNametagColor()
    1251             : {
    1252           0 :         return m_nametag_color;
    1253             : }
    1254             : 
    1255           0 : Inventory* PlayerSAO::getInventory()
    1256             : {
    1257           0 :         return m_inventory;
    1258             : }
    1259           0 : const Inventory* PlayerSAO::getInventory() const
    1260             : {
    1261           0 :         return m_inventory;
    1262             : }
    1263             : 
    1264           0 : InventoryLocation PlayerSAO::getInventoryLocation() const
    1265             : {
    1266           0 :         InventoryLocation loc;
    1267           0 :         loc.setPlayer(m_player->getName());
    1268           0 :         return loc;
    1269             : }
    1270             : 
    1271           0 : std::string PlayerSAO::getWieldList() const
    1272             : {
    1273           0 :         return "main";
    1274             : }
    1275             : 
    1276           0 : int PlayerSAO::getWieldIndex() const
    1277             : {
    1278           0 :         return m_wield_index;
    1279             : }
    1280             : 
    1281           0 : void PlayerSAO::setWieldIndex(int i)
    1282             : {
    1283           0 :         if(i != m_wield_index) {
    1284           0 :                 m_wield_index = i;
    1285             :         }
    1286           0 : }
    1287             : 
    1288           0 : void PlayerSAO::disconnected()
    1289             : {
    1290           0 :         m_peer_id = 0;
    1291           0 :         m_removed = true;
    1292           0 :         if(m_player->getPlayerSAO() == this)
    1293             :         {
    1294           0 :                 m_player->setPlayerSAO(NULL);
    1295           0 :                 m_player->peer_id = 0;
    1296             :         }
    1297           0 : }
    1298             : 
    1299           0 : std::string PlayerSAO::getPropertyPacket()
    1300             : {
    1301           0 :         m_prop.is_visible = (true);
    1302           0 :         return gob_cmd_set_properties(m_prop);
    1303             : }
    1304             : 
    1305           0 : bool PlayerSAO::checkMovementCheat()
    1306             : {
    1307           0 :         bool cheated = false;
    1308           0 :         if(isAttached() || m_is_singleplayer ||
    1309           0 :                         g_settings->getBool("disable_anticheat"))
    1310             :         {
    1311           0 :                 m_last_good_position = m_player->getPosition();
    1312             :         }
    1313             :         else
    1314             :         {
    1315             :                 /*
    1316             :                         Check player movements
    1317             : 
    1318             :                         NOTE: Actually the server should handle player physics like the
    1319             :                         client does and compare player's position to what is calculated
    1320             :                         on our side. This is required when eg. players fly due to an
    1321             :                         explosion. Altough a node-based alternative might be possible
    1322             :                         too, and much more lightweight.
    1323             :                 */
    1324             : 
    1325           0 :                 float player_max_speed = 0;
    1326           0 :                 if(m_privs.count("fast") != 0){
    1327             :                         // Fast speed
    1328           0 :                         player_max_speed = m_player->movement_speed_fast;
    1329             :                 } else {
    1330             :                         // Normal speed
    1331           0 :                         player_max_speed = m_player->movement_speed_walk;
    1332             :                 }
    1333             :                 // Tolerance. With the lag pool we shouldn't need it.
    1334             :                 //player_max_speed *= 2.5;
    1335             :                 //player_max_speed_up *= 2.5;
    1336             : 
    1337           0 :                 v3f diff = (m_player->getPosition() - m_last_good_position);
    1338           0 :                 float d_vert = diff.Y;
    1339           0 :                 diff.Y = 0;
    1340           0 :                 float d_horiz = diff.getLength();
    1341           0 :                 float required_time = d_horiz/player_max_speed;
    1342           0 :                 if(d_vert > 0 && d_vert/player_max_speed > required_time)
    1343           0 :                         required_time = d_vert/player_max_speed;
    1344           0 :                 if(m_move_pool.grab(required_time)){
    1345           0 :                         m_last_good_position = m_player->getPosition();
    1346             :                 } else {
    1347           0 :                         actionstream<<"Player "<<m_player->getName()
    1348           0 :                                         <<" moved too fast; resetting position"
    1349           0 :                                         <<std::endl;
    1350           0 :                         m_player->setPosition(m_last_good_position);
    1351           0 :                         cheated = true;
    1352             :                 }
    1353             :         }
    1354           0 :         return cheated;
    1355             : }
    1356             : 
    1357           0 : bool PlayerSAO::getCollisionBox(aabb3f *toset) {
    1358             :         //update collision box
    1359           0 :         *toset = m_player->getCollisionbox();
    1360             : 
    1361           0 :         toset->MinEdge += m_base_position;
    1362           0 :         toset->MaxEdge += m_base_position;
    1363             : 
    1364           0 :         return true;
    1365             : }
    1366             : 
    1367           0 : bool PlayerSAO::collideWithObjects(){
    1368           0 :         return true;
    1369           3 : }
    1370             : 

Generated by: LCOV version 1.11