LCOV - code coverage report
Current view: top level - src - player.cpp (source / functions) Hit Total Coverage
Test: report Lines: 73 155 47.1 %
Date: 2015-07-11 18:23:49 Functions: 10 16 62.5 %

          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 "player.h"
      21             : 
      22             : #include <fstream>
      23             : #include "jthread/jmutexautolock.h"
      24             : #include "util/numeric.h"
      25             : #include "hud.h"
      26             : #include "constants.h"
      27             : #include "gamedef.h"
      28             : #include "settings.h"
      29             : #include "content_sao.h"
      30             : #include "filesys.h"
      31             : #include "log.h"
      32             : #include "porting.h"  // strlcpy
      33             : 
      34             : 
      35           1 : Player::Player(IGameDef *gamedef, const char *name):
      36             :         touching_ground(false),
      37             :         in_liquid(false),
      38             :         in_liquid_stable(false),
      39             :         liquid_viscosity(0),
      40             :         is_climbing(false),
      41             :         swimming_vertical(false),
      42             :         camera_barely_in_ceiling(false),
      43             :         inventory(gamedef->idef()),
      44             :         hp(PLAYER_MAX_HP),
      45             :         hurt_tilt_timer(0),
      46             :         hurt_tilt_strength(0),
      47             :         peer_id(PEER_ID_INEXISTENT),
      48             :         keyPressed(0),
      49             : // protected
      50             :         m_gamedef(gamedef),
      51             :         m_breath(PLAYER_MAX_BREATH),
      52             :         m_pitch(0),
      53             :         m_yaw(0),
      54             :         m_speed(0,0,0),
      55             :         m_position(0,0,0),
      56             :         m_collisionbox(-BS*0.30,0.0,-BS*0.30,BS*0.30,BS*1.75,BS*0.30),
      57           1 :         m_dirty(false)
      58             : {
      59           1 :         strlcpy(m_name, name, PLAYERNAME_SIZE);
      60             : 
      61           1 :         inventory.clear();
      62           1 :         inventory.addList("main", PLAYER_INVENTORY_SIZE);
      63           1 :         InventoryList *craft = inventory.addList("craft", 9);
      64           1 :         craft->setWidth(3);
      65           1 :         inventory.addList("craftpreview", 1);
      66           1 :         inventory.addList("craftresult", 1);
      67           1 :         inventory.setModified(false);
      68             : 
      69             :         // Can be redefined via Lua
      70           1 :         inventory_formspec = "size[8,7.5]"
      71             :                 //"image[1,0.6;1,2;player.png]"
      72             :                 "list[current_player;main;0,3.5;8,4;]"
      73             :                 "list[current_player;craft;3,0;3,3;]"
      74             :                 "listring[]"
      75           1 :                 "list[current_player;craftpreview;7,1;1,1;]";
      76             : 
      77             :         // Initialize movement settings at default values, so movement can work if the server fails to send them
      78           1 :         movement_acceleration_default   = 3    * BS;
      79           1 :         movement_acceleration_air       = 2    * BS;
      80           1 :         movement_acceleration_fast      = 10   * BS;
      81           1 :         movement_speed_walk             = 4    * BS;
      82           1 :         movement_speed_crouch           = 1.35 * BS;
      83           1 :         movement_speed_fast             = 20   * BS;
      84           1 :         movement_speed_climb            = 2    * BS;
      85           1 :         movement_speed_jump             = 6.5  * BS;
      86           1 :         movement_liquid_fluidity        = 1    * BS;
      87           1 :         movement_liquid_fluidity_smooth = 0.5  * BS;
      88           1 :         movement_liquid_sink            = 10   * BS;
      89           1 :         movement_gravity                = 9.81 * BS;
      90           1 :         local_animation_speed           = 0.0;
      91             : 
      92             :         // Movement overrides are multipliers and must be 1 by default
      93           1 :         physics_override_speed        = 1;
      94           1 :         physics_override_jump         = 1;
      95           1 :         physics_override_gravity      = 1;
      96           1 :         physics_override_sneak        = true;
      97           1 :         physics_override_sneak_glitch = true;
      98             : 
      99             :         hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE |
     100             :                          HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE |
     101           1 :                          HUD_FLAG_BREATHBAR_VISIBLE;
     102             : 
     103           1 :         hud_hotbar_itemcount = HUD_HOTBAR_ITEMCOUNT_DEFAULT;
     104           1 : }
     105             : 
     106           2 : Player::~Player()
     107             : {
     108           1 :         clearHud();
     109           1 : }
     110             : 
     111             : // Horizontal acceleration (X and Z), Y direction is ignored
     112        1186 : void Player::accelerateHorizontal(v3f target_speed, f32 max_increase)
     113             : {
     114        1186 :         if(max_increase == 0)
     115           0 :                 return;
     116             : 
     117        1186 :         v3f d_wanted = target_speed - m_speed;
     118        1186 :         d_wanted.Y = 0;
     119        1186 :         f32 dl = d_wanted.getLength();
     120        1186 :         if(dl > max_increase)
     121         278 :                 dl = max_increase;
     122             :         
     123        1186 :         v3f d = d_wanted.normalize() * dl;
     124             : 
     125        1186 :         m_speed.X += d.X;
     126        1186 :         m_speed.Z += d.Z;
     127             : 
     128             : #if 0 // old code
     129             :         if(m_speed.X < target_speed.X - max_increase)
     130             :                 m_speed.X += max_increase;
     131             :         else if(m_speed.X > target_speed.X + max_increase)
     132             :                 m_speed.X -= max_increase;
     133             :         else if(m_speed.X < target_speed.X)
     134             :                 m_speed.X = target_speed.X;
     135             :         else if(m_speed.X > target_speed.X)
     136             :                 m_speed.X = target_speed.X;
     137             : 
     138             :         if(m_speed.Z < target_speed.Z - max_increase)
     139             :                 m_speed.Z += max_increase;
     140             :         else if(m_speed.Z > target_speed.Z + max_increase)
     141             :                 m_speed.Z -= max_increase;
     142             :         else if(m_speed.Z < target_speed.Z)
     143             :                 m_speed.Z = target_speed.Z;
     144             :         else if(m_speed.Z > target_speed.Z)
     145             :                 m_speed.Z = target_speed.Z;
     146             : #endif
     147             : }
     148             : 
     149             : // Vertical acceleration (Y), X and Z directions are ignored
     150        1186 : void Player::accelerateVertical(v3f target_speed, f32 max_increase)
     151             : {
     152        1186 :         if(max_increase == 0)
     153           2 :                 return;
     154             : 
     155        1184 :         f32 d_wanted = target_speed.Y - m_speed.Y;
     156        1184 :         if(d_wanted > max_increase)
     157           0 :                 d_wanted = max_increase;
     158        1184 :         else if(d_wanted < -max_increase)
     159           0 :                 d_wanted = -max_increase;
     160             : 
     161        1184 :         m_speed.Y += d_wanted;
     162             : 
     163             : #if 0 // old code
     164             :         if(m_speed.Y < target_speed.Y - max_increase)
     165             :                 m_speed.Y += max_increase;
     166             :         else if(m_speed.Y > target_speed.Y + max_increase)
     167             :                 m_speed.Y -= max_increase;
     168             :         else if(m_speed.Y < target_speed.Y)
     169             :                 m_speed.Y = target_speed.Y;
     170             :         else if(m_speed.Y > target_speed.Y)
     171             :                 m_speed.Y = target_speed.Y;
     172             : #endif
     173             : }
     174             : 
     175        1186 : v3s16 Player::getLightPosition() const
     176             : {
     177        1186 :         return floatToInt(m_position + v3f(0,BS+BS/2,0), BS);
     178             : }
     179             : 
     180           0 : void Player::serialize(std::ostream &os)
     181             : {
     182             :         // Utilize a Settings object for storing values
     183           0 :         Settings args;
     184           0 :         args.setS32("version", 1);
     185           0 :         args.set("name", m_name);
     186             :         //args.set("password", m_password);
     187           0 :         args.setFloat("pitch", m_pitch);
     188           0 :         args.setFloat("yaw", m_yaw);
     189           0 :         args.setV3F("position", m_position);
     190           0 :         args.setS32("hp", hp);
     191           0 :         args.setS32("breath", m_breath);
     192             : 
     193           0 :         args.writeLines(os);
     194             : 
     195           0 :         os<<"PlayerArgsEnd\n";
     196             : 
     197           0 :         inventory.serialize(os);
     198           0 : }
     199             : 
     200           0 : void Player::deSerialize(std::istream &is, std::string playername)
     201             : {
     202           0 :         Settings args;
     203             : 
     204           0 :         if (!args.parseConfigLines(is, "PlayerArgsEnd")) {
     205           0 :                 throw SerializationError("PlayerArgsEnd of player " +
     206           0 :                                 playername + " not found!");
     207             :         }
     208             : 
     209           0 :         m_dirty = true;
     210             :         //args.getS32("version"); // Version field value not used
     211           0 :         std::string name = args.get("name");
     212           0 :         strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE);
     213           0 :         setPitch(args.getFloat("pitch"));
     214           0 :         setYaw(args.getFloat("yaw"));
     215           0 :         setPosition(args.getV3F("position"));
     216             :         try{
     217           0 :                 hp = args.getS32("hp");
     218           0 :         }catch(SettingNotFoundException &e) {
     219           0 :                 hp = PLAYER_MAX_HP;
     220             :         }
     221             :         try{
     222           0 :                 m_breath = args.getS32("breath");
     223           0 :         }catch(SettingNotFoundException &e) {
     224           0 :                 m_breath = PLAYER_MAX_BREATH;
     225             :         }
     226             : 
     227           0 :         inventory.deSerialize(is);
     228             : 
     229           0 :         if(inventory.getList("craftpreview") == NULL) {
     230             :                 // Convert players without craftpreview
     231           0 :                 inventory.addList("craftpreview", 1);
     232             : 
     233           0 :                 bool craftresult_is_preview = true;
     234           0 :                 if(args.exists("craftresult_is_preview"))
     235           0 :                         craftresult_is_preview = args.getBool("craftresult_is_preview");
     236           0 :                 if(craftresult_is_preview)
     237             :                 {
     238             :                         // Clear craftresult
     239           0 :                         inventory.getList("craftresult")->changeItem(0, ItemStack());
     240             :                 }
     241             :         }
     242           0 : }
     243             : 
     244           2 : u32 Player::addHud(HudElement *toadd)
     245             : {
     246           4 :         JMutexAutoLock lock(m_mutex);
     247             : 
     248           2 :         u32 id = getFreeHudID();
     249             : 
     250           2 :         if (id < hud.size())
     251           0 :                 hud[id] = toadd;
     252             :         else
     253           2 :                 hud.push_back(toadd);
     254             : 
     255           4 :         return id;
     256             : }
     257             : 
     258        2349 : HudElement* Player::getHud(u32 id)
     259             : {
     260        4698 :         JMutexAutoLock lock(m_mutex);
     261             : 
     262        2349 :         if (id < hud.size())
     263        2345 :                 return hud[id];
     264             : 
     265           4 :         return NULL;
     266             : }
     267             : 
     268           0 : HudElement* Player::removeHud(u32 id)
     269             : {
     270           0 :         JMutexAutoLock lock(m_mutex);
     271             : 
     272           0 :         HudElement* retval = NULL;
     273           0 :         if (id < hud.size()) {
     274           0 :                 retval = hud[id];
     275           0 :                 hud[id] = NULL;
     276             :         }
     277           0 :         return retval;
     278             : }
     279             : 
     280           1 : void Player::clearHud()
     281             : {
     282           2 :         JMutexAutoLock lock(m_mutex);
     283             : 
     284           5 :         while(!hud.empty()) {
     285           2 :                 delete hud.back();
     286           2 :                 hud.pop_back();
     287             :         }
     288           1 : }
     289             : 
     290             : 
     291           0 : void RemotePlayer::save(std::string savedir)
     292             : {
     293             :         /*
     294             :          * We have to open all possible player files in the players directory
     295             :          * and check their player names because some file systems are not
     296             :          * case-sensitive and player names are case-sensitive.
     297             :          */
     298             : 
     299             :         // A player to deserialize files into to check their names
     300           0 :         RemotePlayer testplayer(m_gamedef, "");
     301             : 
     302           0 :         savedir += DIR_DELIM;
     303           0 :         std::string path = savedir + m_name;
     304           0 :         for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) {
     305           0 :                 if (!fs::PathExists(path)) {
     306             :                         // Open file and serialize
     307           0 :                         std::ostringstream ss(std::ios_base::binary);
     308           0 :                         serialize(ss);
     309           0 :                         if (!fs::safeWriteToFile(path, ss.str())) {
     310           0 :                                 infostream << "Failed to write " << path << std::endl;
     311             :                         }
     312           0 :                         setModified(false);
     313           0 :                         return;
     314             :                 }
     315             :                 // Open file and deserialize
     316           0 :                 std::ifstream is(path.c_str(), std::ios_base::binary);
     317           0 :                 if (!is.good()) {
     318           0 :                         infostream << "Failed to open " << path << std::endl;
     319           0 :                         return;
     320             :                 }
     321           0 :                 testplayer.deSerialize(is, path);
     322           0 :                 is.close();
     323           0 :                 if (strcmp(testplayer.getName(), m_name) == 0) {
     324             :                         // Open file and serialize
     325           0 :                         std::ostringstream ss(std::ios_base::binary);
     326           0 :                         serialize(ss);
     327           0 :                         if (!fs::safeWriteToFile(path, ss.str())) {
     328           0 :                                 infostream << "Failed to write " << path << std::endl;
     329             :                         }
     330           0 :                         setModified(false);
     331           0 :                         return;
     332             :                 }
     333           0 :                 path = savedir + m_name + itos(i);
     334             :         }
     335             : 
     336           0 :         infostream << "Didn't find free file for player " << m_name << std::endl;
     337           0 :         return;
     338             : }
     339             : 
     340             : /*
     341             :         RemotePlayer
     342             : */
     343           0 : void RemotePlayer::setPosition(const v3f &position)
     344             : {
     345           0 :         Player::setPosition(position);
     346           0 :         if(m_sao)
     347           0 :                 m_sao->setBasePosition(position);
     348           3 : }
     349             : 

Generated by: LCOV version 1.11