]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/environment.cpp
end-of-day.
[dragonfireclient.git] / src / environment.cpp
index 7c236c3556a54324eca746e5980a43c8078df006..dc44b3a36189d4eee1446dfd42633884f20115e0 100644 (file)
@@ -18,7 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "environment.h"
-#include "main.h" // g_device for timing debug
+#include "filesys.h"
 
 Environment::Environment(Map *map, std::ostream &dout):
                m_dout(dout)
@@ -107,11 +107,13 @@ void Environment::step(float dtime)
                        v3f playerpos = player->getPosition();
                        
                        // Apply physics to local player
-                       if(player->isLocal())
+                       bool haxmode = g_settings.getBool("haxmode");
+                       if(player->isLocal() && haxmode == false)
                        {
                                // Apply gravity to local player
                                v3f speed = player->getSpeed();
-                               speed.Y -= 9.81 * BS * dtime_part * 2;
+                               if(player->swimming_up == false)
+                                       speed.Y -= 9.81 * BS * dtime_part * 2;
 
                                /*
                                        Apply water resistance
@@ -121,7 +123,7 @@ void Environment::step(float dtime)
                                        f32 max_down = 1.0*BS;
                                        if(speed.Y < -max_down) speed.Y = -max_down;
 
-                                       f32 max = 2.0*BS;
+                                       f32 max = 2.5*BS;
                                        if(speed.getLength() > max)
                                        {
                                                speed = speed / speed.getLength() * max;
@@ -190,11 +192,24 @@ Map & Environment::getMap()
 void Environment::addPlayer(Player *player)
 {
        DSTACK(__FUNCTION_NAME);
-       //Check that only one local player exists and peer_ids are unique
+       /*
+               Check that only one local player exists and peer_ids are unique.
+               Also check that names are unique.
+               Exception: there can be multiple players with peer_id=0
+       */
 #ifndef SERVER
-       assert(player->isLocal() == false || getLocalPlayer() == NULL);
+       /*
+               It is a failure if player is local and there already is a local
+               player
+       */
+       assert(!(player->isLocal() == true && getLocalPlayer() != NULL));
 #endif
-       assert(getPlayer(player->peer_id) == NULL);
+       // If peer id is non-zero, it has to be unique.
+       if(player->peer_id != 0)
+               assert(getPlayer(player->peer_id) == NULL);
+       // Name has to be unique.
+       assert(getPlayer(player->getName()) == NULL);
+       // Add.
        m_players.push_back(player);
 }
 
@@ -243,11 +258,44 @@ Player * Environment::getPlayer(u16 peer_id)
        return NULL;
 }
 
+Player * Environment::getPlayer(const char *name)
+{
+       for(core::list<Player*>::Iterator i = m_players.begin();
+                       i != m_players.end(); i++)
+       {
+               Player *player = *i;
+               if(strcmp(player->getName(), name) == 0)
+                       return player;
+       }
+       return NULL;
+}
+
 core::list<Player*> Environment::getPlayers()
 {
        return m_players;
 }
 
+core::list<Player*> Environment::getPlayers(bool ignore_disconnected)
+{
+       core::list<Player*> newlist;
+       for(core::list<Player*>::Iterator
+                       i = m_players.begin();
+                       i != m_players.end(); i++)
+       {
+               Player *player = *i;
+               
+               if(ignore_disconnected)
+               {
+                       // Ignore disconnected players
+                       if(player->peer_id == 0)
+                               continue;
+               }
+
+               newlist.push_back(player);
+       }
+       return newlist;
+}
+
 void Environment::printPlayers(std::ostream &o)
 {
        o<<"Players in environment:"<<std::endl;
@@ -259,6 +307,183 @@ void Environment::printPlayers(std::ostream &o)
        }
 }
 
+void Environment::serializePlayers(const std::string &savedir)
+{
+       std::string players_path = savedir + "/players";
+       fs::CreateDir(players_path);
+
+       core::map<Player*, bool> 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)
+                       continue;
+               
+               // Full path to this file
+               std::string path = players_path + "/" + player_files[i].name;
+
+               //dstream<<"Checking player file "<<path<<std::endl;
+
+               // Load player to see what is its name
+               ServerRemotePlayer testplayer;
+               {
+                       // Open file and deserialize
+                       std::ifstream is(path.c_str(), std::ios_base::binary);
+                       if(is.good() == false)
+                       {
+                               dstream<<"Failed to read "<<path<<std::endl;
+                               continue;
+                       }
+                       testplayer.deSerialize(is);
+               }
+
+               //dstream<<"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)
+               {
+                       dstream<<"Didn't find matching player, ignoring file "<<path<<std::endl;
+                       continue;
+               }
+
+               //dstream<<"Found matching player, overwriting."<<std::endl;
+
+               // OK, found. Save player there.
+               {
+                       // Open file and serialize
+                       std::ofstream os(path.c_str(), std::ios_base::binary);
+                       if(os.good() == false)
+                       {
+                               dstream<<"Failed to overwrite "<<path<<std::endl;
+                               continue;
+                       }
+                       player->serialize(os);
+                       saved_players.insert(player, true);
+               }
+       }
+
+       for(core::list<Player*>::Iterator i = m_players.begin();
+                       i != m_players.end(); i++)
+       {
+               Player *player = *i;
+               if(saved_players.find(player) != NULL)
+               {
+                       /*dstream<<"Player "<<player->getName()
+                                       <<" was already saved."<<std::endl;*/
+                       continue;
+               }
+               std::string playername = player->getName();
+               // Don't save unnamed player
+               if(playername == "")
+               {
+                       //dstream<<"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)
+               {
+                       dstream<<"WARNING: Didn't find free file for player"<<std::endl;
+                       continue;
+               }
+
+               {
+                       /*dstream<<"Saving player "<<player->getName()<<" to "
+                                       <<path<<std::endl;*/
+                       // Open file and serialize
+                       std::ofstream os(path.c_str(), std::ios_base::binary);
+                       if(os.good() == false)
+                       {
+                               dstream<<"WARNING: Failed to overwrite "<<path<<std::endl;
+                               continue;
+                       }
+                       player->serialize(os);
+                       saved_players.insert(player, true);
+               }
+       }
+
+       //dstream<<"Saved "<<saved_players.size()<<" players."<<std::endl;
+}
+
+void Environment::deSerializePlayers(const std::string &savedir)
+{
+       std::string players_path = savedir + "/players";
+
+       core::map<Player*, bool> 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)
+                       continue;
+               
+               // Full path to this file
+               std::string path = players_path + "/" + player_files[i].name;
+
+               dstream<<"Checking player file "<<path<<std::endl;
+
+               // Load player to see what is its name
+               ServerRemotePlayer testplayer;
+               {
+                       // Open file and deserialize
+                       std::ifstream is(path.c_str(), std::ios_base::binary);
+                       if(is.good() == false)
+                       {
+                               dstream<<"Failed to read "<<path<<std::endl;
+                               continue;
+                       }
+                       testplayer.deSerialize(is);
+               }
+
+               dstream<<"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)
+               {
+                       dstream<<"Is a new player"<<std::endl;
+                       player = new ServerRemotePlayer();
+                       newplayer = true;
+               }
+
+               // Load player
+               {
+                       dstream<<"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)
+                       {
+                               dstream<<"Failed to read "<<path<<std::endl;
+                               continue;
+                       }
+                       player->deSerialize(is);
+               }
+
+               if(newplayer)
+                       addPlayer(player);
+       }
+}
+
 #ifndef SERVER
 void Environment::updateMeshes(v3s16 blockpos)
 {