]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/server.cpp
Ctrl+C handling on POSIX, some commands for server and other tweaking
[dragonfireclient.git] / src / server.cpp
index 02a832ca2349fb02b753985c5a55ad0e11e0a221..31ebfacbb5d888294f6c09cb65351e38116f5866 100644 (file)
@@ -46,7 +46,12 @@ void * ServerThread::Thread()
        while(getRun())
        {
                try{
-                       m_server->AsyncRunStep();
+                       //TimeTaker timer("AsyncRunStep() + Receive()");
+
+                       {
+                               //TimeTaker timer("AsyncRunStep()");
+                               m_server->AsyncRunStep();
+                       }
                
                        //dout_server<<"Running m_server->Receive()"<<std::endl;
                        m_server->Receive();
@@ -166,37 +171,6 @@ void * EmergeThread::Thread()
                                                only_from_disk,
                                                changed_blocks,
                                                lighting_invalidated_blocks);
-
-#if 0
-                               /*
-                                       EXPERIMENTAL: Create a few other blocks too
-                               */
-                               
-                               map.emergeBlock(
-                                               p + v3s16(0,1,0),
-                                               only_from_disk,
-                                               changed_blocks,
-                                               lighting_invalidated_blocks);
-
-                               map.emergeBlock(
-                                               p + v3s16(0,-1,0),
-                                               only_from_disk,
-                                               changed_blocks,
-                                               lighting_invalidated_blocks);
-#if 0
-                               map.emergeBlock(
-                                               p + v3s16(0,2,0),
-                                               only_from_disk,
-                                               changed_blocks,
-                                               lighting_invalidated_blocks);
-
-                               map.emergeBlock(
-                                               p + v3s16(0,-2,0),
-                                               only_from_disk,
-                                               changed_blocks,
-                                               lighting_invalidated_blocks);
-#endif
-#endif
                        }
 
                        // If it is a dummy, block was not found on disk
@@ -998,7 +972,8 @@ Server::Server(
        m_time_counter(0),
        m_time_of_day_send_timer(0),
        m_uptime(0),
-       m_mapsavedir(mapsavedir)
+       m_mapsavedir(mapsavedir),
+       m_shutdown_requested(false)
 {
        //m_flowwater_timer = 0.0;
        m_liquid_transform_timer = 0.0;
@@ -1018,28 +993,62 @@ Server::Server(
 
 Server::~Server()
 {
-       // Save players
+       /*
+               Send shutdown message
+       */
+       {
+               JMutexAutoLock conlock(m_con_mutex);
+               
+               std::wstring line = L"*** Server shutting down";
+
+               /*
+                       Send the message to clients
+               */
+               for(core::map<u16, RemoteClient*>::Iterator
+                       i = m_clients.getIterator();
+                       i.atEnd() == false; i++)
+               {
+                       // Get client and check that it is valid
+                       RemoteClient *client = i.getNode()->getValue();
+                       assert(client->peer_id == i.getNode()->getKey());
+                       if(client->serialization_version == SER_FMT_VER_INVALID)
+                               continue;
+
+                       SendChatMessage(client->peer_id, line);
+               }
+       }
+
+       /*
+               Save players
+       */
        m_env.serializePlayers(m_mapsavedir);
        
-       // Stop threads
+       /*
+               Stop threads
+       */
        stop();
-
-       JMutexAutoLock clientslock(m_con_mutex);
-
-       for(core::map<u16, RemoteClient*>::Iterator
-               i = m_clients.getIterator();
-               i.atEnd() == false; i++)
+       
+       /*
+               Delete clients
+       */
        {
-               /*// Delete player
-               // NOTE: These are removed by env destructor
+               JMutexAutoLock clientslock(m_con_mutex);
+
+               for(core::map<u16, RemoteClient*>::Iterator
+                       i = m_clients.getIterator();
+                       i.atEnd() == false; i++)
                {
-                       u16 peer_id = i.getNode()->getKey();
-                       JMutexAutoLock envlock(m_env_mutex);
-                       m_env.removePlayer(peer_id);
-               }*/
-               
-               // Delete client
-               delete i.getNode()->getValue();
+                       /*// Delete player
+                       // NOTE: These are removed by env destructor
+                       {
+                               u16 peer_id = i.getNode()->getKey();
+                               JMutexAutoLock envlock(m_env_mutex);
+                               m_env.removePlayer(peer_id);
+                       }*/
+                       
+                       // Delete client
+                       delete i.getNode()->getValue();
+               }
        }
 }
 
@@ -1617,39 +1626,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                        m_time_of_day.get());
                        m_con.Send(peer->id, 0, data, true);
                }
-
+               
                // Send information about server to player in chat
-               {
-                       std::wostringstream os(std::ios_base::binary);
-                       os<<L"# Server: ";
-                       // Uptime
-                       os<<L"uptime="<<m_uptime.get();
-                       // Information about clients
-                       os<<L", clients={";
-                       for(core::map<u16, RemoteClient*>::Iterator
-                               i = m_clients.getIterator();
-                               i.atEnd() == false; i++)
-                       {
-                               // Get client and check that it is valid
-                               RemoteClient *client = i.getNode()->getValue();
-                               assert(client->peer_id == i.getNode()->getKey());
-                               if(client->serialization_version == SER_FMT_VER_INVALID)
-                                       continue;
-                               // Get player
-                               Player *player = m_env.getPlayer(client->peer_id);
-                               // Get name of player
-                               std::wstring name = L"unknown";
-                               if(player != NULL)
-                                       name = narrow_to_wide(player->getName());
-                               // Add name to information string
-                               os<<name<<L",";
-                       }
-                       os<<L"}";
-                       if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == false)
-                               os<<" WARNING: Map saving is disabled."<<std::endl;
-                       // Send message
-                       SendChatMessage(peer_id, os.str());
-               }
+               SendChatMessage(peer_id, getStatusString());
                
                // Send information about joining in chat
                {
@@ -2492,29 +2471,115 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
                // Get player name of this client
                std::wstring name = narrow_to_wide(player->getName());
-
-               std::wstring line = std::wstring(L"<")+name+L"> "+message;
                
-               dstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
-
-               /*
-                       Send the message to all other clients
-               */
-               for(core::map<u16, RemoteClient*>::Iterator
-                       i = m_clients.getIterator();
-                       i.atEnd() == false; i++)
+               // Line to send to players
+               std::wstring line;
+               // Whether to send to the player that sent the line
+               bool send_to_sender = false;
+               // Whether to send to other players
+               bool send_to_others = false;
+               
+               // Parse commands
+               std::wstring commandprefix = L"/#";
+               if(message.substr(0, commandprefix.size()) == commandprefix)
+               {
+                       line += L"Server: ";
+
+                       message = message.substr(commandprefix.size());
+                       // Get player name as narrow string
+                       std::string name_s = player->getName();
+                       // Convert message to narrow string
+                       std::string message_s = wide_to_narrow(message);
+                       // Operator is the single name defined in config.
+                       std::string operator_name = g_settings.get("name");
+                       bool is_operator = (operator_name != "" &&
+                                       wide_to_narrow(name) == operator_name);
+                       bool valid_command = false;
+                       if(message_s == "help")
+                       {
+                               line += L"-!- Available commands: ";
+                               line += L"status ";
+                               if(is_operator)
+                               {
+                                       line += L"shutdown setting ";
+                               }
+                               else
+                               {
+                               }
+                               send_to_sender = true;
+                               valid_command = true;
+                       }
+                       else if(message_s == "status")
+                       {
+                               line = getStatusString();
+                               send_to_sender = true;
+                               valid_command = true;
+                       }
+                       else if(is_operator)
+                       {
+                               if(message_s == "shutdown")
+                               {
+                                       dstream<<DTIME<<" Server: Operator requested shutdown."
+                                                       <<std::endl;
+                                       m_shutdown_requested.set(true);
+                                       
+                                       line += L"*** Server shutting down (operator request)";
+                                       send_to_sender = true;
+                                       valid_command = true;
+                               }
+                               else if(message_s.substr(0,8) == "setting ")
+                               {
+                                       std::string confline = message_s.substr(8);
+                                       g_settings.parseConfigLine(confline);
+                                       line += L"-!- Setting changed.";
+                                       send_to_sender = true;
+                                       valid_command = true;
+                               }
+                       }
+                       
+                       if(valid_command == false)
+                       {
+                               line += L"-!- Invalid command: " + message;
+                               send_to_sender = true;
+                       }
+               }
+               else
                {
-                       // Get client and check that it is valid
-                       RemoteClient *client = i.getNode()->getValue();
-                       assert(client->peer_id == i.getNode()->getKey());
-                       if(client->serialization_version == SER_FMT_VER_INVALID)
-                               continue;
+                       line += L"<";
+                       /*if(is_operator)
+                               line += L"@";*/
+                       line += name;
+                       line += L"> ";
+                       line += message;
+                       send_to_others = true;
+               }
+               
+               if(line != L"")
+               {
+                       dstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
 
-                       // Don't send if it's the same one
-                       if(peer_id == client->peer_id)
-                               continue;
+                       /*
+                               Send the message to clients
+                       */
+                       for(core::map<u16, RemoteClient*>::Iterator
+                               i = m_clients.getIterator();
+                               i.atEnd() == false; i++)
+                       {
+                               // Get client and check that it is valid
+                               RemoteClient *client = i.getNode()->getValue();
+                               assert(client->peer_id == i.getNode()->getKey());
+                               if(client->serialization_version == SER_FMT_VER_INVALID)
+                                       continue;
 
-                       SendChatMessage(client->peer_id, line);
+                               // Filter recipient
+                               bool sender_selected = (peer_id == client->peer_id);
+                               if(sender_selected == true && send_to_sender == false)
+                                       continue;
+                               if(sender_selected == false && send_to_others == false)
+                                       continue;
+
+                               SendChatMessage(client->peer_id, line);
+                       }
                }
        }
        else
@@ -2611,6 +2676,7 @@ core::list<PlayerInfo> Server::getPlayerInfo()
        return list;
 }
 
+
 void Server::peerAdded(con::Peer *peer)
 {
        DSTACK(__FUNCTION_NAME);
@@ -3051,6 +3117,8 @@ void Server::SendBlocks(float dtime)
 
        JMutexAutoLock envlock(m_env_mutex);
 
+       //TimeTaker timer("Server::SendBlocks");
+
        core::array<PrioritySortedBlockTransfer> queue;
 
        s32 total_sending = 0;
@@ -3118,6 +3186,39 @@ RemoteClient* Server::getClient(u16 peer_id)
        return n->getValue();
 }
 
+std::wstring Server::getStatusString()
+{
+       std::wostringstream os(std::ios_base::binary);
+       os<<L"# Server: ";
+       // Uptime
+       os<<L"uptime="<<m_uptime.get();
+       // Information about clients
+       os<<L", clients={";
+       for(core::map<u16, RemoteClient*>::Iterator
+               i = m_clients.getIterator();
+               i.atEnd() == false; i++)
+       {
+               // Get client and check that it is valid
+               RemoteClient *client = i.getNode()->getValue();
+               assert(client->peer_id == i.getNode()->getKey());
+               if(client->serialization_version == SER_FMT_VER_INVALID)
+                       continue;
+               // Get player
+               Player *player = m_env.getPlayer(client->peer_id);
+               // Get name of player
+               std::wstring name = L"unknown";
+               if(player != NULL)
+                       name = narrow_to_wide(player->getName());
+               // Add name to information string
+               os<<name<<L",";
+       }
+       os<<L"}";
+       if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == false)
+               os<<" WARNING: Map saving is disabled."<<std::endl;
+       return os.str();
+}
+
+
 void setCreativeInventory(Player *player)
 {
        player->resetInventory();
@@ -3486,11 +3587,11 @@ void Server::handlePeerChanges()
        }
 }
 
-void dedicated_server_loop(Server &server)
+void dedicated_server_loop(Server &server, bool &kill)
 {
        DSTACK(__FUNCTION_NAME);
        
-       std::cout<<std::endl;
+       std::cout<<DTIME<<std::endl;
        std::cout<<"========================"<<std::endl;
        std::cout<<"Running dedicated server"<<std::endl;
        std::cout<<"========================"<<std::endl;
@@ -3503,6 +3604,12 @@ void dedicated_server_loop(Server &server)
                sleep_ms(30);
                server.step(0.030);
 
+               if(server.getShutdownRequested() || kill)
+               {
+                       std::cout<<DTIME<<" dedicated_server_loop(): Quitting."<<std::endl;
+                       break;
+               }
+
                static int counter = 0;
                counter--;
                if(counter <= 0)