]> git.lizzy.rs Git - minetest.git/blobdiff - src/server.cpp
Revert old 4BS/s walk speed for now
[minetest.git] / src / server.cpp
index 8f40cfa5b809545cd9a0284730300e85e01995a4..2139df957388a8b05740cdaf4440374541fdf9ec 100644 (file)
@@ -109,6 +109,10 @@ void * ServerThread::Thread()
                {
                        infostream<<"Server: PeerNotFoundException"<<std::endl;
                }
+               catch(con::ConnectionBindFailed &e)
+               {
+                       m_server->setAsyncFatalError(e.what());
+               }
        }
        
        END_DEBUG_EXCEPTION_HANDLER(errorstream)
@@ -830,13 +834,16 @@ void PlayerInfo::PrintLine(std::ostream *s)
 */
 
 Server::Server(
-               std::string path_world,
-               std::string path_config,
-               std::string gamename
+               const std::string &path_world,
+               const std::string &path_config,
+               const SubgameSpec &gamespec,
+               bool simple_singleplayer_mode
        ):
-       m_gamename(gamename),
        m_path_world(path_world),
        m_path_config(path_config),
+       m_gamespec(gamespec),
+       m_simple_singleplayer_mode(simple_singleplayer_mode),
+       m_async_fatal_error(""),
        m_env(NULL),
        m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
        m_authmanager(path_world+DIR_DELIM+"auth.txt"),
@@ -865,57 +872,51 @@ Server::Server(
        m_step_dtime_mutex.Init();
        m_step_dtime = 0.0;
 
+       if(path_world == "")
+               throw ServerError("Supplied empty world path");
+       
+       if(!gamespec.isValid())
+               throw ServerError("Supplied invalid gamespec");
+       
        // Figure out some paths
        // share/server
        m_path_share = porting::path_share + DIR_DELIM + "server";
-       // game
-       m_path_game = porting::path_user + DIR_DELIM + "server" + DIR_DELIM
-                       + "games" + DIR_DELIM + m_gamename;
-       bool user_game = true; // Game is in user's directory
-       if(!fs::PathExists(m_path_game)){
-               m_path_game = m_path_share + DIR_DELIM + "games" + DIR_DELIM
-                               + m_gamename;
-               user_game = false;
-       }
-       if(!fs::PathExists(m_path_game)){
-               throw ServerError("Could not find game files for game \""
-                               +gamename+"\"");
-       }
-       // addons
-       if(!user_game)
-               m_path_addons.insert(m_path_share + DIR_DELIM + "addons"
-                               + DIR_DELIM + m_gamename);
-       m_path_addons.insert(porting::path_user + DIR_DELIM + "server"
-                       + DIR_DELIM + "addons" + DIR_DELIM + m_gamename);
-
-       infostream<<"Server created for gamename=\""<<gamename<<"\""<<std::endl;
-       infostream<<"- path_world  = "<<m_path_world<<std::endl;
-       infostream<<"- path_config = "<<m_path_config<<std::endl;
-       infostream<<"- path_game   = "<<m_path_game<<std::endl;
-       for(std::set<std::string>::const_iterator i = m_path_addons.begin();
-                       i != m_path_addons.end(); i++)
-               infostream<<"- path_addons+= "<<(*i)<<std::endl;
+
+       infostream<<"Server created for gameid \""<<m_gamespec.id<<"\"";
+       if(m_simple_singleplayer_mode)
+               infostream<<" in simple singleplayer mode"<<std::endl;
+       else
+               infostream<<std::endl;
+       infostream<<"- world:  "<<m_path_world<<std::endl;
+       infostream<<"- config: "<<m_path_config<<std::endl;
+       infostream<<"- game:   "<<m_gamespec.path<<std::endl;
+       for(std::set<std::string>::const_iterator i = m_gamespec.addon_paths.begin();
+                       i != m_gamespec.addon_paths.end(); i++)
+               infostream<<"- addons: "<<(*i)<<std::endl;
 
        // Path to builtin.lua
        std::string builtinpath = m_path_share + DIR_DELIM + "builtin.lua";
 
        // Add default global mod search path
-       m_modspaths.push_front(m_path_game + DIR_DELIM "mods");
+       m_modspaths.push_front(m_gamespec.path + DIR_DELIM "mods");
        // Add world mod search path
        m_modspaths.push_front(m_path_world + DIR_DELIM + "worldmods");
        // Add addon mod search path
-       for(std::set<std::string>::const_iterator i = m_path_addons.begin();
-                       i != m_path_addons.end(); i++){
+       for(std::set<std::string>::const_iterator i = m_gamespec.addon_paths.begin();
+                       i != m_gamespec.addon_paths.end(); i++)
                m_modspaths.push_front((*i) + DIR_DELIM + "mods");
-       }
 
        // Print out mod search paths
        for(core::list<std::string>::Iterator i = m_modspaths.begin();
                        i != m_modspaths.end(); i++){
                std::string modspath = *i;
-               infostream<<"- modspath   += "<<modspath<<std::endl;
+               infostream<<"- mods:   "<<modspath<<std::endl;
        }
        
+       // Create world if it doesn't exist
+       if(!initializeWorld(m_path_world, m_gamespec.id))
+               throw ServerError("Failed to initialize world");
+
        // Lock environment
        JMutexAutoLock envlock(m_env_mutex);
        JMutexAutoLock conlock(m_con_mutex);
@@ -1087,6 +1088,8 @@ Server::~Server()
 void Server::start(unsigned short port)
 {
        DSTACK(__FUNCTION_NAME);
+       infostream<<"Starting server on port "<<port<<"..."<<std::endl;
+
        // Stop thread if already running
        m_thread.stop();
        
@@ -1106,7 +1109,9 @@ void Server::start(unsigned short port)
        <<"|  Y Y  \\  |   |  \\  ___/|  | \\  ___/ \\___ \\  |  |  "<<std::endl
        <<"|__|_|  /__|___|  /\\___  >__|  \\___  >____  > |__|  "<<std::endl
        <<"      \\/        \\/     \\/          \\/     \\/        "<<std::endl;
-       actionstream<<"Server listening on port "<<port<<"."<<std::endl;
+       actionstream<<"World at ["<<m_path_world<<"]"<<std::endl;
+       actionstream<<"Server for gameid=\""<<m_gamespec.id
+                       <<"\" listening on port "<<port<<"."<<std::endl;
 }
 
 void Server::stop()
@@ -1134,6 +1139,11 @@ void Server::step(float dtime)
                JMutexAutoLock lock(m_step_dtime_mutex);
                m_step_dtime += dtime;
        }
+       // Throw if fatal error occurred in thread
+       std::string async_err = m_async_fatal_error.get();
+       if(async_err != ""){
+               throw ServerError(async_err);
+       }
 }
 
 void Server::AsyncRunStep()
@@ -2101,6 +2111,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        SendAccessDenied(m_con, peer_id, L"Invalid password");
                        return;
                }
+
+               // Do not allow multiple players in simple singleplayer mode.
+               // This isn't a perfect way to do it, but will suffice for now.
+               if(m_simple_singleplayer_mode && m_clients.size() > 1){
+                       infostream<<"Server: Not allowing another client to connect in"
+                                       <<" simple singleplayer mode"<<std::endl;
+                       SendAccessDenied(m_con, peer_id,
+                                       L"Running in simple singleplayer mode.");
+                       return;
+               }
                
                // Enforce user limit.
                // Don't enforce for users that have some admin right
@@ -2200,21 +2220,25 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        m_con.Send(peer_id, 0, data, true);
                }
                
-               // Send information about server to player in chat
-               SendChatMessage(peer_id, getStatusString());
-               
-               // Send information about joining in chat
+               // Note things in chat if not in simple singleplayer mode
+               if(!m_simple_singleplayer_mode)
                {
-                       std::wstring name = L"unknown";
-                       Player *player = m_env->getPlayer(peer_id);
-                       if(player != NULL)
-                               name = narrow_to_wide(player->getName());
+                       // Send information about server to player in chat
+                       SendChatMessage(peer_id, getStatusString());
                        
-                       std::wstring message;
-                       message += L"*** ";
-                       message += name;
-                       message += L" joined game";
-                       BroadcastChatMessage(message);
+                       // Send information about joining in chat
+                       {
+                               std::wstring name = L"unknown";
+                               Player *player = m_env->getPlayer(peer_id);
+                               if(player != NULL)
+                                       name = narrow_to_wide(player->getName());
+                               
+                               std::wstring message;
+                               message += L"*** ";
+                               message += name;
+                               message += L" joined game";
+                               BroadcastChatMessage(message);
+                       }
                }
                
                // Warnings about protocol version can be issued here
@@ -4158,6 +4182,40 @@ std::wstring Server::getStatusString()
        return os.str();
 }
 
+u64 Server::getPlayerAuthPrivs(const std::string &name)
+{
+       try{
+               return m_authmanager.getPrivs(name);
+       }
+       catch(AuthNotFoundException &e)
+       {
+               dstream<<"WARNING: Auth not found for "<<name<<std::endl;
+               return 0;
+       }
+}
+
+void Server::setPlayerAuthPrivs(const std::string &name, u64 privs)
+{
+       try{
+               return m_authmanager.setPrivs(name, privs);
+       }
+       catch(AuthNotFoundException &e)
+       {
+               dstream<<"WARNING: Auth not found for "<<name<<std::endl;
+       }
+}
+
+u64 Server::getPlayerEffectivePrivs(const std::string &name)
+{
+       // Local player gets all privileges regardless of
+       // what's set on their account.
+       if(m_simple_singleplayer_mode)
+               return PRIV_ALL;
+       if(name == g_settings->get("name"))
+               return PRIV_ALL;
+       return getPlayerAuthPrivs(name);
+}
+
 void Server::setPlayerPassword(const std::string &name, const std::wstring &password)
 {
        // Add player to auth manager
@@ -4546,16 +4604,7 @@ u64 Server::getPlayerPrivs(Player *player)
        if(player==NULL)
                return 0;
        std::string playername = player->getName();
-       // Local player gets all privileges regardless of
-       // what's set on their account.
-       if(g_settings->get("name") == playername)
-       {
-               return PRIV_ALL;
-       }
-       else
-       {
-               return getPlayerAuthPrivs(playername);
-       }
+       return getPlayerEffectivePrivs(playername);
 }
 
 void dedicated_server_loop(Server &server, bool &kill)