player.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "player.h"
  17. #include "hud.h"
  18. #include "constants.h"
  19. #include "gamedef.h"
  20. #include "settings.h"
  21. #include "content_sao.h"
  22. #include "util/numeric.h"
  23. Player::Player(IGameDef *gamedef):
  24. touching_ground(false),
  25. in_liquid(false),
  26. in_liquid_stable(false),
  27. liquid_viscosity(0),
  28. is_climbing(false),
  29. swimming_vertical(false),
  30. camera_barely_in_ceiling(false),
  31. light(0),
  32. inventory(gamedef->idef()),
  33. hp(PLAYER_MAX_HP),
  34. hurt_tilt_timer(0),
  35. hurt_tilt_strength(0),
  36. peer_id(PEER_ID_INEXISTENT),
  37. keyPressed(0),
  38. // protected
  39. m_gamedef(gamedef),
  40. m_breath(-1),
  41. m_pitch(0),
  42. m_yaw(0),
  43. m_speed(0,0,0),
  44. m_position(0,0,0),
  45. m_collisionbox(-BS*0.30,0.0,-BS*0.30,BS*0.30,BS*1.75,BS*0.30),
  46. m_last_pitch(0),
  47. m_last_yaw(0),
  48. m_last_pos(0,0,0),
  49. m_last_hp(PLAYER_MAX_HP),
  50. m_last_inventory(gamedef->idef())
  51. {
  52. updateName("<not set>");
  53. inventory.clear();
  54. inventory.addList("main", PLAYER_INVENTORY_SIZE);
  55. InventoryList *craft = inventory.addList("craft", 9);
  56. craft->setWidth(3);
  57. inventory.addList("craftpreview", 1);
  58. inventory.addList("craftresult", 1);
  59. m_last_inventory = inventory;
  60. // Can be redefined via Lua
  61. inventory_formspec = "size[8,7.5]"
  62. //"image[1,0.6;1,2;player.png]"
  63. "list[current_player;main;0,3.5;8,4;]"
  64. "list[current_player;craft;3,0;3,3;]"
  65. "list[current_player;craftpreview;7,1;1,1;]";
  66. // Initialize movement settings at default values, so movement can work if the server fails to send them
  67. movement_acceleration_default = 3 * BS;
  68. movement_acceleration_air = 2 * BS;
  69. movement_acceleration_fast = 10 * BS;
  70. movement_speed_walk = 4 * BS;
  71. movement_speed_crouch = 1.35 * BS;
  72. movement_speed_fast = 20 * BS;
  73. movement_speed_climb = 2 * BS;
  74. movement_speed_jump = 6.5 * BS;
  75. movement_liquid_fluidity = 1 * BS;
  76. movement_liquid_fluidity_smooth = 0.5 * BS;
  77. movement_liquid_sink = 10 * BS;
  78. movement_gravity = 9.81 * BS;
  79. // Movement overrides are multipliers and must be 1 by default
  80. physics_override_speed = 1;
  81. physics_override_jump = 1;
  82. physics_override_gravity = 1;
  83. physics_override_sneak = true;
  84. physics_override_sneak_glitch = true;
  85. hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE |
  86. HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE |
  87. HUD_FLAG_BREATHBAR_VISIBLE;
  88. hud_hotbar_itemcount = HUD_HOTBAR_ITEMCOUNT_DEFAULT;
  89. }
  90. Player::~Player()
  91. {
  92. clearHud();
  93. }
  94. // Horizontal acceleration (X and Z), Y direction is ignored
  95. void Player::accelerateHorizontal(v3f target_speed, f32 max_increase)
  96. {
  97. if(max_increase == 0)
  98. return;
  99. v3f d_wanted = target_speed - m_speed;
  100. d_wanted.Y = 0;
  101. f32 dl = d_wanted.getLength();
  102. if(dl > max_increase)
  103. dl = max_increase;
  104. v3f d = d_wanted.normalize() * dl;
  105. m_speed.X += d.X;
  106. m_speed.Z += d.Z;
  107. #if 0 // old code
  108. if(m_speed.X < target_speed.X - max_increase)
  109. m_speed.X += max_increase;
  110. else if(m_speed.X > target_speed.X + max_increase)
  111. m_speed.X -= max_increase;
  112. else if(m_speed.X < target_speed.X)
  113. m_speed.X = target_speed.X;
  114. else if(m_speed.X > target_speed.X)
  115. m_speed.X = target_speed.X;
  116. if(m_speed.Z < target_speed.Z - max_increase)
  117. m_speed.Z += max_increase;
  118. else if(m_speed.Z > target_speed.Z + max_increase)
  119. m_speed.Z -= max_increase;
  120. else if(m_speed.Z < target_speed.Z)
  121. m_speed.Z = target_speed.Z;
  122. else if(m_speed.Z > target_speed.Z)
  123. m_speed.Z = target_speed.Z;
  124. #endif
  125. }
  126. // Vertical acceleration (Y), X and Z directions are ignored
  127. void Player::accelerateVertical(v3f target_speed, f32 max_increase)
  128. {
  129. if(max_increase == 0)
  130. return;
  131. f32 d_wanted = target_speed.Y - m_speed.Y;
  132. if(d_wanted > max_increase)
  133. d_wanted = max_increase;
  134. else if(d_wanted < -max_increase)
  135. d_wanted = -max_increase;
  136. m_speed.Y += d_wanted;
  137. #if 0 // old code
  138. if(m_speed.Y < target_speed.Y - max_increase)
  139. m_speed.Y += max_increase;
  140. else if(m_speed.Y > target_speed.Y + max_increase)
  141. m_speed.Y -= max_increase;
  142. else if(m_speed.Y < target_speed.Y)
  143. m_speed.Y = target_speed.Y;
  144. else if(m_speed.Y > target_speed.Y)
  145. m_speed.Y = target_speed.Y;
  146. #endif
  147. }
  148. v3s16 Player::getLightPosition() const
  149. {
  150. return floatToInt(m_position + v3f(0,BS+BS/2,0), BS);
  151. }
  152. void Player::serialize(std::ostream &os)
  153. {
  154. // Utilize a Settings object for storing values
  155. Settings args;
  156. args.setS32("version", 1);
  157. args.set("name", m_name);
  158. //args.set("password", m_password);
  159. args.setFloat("pitch", m_pitch);
  160. args.setFloat("yaw", m_yaw);
  161. args.setV3F("position", m_position);
  162. args.setS32("hp", hp);
  163. args.setS32("breath", m_breath);
  164. args.writeLines(os);
  165. os<<"PlayerArgsEnd\n";
  166. inventory.serialize(os);
  167. }
  168. void Player::deSerialize(std::istream &is, std::string playername)
  169. {
  170. Settings args;
  171. for(;;)
  172. {
  173. if(is.eof())
  174. throw SerializationError
  175. (("Player::deSerialize(): PlayerArgsEnd of player \"" + playername + "\" not found").c_str());
  176. std::string line;
  177. std::getline(is, line);
  178. std::string trimmedline = trim(line);
  179. if(trimmedline == "PlayerArgsEnd")
  180. break;
  181. args.parseConfigLine(line);
  182. }
  183. //args.getS32("version"); // Version field value not used
  184. std::string name = args.get("name");
  185. updateName(name.c_str());
  186. setPitch(args.getFloat("pitch"));
  187. setYaw(args.getFloat("yaw"));
  188. setPosition(args.getV3F("position"));
  189. try{
  190. hp = args.getS32("hp");
  191. }catch(SettingNotFoundException &e) {
  192. hp = 20;
  193. }
  194. try{
  195. m_breath = args.getS32("breath");
  196. }catch(SettingNotFoundException &e) {
  197. m_breath = 11;
  198. }
  199. inventory.deSerialize(is);
  200. if(inventory.getList("craftpreview") == NULL) {
  201. // Convert players without craftpreview
  202. inventory.addList("craftpreview", 1);
  203. bool craftresult_is_preview = true;
  204. if(args.exists("craftresult_is_preview"))
  205. craftresult_is_preview = args.getBool("craftresult_is_preview");
  206. if(craftresult_is_preview)
  207. {
  208. // Clear craftresult
  209. inventory.getList("craftresult")->changeItem(0, ItemStack());
  210. }
  211. }
  212. // Set m_last_*
  213. checkModified();
  214. }
  215. u32 Player::addHud(HudElement *toadd)
  216. {
  217. u32 id = getFreeHudID();
  218. if (id < hud.size())
  219. hud[id] = toadd;
  220. else
  221. hud.push_back(toadd);
  222. return id;
  223. }
  224. HudElement* Player::getHud(u32 id)
  225. {
  226. if (id < hud.size())
  227. return hud[id];
  228. return NULL;
  229. }
  230. HudElement* Player::removeHud(u32 id)
  231. {
  232. HudElement* retval = NULL;
  233. if (id < hud.size()) {
  234. retval = hud[id];
  235. hud[id] = NULL;
  236. }
  237. return retval;
  238. }
  239. void Player::clearHud()
  240. {
  241. while(!hud.empty()) {
  242. delete hud.back();
  243. hud.pop_back();
  244. }
  245. }
  246. void RemotePlayer::save(std::string savedir)
  247. {
  248. /*
  249. * We have to open all possible player files in the players directory
  250. * and check their player names because some file systems are not
  251. * case-sensitive and player names are case-sensitive.
  252. */
  253. // A player to deserialize files into to check their names
  254. RemotePlayer testplayer(m_gamedef);
  255. savedir += DIR_DELIM;
  256. std::string path = savedir + m_name;
  257. for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) {
  258. if (!fs::PathExists(path)) {
  259. // Open file and serialize
  260. std::ostringstream ss(std::ios_base::binary);
  261. serialize(ss);
  262. if (!fs::safeWriteToFile(path, ss.str())) {
  263. infostream << "Failed to write " << path << std::endl;
  264. }
  265. return;
  266. }
  267. // Open file and deserialize
  268. std::ifstream is(path.c_str(), std::ios_base::binary);
  269. if (!is.good()) {
  270. infostream << "Failed to open " << path << std::endl;
  271. return;
  272. }
  273. testplayer.deSerialize(is, path);
  274. is.close();
  275. if (strcmp(testplayer.getName(), m_name) == 0) {
  276. // Open file and serialize
  277. std::ostringstream ss(std::ios_base::binary);
  278. serialize(ss);
  279. if (!fs::safeWriteToFile(path, ss.str())) {
  280. infostream << "Failed to write " << path << std::endl;
  281. }
  282. return;
  283. }
  284. path = savedir + m_name + itos(i);
  285. }
  286. infostream << "Didn't find free file for player " << m_name << std::endl;
  287. return;
  288. }
  289. /*
  290. RemotePlayer
  291. */
  292. void RemotePlayer::setPosition(const v3f &position)
  293. {
  294. Player::setPosition(position);
  295. if(m_sao)
  296. m_sao->setBasePosition(position);
  297. }