Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Only keep players loaded while they're connected
  • Loading branch information
ShadowNinja committed Jun 23, 2014
1 parent 5012751 commit 7e6db1b
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 242 deletions.
2 changes: 2 additions & 0 deletions src/content_sao.cpp
Expand Up @@ -1027,6 +1027,8 @@ void PlayerSAO::removingFromEnvironment()
{
m_player->setPlayerSAO(NULL);
m_player->peer_id = 0;
m_env->savePlayer(m_player->getName());
m_env->removePlayer(m_player->getName());
}
}

Expand Down
231 changes: 67 additions & 164 deletions src/environment.cpp
Expand Up @@ -100,6 +100,18 @@ void Environment::removePlayer(u16 peer_id)
}
}

void Environment::removePlayer(const char *name)
{
for (std::list<Player*>::iterator it = m_players.begin();
it != m_players.end(); ++it) {
if (strcmp((*it)->getName(), name) == 0) {
delete *it;
m_players.erase(it);
return;
}
}
}

Player * Environment::getPlayer(u16 peer_id)
{
for(std::list<Player*>::iterator i = m_players.begin();
Expand Down Expand Up @@ -332,10 +344,12 @@ void ActiveBlockList::update(std::list<v3s16> &active_positions,
*/

ServerEnvironment::ServerEnvironment(ServerMap *map,
GameScripting *scriptIface, IGameDef *gamedef):
GameScripting *scriptIface, IGameDef *gamedef,
const std::string &path_world) :
m_map(map),
m_script(scriptIface),
m_gamedef(gamedef),
m_path_world(path_world),
m_send_recommended_timer(0),
m_active_block_interval_overload_skip(0),
m_game_time(0),
Expand Down Expand Up @@ -401,196 +415,85 @@ bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16
return true;
}

void ServerEnvironment::serializePlayers(const std::string &savedir)
void ServerEnvironment::saveLoadedPlayers()
{
std::string players_path = savedir + "/players";
std::string players_path = m_path_world + DIR_DELIM "players";
fs::CreateDir(players_path);

std::set<Player*> saved_players;

std::vector<fs::DirListNode> player_files = fs::GetDirListing(players_path);
for(u32 i=0; i<player_files.size(); i++)
{
if(player_files[i].dir || player_files[i].name[0] == '.')
continue;

// Full path to this file
std::string path = players_path + "/" + player_files[i].name;

//infostream<<"Checking player file "<<path<<std::endl;

// Load player to see what is its name
RemotePlayer testplayer(m_gamedef);
{
// Open file and deserialize
std::ifstream is(path.c_str(), std::ios_base::binary);
if(is.good() == false)
{
infostream<<"Failed to read "<<path<<std::endl;
continue;
}
testplayer.deSerialize(is, player_files[i].name);
}

//infostream<<"Loaded test player with name "<<testplayer.getName()<<std::endl;

// Search for the player
std::string playername = testplayer.getName();
Player *player = getPlayer(playername.c_str());
if(player == NULL)
{
infostream<<"Didn't find matching player, ignoring file "<<path<<std::endl;
continue;
}

//infostream<<"Found matching player, overwriting."<<std::endl;

// OK, found. Save player there.
if(player->checkModified())
{
// Open file and serialize
std::ostringstream ss(std::ios_base::binary);
player->serialize(ss);
if(!fs::safeWriteToFile(path, ss.str()))
{
infostream<<"Failed to write "<<path<<std::endl;
continue;
}
saved_players.insert(player);
} else {
saved_players.insert(player);
for (std::list<Player*>::iterator it = m_players.begin();
it != m_players.end();
++it) {
RemotePlayer *player = static_cast<RemotePlayer*>(*it);
if (player->checkModified()) {
player->save(players_path);
}
}
}

for(std::list<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i)
{
Player *player = *i;
if(saved_players.find(player) != saved_players.end())
{
/*infostream<<"Player "<<player->getName()
<<" was already saved."<<std::endl;*/
continue;
}
std::string playername = player->getName();
// Don't save unnamed player
if(playername == "")
{
//infostream<<"Not saving unnamed player."<<std::endl;
continue;
}
/*
Find a sane filename
*/
if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS) == false)
playername = "player";
std::string path = players_path + "/" + playername;
bool found = false;
for(u32 i=0; i<1000; i++)
{
if(fs::PathExists(path) == false)
{
found = true;
break;
}
path = players_path + "/" + playername + itos(i);
}
if(found == false)
{
infostream<<"Didn't find free file for player"<<std::endl;
continue;
}
void ServerEnvironment::savePlayer(const std::string &playername)
{
std::string players_path = m_path_world + DIR_DELIM "players";
fs::CreateDir(players_path);

{
/*infostream<<"Saving player "<<player->getName()<<" to "
<<path<<std::endl;*/
// Open file and serialize
std::ostringstream ss(std::ios_base::binary);
player->serialize(ss);
if(!fs::safeWriteToFile(path, ss.str()))
{
infostream<<"Failed to write "<<path<<std::endl;
continue;
}
saved_players.insert(player);
}
RemotePlayer *player = static_cast<RemotePlayer*>(getPlayer(playername.c_str()));
if (player) {
player->save(players_path);
}

//infostream<<"Saved "<<saved_players.size()<<" players."<<std::endl;
}

void ServerEnvironment::deSerializePlayers(const std::string &savedir)
Player *ServerEnvironment::loadPlayer(const std::string &playername)
{
std::string players_path = savedir + "/players";
std::string players_path = m_path_world + DIR_DELIM "players";

RemotePlayer *player = static_cast<RemotePlayer*>(getPlayer(playername.c_str()));
bool newplayer = false;
bool foundplayer = false;
if (!player) {
player = new RemotePlayer(m_gamedef);
newplayer = true;
}

std::vector<fs::DirListNode> player_files = fs::GetDirListing(players_path);
for(u32 i=0; i<player_files.size(); i++)
{
if(player_files[i].dir)
for (u32 i = 0; i < player_files.size(); i++) {
if (player_files[i].dir)
continue;

// Full path to this file
std::string path = players_path + "/" + player_files[i].name;

//infostream<<"Checking player file "<<path<<std::endl;

// Load player to see what is its name
RemotePlayer testplayer(m_gamedef);
{
// Open file and deserialize
std::ifstream is(path.c_str(), std::ios_base::binary);
if(is.good() == false)
{
infostream<<"Failed to read "<<path<<std::endl;
continue;
}
testplayer.deSerialize(is, player_files[i].name);
}

if(!string_allowed(testplayer.getName(), PLAYERNAME_ALLOWED_CHARS))
{
infostream<<"Not loading player with invalid name: "
<<testplayer.getName()<<std::endl;
std::ifstream is(path.c_str(), std::ios_base::binary);
if (!is.good()) {
infostream << "Failed to read " << path << std::endl;
continue;
}
player->deSerialize(is, player_files[i].name);

/*infostream<<"Loaded test player with name "<<testplayer.getName()
<<std::endl;*/

// Search for the player
std::string playername = testplayer.getName();
Player *player = getPlayer(playername.c_str());
bool newplayer = false;
if(player == NULL)
{
//infostream<<"Is a new player"<<std::endl;
player = new RemotePlayer(m_gamedef);
newplayer = true;
if (!string_allowed(player->getName(), PLAYERNAME_ALLOWED_CHARS)) {
infostream << "Not loading player with invalid name: "
<< player->getName() << std::endl;
continue;
}

// Load player
{
verbosestream<<"Reading player "<<testplayer.getName()<<" from "
<<path<<std::endl;
// Open file and deserialize
std::ifstream is(path.c_str(), std::ios_base::binary);
if(is.good() == false)
{
infostream<<"Failed to read "<<path<<std::endl;
continue;
}
player->deSerialize(is, player_files[i].name);
if (player->getName() == playername) {
// We found our player
foundplayer = true;
break;
}

if(newplayer)
{
addPlayer(player);
}
}
if (!foundplayer) {
return NULL;
}
if (newplayer) {
addPlayer(player);
}
return player;
}

void ServerEnvironment::saveMeta(const std::string &savedir)
void ServerEnvironment::saveMeta()
{
std::string path = savedir + "/env_meta.txt";
std::string path = m_path_world + DIR_DELIM "env_meta.txt";

// Open file and serialize
std::ostringstream ss(std::ios_base::binary);
Expand All @@ -609,9 +512,9 @@ void ServerEnvironment::saveMeta(const std::string &savedir)
}
}

void ServerEnvironment::loadMeta(const std::string &savedir)
void ServerEnvironment::loadMeta()
{
std::string path = savedir + "/env_meta.txt";
std::string path = m_path_world + DIR_DELIM "env_meta.txt";

// Open file and deserialize
std::ifstream is(path.c_str(), std::ios_base::binary);
Expand Down
18 changes: 10 additions & 8 deletions src/environment.h
Expand Up @@ -70,6 +70,7 @@ class Environment

virtual void addPlayer(Player *player);
void removePlayer(u16 peer_id);
void removePlayer(const char *name);
Player * getPlayer(u16 peer_id);
Player * getPlayer(const char *name);
Player * getRandomConnectedPlayer();
Expand Down Expand Up @@ -199,7 +200,7 @@ class ServerEnvironment : public Environment
{
public:
ServerEnvironment(ServerMap *map, GameScripting *scriptIface,
IGameDef *gamedef);
IGameDef *gamedef, const std::string &path_world);
~ServerEnvironment();

Map & getMap();
Expand All @@ -216,17 +217,16 @@ class ServerEnvironment : public Environment
float getSendRecommendedInterval()
{ return m_recommended_send_interval; }

/*
Save players
*/
void serializePlayers(const std::string &savedir);
void deSerializePlayers(const std::string &savedir);
// Save players
void saveLoadedPlayers();
void savePlayer(const std::string &playername);
Player *loadPlayer(const std::string &playername);

/*
Save and load time of day and game timer
*/
void saveMeta(const std::string &savedir);
void loadMeta(const std::string &savedir);
void saveMeta();
void loadMeta();

/*
External ActiveObject interface
Expand Down Expand Up @@ -368,6 +368,8 @@ class ServerEnvironment : public Environment
GameScripting* m_script;
// Game definition
IGameDef *m_gamedef;
// World path
const std::string m_path_world;
// Active object list
std::map<u16, ServerActiveObject*> m_active_objects;
// Outgoing network message buffer for active objects
Expand Down

0 comments on commit 7e6db1b

Please sign in to comment.