summaryrefslogtreecommitdiff
path: root/src/server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.cpp')
-rw-r--r--src/server.cpp282
1 files changed, 210 insertions, 72 deletions
diff --git a/src/server.cpp b/src/server.cpp
index dc72661ff..31ebfacbb 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -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();
@@ -967,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;
@@ -987,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();
+ }
}
}
@@ -1586,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
{
@@ -2461,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
@@ -2580,6 +2676,7 @@ core::list<PlayerInfo> Server::getPlayerInfo()
return list;
}
+
void Server::peerAdded(con::Peer *peer)
{
DSTACK(__FUNCTION_NAME);
@@ -3020,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;
@@ -3087,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();
@@ -3455,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;
@@ -3472,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)