database-files.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. Minetest
  3. Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
  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 <cassert>
  17. #include <json/json.h>
  18. #include "database-files.h"
  19. #include "content_sao.h"
  20. #include "remoteplayer.h"
  21. #include "settings.h"
  22. #include "porting.h"
  23. #include "filesys.h"
  24. // !!! WARNING !!!
  25. // This backend is intended to be used on Minetest 0.4.16 only for the transition backend
  26. // for player files
  27. void PlayerDatabaseFiles::serialize(std::ostringstream &os, RemotePlayer *player)
  28. {
  29. // Utilize a Settings object for storing values
  30. Settings args;
  31. args.setS32("version", 1);
  32. args.set("name", player->getName());
  33. sanity_check(player->getPlayerSAO());
  34. args.setS32("hp", player->getPlayerSAO()->getHP());
  35. args.setV3F("position", player->getPlayerSAO()->getBasePosition());
  36. args.setFloat("pitch", player->getPlayerSAO()->getPitch());
  37. args.setFloat("yaw", player->getPlayerSAO()->getYaw());
  38. args.setS32("breath", player->getPlayerSAO()->getBreath());
  39. std::string extended_attrs;
  40. player->serializeExtraAttributes(extended_attrs);
  41. args.set("extended_attributes", extended_attrs);
  42. args.writeLines(os);
  43. os << "PlayerArgsEnd\n";
  44. player->inventory.serialize(os);
  45. }
  46. void PlayerDatabaseFiles::savePlayer(RemotePlayer *player)
  47. {
  48. std::string savedir = m_savedir + DIR_DELIM;
  49. std::string path = savedir + player->getName();
  50. bool path_found = false;
  51. RemotePlayer testplayer("", NULL);
  52. for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES && !path_found; i++) {
  53. if (!fs::PathExists(path)) {
  54. path_found = true;
  55. continue;
  56. }
  57. // Open and deserialize file to check player name
  58. std::ifstream is(path.c_str(), std::ios_base::binary);
  59. if (!is.good()) {
  60. errorstream << "Failed to open " << path << std::endl;
  61. return;
  62. }
  63. testplayer.deSerialize(is, path, NULL);
  64. is.close();
  65. if (strcmp(testplayer.getName(), player->getName()) == 0) {
  66. path_found = true;
  67. continue;
  68. }
  69. path = savedir + player->getName() + itos(i);
  70. }
  71. if (!path_found) {
  72. errorstream << "Didn't find free file for player " << player->getName()
  73. << std::endl;
  74. return;
  75. }
  76. // Open and serialize file
  77. std::ostringstream ss(std::ios_base::binary);
  78. serialize(ss, player);
  79. if (!fs::safeWriteToFile(path, ss.str())) {
  80. infostream << "Failed to write " << path << std::endl;
  81. }
  82. player->setModified(false);
  83. }
  84. bool PlayerDatabaseFiles::removePlayer(const std::string &name)
  85. {
  86. std::string players_path = m_savedir + DIR_DELIM;
  87. std::string path = players_path + name;
  88. RemotePlayer temp_player("", NULL);
  89. for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) {
  90. // Open file and deserialize
  91. std::ifstream is(path.c_str(), std::ios_base::binary);
  92. if (!is.good())
  93. continue;
  94. temp_player.deSerialize(is, path, NULL);
  95. is.close();
  96. if (temp_player.getName() == name) {
  97. fs::DeleteSingleFileOrEmptyDirectory(path);
  98. return true;
  99. }
  100. path = players_path + name + itos(i);
  101. }
  102. return false;
  103. }
  104. bool PlayerDatabaseFiles::loadPlayer(RemotePlayer *player, PlayerSAO *sao)
  105. {
  106. std::string players_path = m_savedir + DIR_DELIM;
  107. std::string path = players_path + player->getName();
  108. const std::string player_to_load = player->getName();
  109. for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) {
  110. // Open file and deserialize
  111. std::ifstream is(path.c_str(), std::ios_base::binary);
  112. if (!is.good())
  113. continue;
  114. player->deSerialize(is, path, sao);
  115. is.close();
  116. if (player->getName() == player_to_load)
  117. return true;
  118. path = players_path + player_to_load + itos(i);
  119. }
  120. infostream << "Player file for player " << player_to_load << " not found" << std::endl;
  121. return false;
  122. }
  123. void PlayerDatabaseFiles::listPlayers(std::vector<std::string> &res)
  124. {
  125. std::vector<fs::DirListNode> files = fs::GetDirListing(m_savedir);
  126. // list files into players directory
  127. for (std::vector<fs::DirListNode>::const_iterator it = files.begin(); it !=
  128. files.end(); ++it) {
  129. // Ignore directories
  130. if (it->dir)
  131. continue;
  132. const std::string &filename = it->name;
  133. std::string full_path = m_savedir + DIR_DELIM + filename;
  134. std::ifstream is(full_path.c_str(), std::ios_base::binary);
  135. if (!is.good())
  136. continue;
  137. RemotePlayer player(filename.c_str(), NULL);
  138. // Null env & dummy peer_id
  139. PlayerSAO playerSAO(NULL, &player, 15789, false);
  140. player.deSerialize(is, "", &playerSAO);
  141. is.close();
  142. res.emplace_back(player.getName());
  143. }
  144. }