]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/server.cpp
Fix doc and forceloading crash.
[dragonfireclient.git] / src / server.cpp
index 13b59e7f5c1b41e686bc8e575ba7ba9015aa96ce..b257448a1c4e2de8b1b7091ffd74e103352e4c2a 100644 (file)
@@ -73,14 +73,14 @@ class ClientNotFoundException : public BaseException
        {}
 };
 
-class ServerThread : public SimpleThread
+class ServerThread : public JThread
 {
        Server *m_server;
 
 public:
 
        ServerThread(Server *server):
-               SimpleThread(),
+               JThread(),
                m_server(server)
        {
        }
@@ -90,15 +90,16 @@ class ServerThread : public SimpleThread
 
 void * ServerThread::Thread()
 {
-       ThreadStarted();
-
        log_register_thread("ServerThread");
 
        DSTACK(__FUNCTION_NAME);
-
        BEGIN_DEBUG_EXCEPTION_HANDLER
 
-       while(getRun())
+       m_server->AsyncRunStep(true);
+
+       ThreadStarted();
+
+       while(!StopRequested())
        {
                try{
                        //TimeTaker timer("AsyncRunStep() + Receive()");
@@ -675,6 +676,7 @@ Server::Server(
        m_savemap_timer = 0.0;
 
        m_step_dtime = 0.0;
+       m_lag = g_settings->getFloat("dedicated_server_step");
 
        if(path_world == "")
                throw ServerError("Supplied empty world path");
@@ -703,6 +705,10 @@ Server::Server(
        // Create emerge manager
        m_emerge = new EmergeManager(this);
 
+       // Create world if it doesn't exist
+       if(!initializeWorld(m_path_world, m_gamespec.id))
+               throw ServerError("Failed to initialize world");
+
        // Create ban manager
        std::string ban_path = m_path_world+DIR_DELIM+"ipban.txt";
        m_banmanager = new BanManager(ban_path);
@@ -711,10 +717,6 @@ Server::Server(
        std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt";
        m_rollback = createRollbackManager(rollback_path, this);
 
-       // Create world if it doesn't exist
-       if(!initializeWorld(m_path_world, m_gamespec.id))
-               throw ServerError("Failed to initialize world");
-
        ModConfiguration modconf(m_path_world);
        m_mods = modconf.getMods();
        std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
@@ -823,6 +825,7 @@ Server::Server(
        
        // Initialize mapgens
        m_emerge->initMapgens(mgparams);
+       servermap->setMapgenParams(m_emerge->params);
 
        // Give environment reference to scripting api
        m_script->initializeEnvironment(m_env);
@@ -962,14 +965,13 @@ void Server::start(unsigned short port)
        infostream<<"Starting server on port "<<port<<"..."<<std::endl;
 
        // Stop thread if already running
-       m_thread->stop();
+       m_thread->Stop();
 
        // Initialize connection
        m_con.SetTimeoutMs(30);
        m_con.Serve(port);
 
        // Start thread
-       m_thread->setRun(true);
        m_thread->Start();
 
        // ASCII art for the win!
@@ -992,9 +994,9 @@ void Server::stop()
        infostream<<"Server: Stopping and waiting threads"<<std::endl;
 
        // Stop threads (set run=false first so both start stopping)
-       m_thread->setRun(false);
+       m_thread->Stop();
        //m_emergethread.setRun(false);
-       m_thread->stop();
+       m_thread->Wait();
        //m_emergethread.stop();
 
        infostream<<"Server: Threads stopped"<<std::endl;
@@ -1017,7 +1019,7 @@ void Server::step(float dtime)
        }
 }
 
-void Server::AsyncRunStep()
+void Server::AsyncRunStep(bool initial_step)
 {
        DSTACK(__FUNCTION_NAME);
 
@@ -1034,7 +1036,7 @@ void Server::AsyncRunStep()
                SendBlocks(dtime);
        }
 
-       if(dtime < 0.001)
+       if((dtime < 0.001) && (initial_step == false))
                return;
 
        g_profiler->add("Server::AsyncRunStep with dtime (num)", 1);
@@ -1260,13 +1262,14 @@ void Server::AsyncRunStep()
        }
 
 
+       m_lag += (m_lag > dtime ? -1 : 1) * dtime/100;
 #if USE_CURL
        // send masterserver announce
        {
                float &counter = m_masterserver_timer;
                if(!isSingleplayer() && (!counter || counter >= 300.0) && g_settings->getBool("server_announce") == true)
                {
-                       ServerList::sendAnnounce(!counter ? "start" : "update", m_clients_names, m_uptime.get(), m_env->getGameTime(), m_gamespec.id, m_mods);
+                       ServerList::sendAnnounce(!counter ? "start" : "update", m_clients_names, m_uptime.get(), m_env->getGameTime(), m_lag, m_gamespec.id, m_mods);
                        counter = 0.01;
                }
                counter += dtime;
@@ -1526,7 +1529,7 @@ void Server::AsyncRunStep()
                                memcpy((char*)&reply[2], unreliable_data.c_str(),
                                                unreliable_data.size());
                                // Send as unreliable
-                               m_con.Send(client->peer_id, 0, reply, false);
+                               m_con.Send(client->peer_id, 1, reply, false);
                        }
 
                        /*if(reliable_data.size() > 0 || unreliable_data.size() > 0)
@@ -1681,7 +1684,7 @@ void Server::AsyncRunStep()
                {
                        counter = 0.0;
 
-                       m_emerge->triggerAllThreads();
+                       m_emerge->startAllThreads();
 
                        // Update m_enable_rollback_recording here too
                        m_enable_rollback_recording =
@@ -1970,6 +1973,19 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        return;
                }
 
+               {
+                       std::string reason;
+                       if(m_script->on_prejoinplayer(playername, addr_s, reason))
+                       {
+                               actionstream<<"Server: Player with the name \""<<playername<<"\" "
+                                               <<"tried to connect from "<<addr_s<<" "
+                                               <<"but it was disallowed for the following reason: "
+                                               <<reason<<std::endl;
+                               DenyAccess(peer_id, narrow_to_wide(reason.c_str()));
+                               return;
+                       }
+               }
+
                infostream<<"Server: New connection: \""<<playername<<"\" from "
                                <<addr_s<<" (peer_id="<<peer_id<<")"<<std::endl;
 
@@ -2285,9 +2301,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                }
 
                /*infostream<<"Server::ProcessData(): Moved player "<<peer_id<<" to "
-                                                                                                                       <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
-                                                                                                                       <<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
-
+                               <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
+                               <<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
        }
        else if(command == TOSERVER_GOTBLOCKS)
        {
@@ -2732,7 +2747,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                std::string datastring((char*)&data[2], datasize-2);
                std::istringstream is(datastring, std::ios_base::binary);
 
-               std::list<MediaRequest> tosend;
+               std::list<std::string> tosend;
                u16 numfiles = readU16(is);
 
                infostream<<"Sending "<<numfiles<<" files to "
@@ -2741,7 +2756,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
                for(int i = 0; i < numfiles; i++) {
                        std::string name = deSerializeString(is);
-                       tosend.push_back(MediaRequest(name));
+                       tosend.push_back(name);
                        verbosestream<<"TOSERVER_REQUEST_MEDIA: requested file "
                                        <<name<<std::endl;
                }
@@ -3707,7 +3722,7 @@ void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
        std::string s = os.str();
        SharedBuffer<u8> data((u8*)s.c_str(), s.size());
        // Send as reliable
-       m_con.Send(peer_id, 0, data, true);
+       m_con.Send(peer_id, 1, data, true);
 }
 
 void Server::SendHUDRemove(u16 peer_id, u32 id)
@@ -3722,7 +3737,8 @@ void Server::SendHUDRemove(u16 peer_id, u32 id)
        std::string s = os.str();
        SharedBuffer<u8> data((u8*)s.c_str(), s.size());
        // Send as reliable
-       m_con.Send(peer_id, 0, data, true);
+
+       m_con.Send(peer_id, 1, data, true);
 }
 
 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
@@ -4190,7 +4206,7 @@ void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto
        /*
                Send packet
        */
-       m_con.Send(peer_id, 1, reply, true);
+       m_con.Send(peer_id, 2, reply, true);
 }
 
 void Server::SendBlocks(float dtime)
@@ -4440,7 +4456,7 @@ struct SendableMedia
 };
 
 void Server::sendRequestedMedia(u16 peer_id,
-               const std::list<MediaRequest> &tosend)
+               const std::list<std::string> &tosend)
 {
        DSTACK(__FUNCTION_NAME);
 
@@ -4457,17 +4473,19 @@ void Server::sendRequestedMedia(u16 peer_id,
 
        u32 file_size_bunch_total = 0;
 
-       for(std::list<MediaRequest>::const_iterator i = tosend.begin();
+       for(std::list<std::string>::const_iterator i = tosend.begin();
                        i != tosend.end(); ++i)
        {
-               if(m_media.find(i->name) == m_media.end()){
+               const std::string &name = *i;
+
+               if(m_media.find(name) == m_media.end()){
                        errorstream<<"Server::sendRequestedMedia(): Client asked for "
-                                       <<"unknown file \""<<(i->name)<<"\""<<std::endl;
+                                       <<"unknown file \""<<(name)<<"\""<<std::endl;
                        continue;
                }
 
                //TODO get path + name
-               std::string tpath = m_media[(*i).name].path;
+               std::string tpath = m_media[name].path;
 
                // Read data
                std::ifstream fis(tpath.c_str(), std::ios_base::binary);
@@ -4493,14 +4511,14 @@ void Server::sendRequestedMedia(u16 peer_id,
                }
                if(bad){
                        errorstream<<"Server::sendRequestedMedia(): Failed to read \""
-                                       <<(*i).name<<"\""<<std::endl;
+                                       <<name<<"\""<<std::endl;
                        continue;
                }
                /*infostream<<"Server::sendRequestedMedia(): Loaded \""
                                <<tname<<"\""<<std::endl;*/
                // Put in list
                file_bunches[file_bunches.size()-1].push_back(
-                               SendableMedia((*i).name, tpath, tmp_os.str()));
+                               SendableMedia(name, tpath, tmp_os.str()));
 
                // Start next bunch if got enough data
                if(file_size_bunch_total >= bytes_per_bunch){
@@ -4550,7 +4568,7 @@ void Server::sendRequestedMedia(u16 peer_id,
                                <<" size=" <<s.size()<<std::endl;
                SharedBuffer<u8> data((u8*)s.c_str(), s.size());
                // Send as reliable
-               m_con.Send(peer_id, 0, data, true);
+               m_con.Send(peer_id, 2, data, true);
        }
 }
 
@@ -5319,10 +5337,10 @@ v3f findSpawnPos(ServerMap &map)
                                -range + (myrand() % (range * 2)));
 
                // Get ground height at point
-               s16 groundheight = map.findGroundLevel(nodepos2d, g_settings->getBool("cache_block_before_spawn"));
+               s16 groundheight = map.findGroundLevel(nodepos2d);
                if (groundheight <= water_level) // Don't go underwater
                        continue;
-               if (groundheight > water_level + g_settings->getS16("max_spawn_height")) // Don't go to high places
+               if (groundheight > water_level + 6) // Don't go to high places
                        continue;
 
                nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);