Only try to load from possible player files

This commit is contained in:
ShadowNinja 2014-06-01 13:11:37 -04:00
parent 7e6db1b803
commit e491f8cd48
3 changed files with 37 additions and 67 deletions

View File

@ -443,46 +443,35 @@ void ServerEnvironment::savePlayer(const std::string &playername)
Player *ServerEnvironment::loadPlayer(const std::string &playername) Player *ServerEnvironment::loadPlayer(const std::string &playername)
{ {
std::string players_path = m_path_world + DIR_DELIM "players"; std::string players_path = m_path_world + DIR_DELIM "players" DIR_DELIM;
RemotePlayer *player = static_cast<RemotePlayer*>(getPlayer(playername.c_str())); RemotePlayer *player = static_cast<RemotePlayer*>(getPlayer(playername.c_str()));
bool newplayer = false; bool newplayer = false;
bool foundplayer = false; bool found = false;
if (!player) { if (!player) {
player = new RemotePlayer(m_gamedef); player = new RemotePlayer(m_gamedef);
newplayer = true; newplayer = true;
} }
std::vector<fs::DirListNode> player_files = fs::GetDirListing(players_path); RemotePlayer testplayer(m_gamedef);
for (u32 i = 0; i < player_files.size(); i++) { std::string path = players_path + playername;
if (player_files[i].dir) for (u32 i = 0; i < 1000; i++) {
continue; // Open file and deserialize
// Full path to this file
std::string path = players_path + "/" + player_files[i].name;
// Load player to see what is its name
std::ifstream is(path.c_str(), std::ios_base::binary); std::ifstream is(path.c_str(), std::ios_base::binary);
if (!is.good()) { if (!is.good()) {
infostream << "Failed to read " << path << std::endl; return NULL;
continue;
} }
player->deSerialize(is, player_files[i].name); testplayer.deSerialize(is, path);
if (testplayer.getName() == playername) {
if (!string_allowed(player->getName(), PLAYERNAME_ALLOWED_CHARS)) { *player = testplayer;
infostream << "Not loading player with invalid name: " found = true;
<< player->getName() << std::endl;
continue;
}
if (player->getName() == playername) {
// We found our player
foundplayer = true;
break; break;
} }
path = players_path + playername + itos(i);
} }
if (!foundplayer) { if (!found) {
infostream << "Player file for player " << playername
<< " not found" << std::endl;
return NULL; return NULL;
} }
if (newplayer) { if (newplayer) {

View File

@ -284,11 +284,10 @@ void Player::clearHud()
} }
void RemotePlayer::save(const std::string &savedir) void RemotePlayer::save(std::string savedir)
{ {
bool newplayer = true; /*
* We have to open all possible player files in the players directory
/* We have to iterate through all files in the players directory
* and check their player names because some file systems are not * and check their player names because some file systems are not
* case-sensitive and player names are case-sensitive. * case-sensitive and player names are case-sensitive.
*/ */
@ -296,23 +295,25 @@ void RemotePlayer::save(const std::string &savedir)
// A player to deserialize files into to check their names // A player to deserialize files into to check their names
RemotePlayer testplayer(m_gamedef); RemotePlayer testplayer(m_gamedef);
std::vector<fs::DirListNode> player_files = fs::GetDirListing(savedir); savedir += DIR_DELIM;
for(u32 i = 0; i < player_files.size(); i++) { std::string path = savedir + m_name;
if (player_files[i].dir || player_files[i].name[0] == '.') { for (u32 i = 0; i < 1000; i++) {
continue; if (!fs::PathExists(path)) {
// Open file and serialize
std::ostringstream ss(std::ios_base::binary);
serialize(ss);
if (!fs::safeWriteToFile(path, ss.str())) {
infostream << "Failed to write " << path << std::endl;
}
return;
} }
// Full path to this file
std::string path = savedir + "/" + player_files[i].name;
// Open file and deserialize // Open file and deserialize
std::ifstream is(path.c_str(), std::ios_base::binary); std::ifstream is(path.c_str(), std::ios_base::binary);
if (!is.good()) { if (!is.good()) {
infostream << "Failed to read " << path << std::endl; infostream << "Failed to open " << path << std::endl;
continue; return;
} }
testplayer.deSerialize(is, player_files[i].name); testplayer.deSerialize(is, path);
if (strcmp(testplayer.getName(), m_name) == 0) { if (strcmp(testplayer.getName(), m_name) == 0) {
// Open file and serialize // Open file and serialize
std::ostringstream ss(std::ios_base::binary); std::ostringstream ss(std::ios_base::binary);
@ -320,33 +321,13 @@ void RemotePlayer::save(const std::string &savedir)
if (!fs::safeWriteToFile(path, ss.str())) { if (!fs::safeWriteToFile(path, ss.str())) {
infostream << "Failed to write " << path << std::endl; infostream << "Failed to write " << path << std::endl;
} }
newplayer = false;
break;
}
}
if (newplayer) {
bool found = false;
std::string path = savedir + "/" + m_name;
for (u32 i = 0; i < 1000; i++) {
if (!fs::PathExists(path)) {
found = true;
break;
}
path = savedir + "/" + m_name + itos(i);
}
if (!found) {
infostream << "Didn't find free file for player " << m_name << std::endl;
return; return;
} }
path = savedir + m_name + itos(i);
// Open file and serialize
std::ostringstream ss(std::ios_base::binary);
serialize(ss);
if (!fs::safeWriteToFile(path, ss.str())) {
infostream << "Failed to write " << path << std::endl;
}
} }
infostream << "Didn't find free file for player " << m_name << std::endl;
return;
} }
/* /*

View File

@ -335,7 +335,7 @@ public:
RemotePlayer(IGameDef *gamedef): Player(gamedef), m_sao(0) {} RemotePlayer(IGameDef *gamedef): Player(gamedef), m_sao(0) {}
virtual ~RemotePlayer() {} virtual ~RemotePlayer() {}
void save(const std::string &savedir); void save(std::string savedir);
PlayerSAO *getPlayerSAO() PlayerSAO *getPlayerSAO()
{ return m_sao; } { return m_sao; }