Created
January 12, 2014 11:48
-
-
Save sapier/8383662 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/connection.cpp b/src/connection.cpp | |
index ee03b21..b32a965 100644 | |
--- a/src/connection.cpp | |
+++ b/src/connection.cpp | |
@@ -1985,11 +1985,10 @@ void * ConnectionReceiveThread::Thread() | |
// Receive packets from the network and buffers and create ConnectionEvents | |
void ConnectionReceiveThread::receive() | |
{ | |
- /* now reorder reliables */ | |
- u32 datasize = m_max_packet_size * 2; // Double it just to be safe | |
- // TODO: We can not know how many layers of header there are. | |
- // For now, just assume there are no other than the base headers. | |
- u32 packet_maxsize = datasize + BASE_HEADER_SIZE; | |
+ // use IPv6 minimum allowed MTU as receive buffer size as this is | |
+ // theoretical reliable upper boundary of a udp packet for all IPv6 enabled | |
+ // infrastructure | |
+ unsigned int packet_maxsize = 1500; | |
SharedBuffer<u8> packetdata(packet_maxsize); | |
bool packet_queued = true; | |
@@ -2124,7 +2123,7 @@ void ConnectionReceiveThread::receive() | |
LOG(dout_con<<m_connection->getDesc() | |
<<" ProcessPacket from peer_id: " << peer_id | |
- << ",channel: " << channelnum << ", returned " | |
+ << ",channel: " << (channelnum & 0xFF) << ", returned " | |
<< resultdata.getSize() << " bytes" <<std::endl); | |
ConnectionEvent e; | |
@@ -2872,11 +2871,6 @@ u16 Connection::createPeer(Address& sender, MTProtocols protocol, int fd) | |
m_peers[peer->id] = peer; | |
m_peers_mutex.Unlock(); | |
- // Create peer addition event | |
- ConnectionEvent e; | |
- e.peerAdded(peer_id_new, sender); | |
- putEvent(e); | |
- | |
ConnectionCommand cmd; | |
SharedBuffer<u8> reply(4); | |
writeU8(&reply[0], TYPE_CONTROL); | |
@@ -2885,6 +2879,11 @@ u16 Connection::createPeer(Address& sender, MTProtocols protocol, int fd) | |
cmd.createPeer(peer_id_new,reply); | |
this->putCommand(cmd); | |
+ // Create peer addition event | |
+ ConnectionEvent e; | |
+ e.peerAdded(peer_id_new, sender); | |
+ putEvent(e); | |
+ | |
// We're now talking to a valid peer_id | |
return peer_id_new; | |
} | |
diff --git a/src/emerge.cpp b/src/emerge.cpp | |
index ff00a0b..0f96053 100644 | |
--- a/src/emerge.cpp | |
+++ b/src/emerge.cpp | |
@@ -565,7 +565,7 @@ void *EmergeThread::Thread() { | |
// NOTE: Server's clients are also behind the connection mutex | |
//conlock: consistently takes 30-40ms to acquire | |
- JMutexAutoLock lock(m_server->m_con_mutex); | |
+ JMutexAutoLock lock(m_server->m_clients_mutex); | |
// Add the originally fetched block to the modified list | |
if (block) | |
modified_blocks[p] = block; | |
diff --git a/src/server.cpp b/src/server.cpp | |
index b257448..9a055d1 100644 | |
--- a/src/server.cpp | |
+++ b/src/server.cpp | |
@@ -104,13 +104,10 @@ void * ServerThread::Thread() | |
try{ | |
//TimeTaker timer("AsyncRunStep() + Receive()"); | |
- { | |
- //TimeTaker timer("AsyncRunStep()"); | |
- m_server->AsyncRunStep(); | |
- } | |
+ m_server->AsyncRunStep(); | |
- //infostream<<"Running m_server->Receive()"<<std::endl; | |
m_server->Receive(); | |
+ | |
} | |
catch(con::NoIncomingDataException &e) | |
{ | |
@@ -768,10 +765,8 @@ void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks) | |
// Lock environment | |
JMutexAutoLock envlock(m_env_mutex); | |
- JMutexAutoLock conlock(m_con_mutex); | |
// Initialize scripting | |
- | |
infostream<<"Server: Initializing Lua"<<std::endl; | |
m_script = new GameScripting(this); | |
@@ -860,34 +855,13 @@ void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks) | |
Send shutdown message | |
*/ | |
{ | |
- JMutexAutoLock conlock(m_con_mutex); | |
- | |
std::wstring line = L"*** Server shutting down"; | |
- | |
- /* | |
- Send the message to clients | |
- */ | |
- for(std::map<u16, RemoteClient*>::iterator | |
- i = m_clients.begin(); | |
- i != m_clients.end(); ++i) | |
- { | |
- // Get client and check that it is valid | |
- RemoteClient *client = i->second; | |
- assert(client->peer_id == i->first); | |
- if(client->serialization_version == SER_FMT_VER_INVALID) | |
- continue; | |
- | |
- try{ | |
- SendChatMessage(client->peer_id, line); | |
- } | |
- catch(con::PeerNotFoundException &e) | |
- {} | |
- } | |
+ SendChatMessage(PEER_ID_INEXISTENT, line); | |
} | |
{ | |
JMutexAutoLock envlock(m_env_mutex); | |
- JMutexAutoLock conlock(m_con_mutex); | |
+ JMutexAutoLock conlock(m_clients_mutex); | |
/* | |
Execute script shutdown hooks | |
@@ -924,7 +898,7 @@ void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks) | |
Delete clients | |
*/ | |
{ | |
- JMutexAutoLock clientslock(m_con_mutex); | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
for(std::map<u16, RemoteClient*>::iterator | |
i = m_clients.begin(); | |
@@ -1058,7 +1032,7 @@ void Server::AsyncRunStep(bool initial_step) | |
{ | |
// Process connection's timeouts | |
- JMutexAutoLock lock2(m_con_mutex); | |
+ JMutexAutoLock lock2(m_clients_mutex); | |
ScopeProfiler sp(g_profiler, "Server: connection timeout processing"); | |
m_con.RunTimeouts(dtime); | |
} | |
@@ -1085,20 +1059,9 @@ void Server::AsyncRunStep(bool initial_step) | |
if(m_time_of_day_send_timer < 0.0) | |
{ | |
m_time_of_day_send_timer = g_settings->getFloat("time_send_interval"); | |
- | |
- //JMutexAutoLock envlock(m_env_mutex); | |
- JMutexAutoLock conlock(m_con_mutex); | |
- | |
u16 time = m_env->getTimeOfDay(); | |
float time_speed = g_settings->getFloat("time_speed"); | |
- | |
- for(std::map<u16, RemoteClient*>::iterator | |
- i = m_clients.begin(); | |
- i != m_clients.end(); ++i) | |
- { | |
- RemoteClient *client = i->second; | |
- SendTimeOfDay(client->peer_id, time, time_speed); | |
- } | |
+ SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed); | |
} | |
} | |
@@ -1139,7 +1102,7 @@ void Server::AsyncRunStep(bool initial_step) | |
*/ | |
{ | |
JMutexAutoLock lock(m_env_mutex); | |
- JMutexAutoLock lock2(m_con_mutex); | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
ScopeProfiler sp(g_profiler, "Server: handle players"); | |
@@ -1217,7 +1180,7 @@ void Server::AsyncRunStep(bool initial_step) | |
Set the modified blocks unsent for all the clients | |
*/ | |
- JMutexAutoLock lock2(m_con_mutex); | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
for(std::map<u16, RemoteClient*>::iterator | |
i = m_clients.begin(); | |
@@ -1241,7 +1204,7 @@ void Server::AsyncRunStep(bool initial_step) | |
{ | |
counter = 0.0; | |
- JMutexAutoLock lock2(m_con_mutex); | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
m_clients_names.clear(); | |
if(m_clients.size() != 0) | |
infostream<<"Players:"<<std::endl; | |
@@ -1285,7 +1248,7 @@ void Server::AsyncRunStep(bool initial_step) | |
{ | |
//infostream<<"Server: Checking added and deleted active objects"<<std::endl; | |
JMutexAutoLock envlock(m_env_mutex); | |
- JMutexAutoLock conlock(m_con_mutex); | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs"); | |
@@ -1440,7 +1403,7 @@ void Server::AsyncRunStep(bool initial_step) | |
*/ | |
{ | |
JMutexAutoLock envlock(m_env_mutex); | |
- JMutexAutoLock conlock(m_con_mutex); | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
ScopeProfiler sp(g_profiler, "Server: sending object messages"); | |
@@ -1556,9 +1519,8 @@ void Server::AsyncRunStep(bool initial_step) | |
Send queued-for-sending map edit events. | |
*/ | |
{ | |
- // We will be accessing the environment and the connection | |
+ // We will be accessing the environment | |
JMutexAutoLock lock(m_env_mutex); | |
- JMutexAutoLock conlock(m_con_mutex); | |
// Don't send too many at a time | |
//u32 count = 0; | |
@@ -1727,7 +1689,7 @@ void Server::Receive() | |
u32 datasize; | |
try{ | |
{ | |
- JMutexAutoLock conlock(m_con_mutex); | |
+ JMutexAutoLock conlock(m_clients_mutex); | |
datasize = m_con.Receive(peer_id, data); | |
} | |
@@ -1765,7 +1727,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |
DSTACK(__FUNCTION_NAME); | |
// Environment is locked first. | |
JMutexAutoLock envlock(m_env_mutex); | |
- JMutexAutoLock conlock(m_con_mutex); | |
ScopeProfiler sp(g_profiler, "Server::ProcessData"); | |
@@ -1794,8 +1755,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |
return; | |
} | |
- u8 peer_ser_ver = getClient(peer_id)->serialization_version; | |
- | |
try | |
{ | |
@@ -1815,7 +1774,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |
return; | |
// If net_proto_version is set, this client has already been handled | |
- if(getClient(peer_id)->net_proto_version != 0){ | |
+ if(getClient(peer_id,true)->net_proto_version != 0){ | |
verbosestream<<"Server: Ignoring multiple TOSERVER_INITs from " | |
<<addr_s<<" (peer_id="<<peer_id<<")"<<std::endl; | |
return; | |
@@ -1826,11 +1785,15 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |
// 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 ("<<addr_s | |
- <<") to connect in simple singleplayer mode"<<std::endl; | |
- DenyAccess(peer_id, L"Running in simple singleplayer mode."); | |
- return; | |
+ { | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
+ | |
+ if(m_simple_singleplayer_mode && m_clients.size() > 1){ | |
+ infostream<<"Server: Not allowing another client ("<<addr_s | |
+ <<") to connect in simple singleplayer mode"<<std::endl; | |
+ DenyAccess(peer_id, L"Running in simple singleplayer mode."); | |
+ return; | |
+ } | |
} | |
// First byte after command is maximum supported | |
@@ -1844,7 +1807,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |
deployed = SER_FMT_VER_INVALID; | |
//peer->serialization_version = deployed; | |
- getClient(peer_id)->pending_serialization_version = deployed; | |
+ getClient(peer_id,true)->pending_serialization_version = deployed; | |
if(deployed == SER_FMT_VER_INVALID) | |
{ | |
@@ -1893,7 +1856,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |
<<min_net_proto_version<<", max: "<<max_net_proto_version | |
<<", chosen: "<<net_proto_version<<std::endl; | |
- getClient(peer_id)->net_proto_version = net_proto_version; | |
+ getClient(peer_id,true)->net_proto_version = net_proto_version; | |
if(net_proto_version < SERVER_PROTOCOL_VERSION_MIN || | |
net_proto_version > SERVER_PROTOCOL_VERSION_MAX) | |
@@ -2012,20 +1975,23 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |
return; | |
} | |
- // Enforce user limit. | |
- // Don't enforce for users that have some admin right | |
- if(m_clients.size() >= g_settings->getU16("max_users") && | |
- !checkPriv(playername, "server") && | |
- !checkPriv(playername, "ban") && | |
- !checkPriv(playername, "privs") && | |
- !checkPriv(playername, "password") && | |
- playername != g_settings->get("name")) | |
{ | |
- actionstream<<"Server: "<<playername<<" tried to join, but there" | |
- <<" are already max_users=" | |
- <<g_settings->getU16("max_users")<<" players."<<std::endl; | |
- DenyAccess(peer_id, L"Too many users."); | |
- return; | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
+ // Enforce user limit. | |
+ // Don't enforce for users that have some admin right | |
+ if(m_clients.size() >= g_settings->getU16("max_users") && | |
+ !checkPriv(playername, "server") && | |
+ !checkPriv(playername, "ban") && | |
+ !checkPriv(playername, "privs") && | |
+ !checkPriv(playername, "password") && | |
+ playername != g_settings->get("name")) | |
+ { | |
+ actionstream<<"Server: "<<playername<<" tried to join, but there" | |
+ <<" are already max_users=" | |
+ <<g_settings->getU16("max_users")<<" players."<<std::endl; | |
+ DenyAccess(peer_id, L"Too many users."); | |
+ return; | |
+ } | |
} | |
std::string checkpwd; // Password hash to check against | |
@@ -2198,7 +2164,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |
message += L"*** "; | |
message += name; | |
message += L" joined the game."; | |
- BroadcastChatMessage(message); | |
+ SendChatMessage(PEER_ID_INEXISTENT,message); | |
} | |
} | |
@@ -2213,6 +2179,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |
Print out action | |
*/ | |
{ | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
std::ostringstream os(std::ios_base::binary); | |
for(std::map<u16, RemoteClient*>::iterator | |
i = m_clients.begin(); | |
@@ -2237,6 +2204,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |
return; | |
} | |
+ u8 peer_ser_ver = getClient(peer_id)->serialization_version; | |
+ | |
if(peer_ser_ver == SER_FMT_VER_INVALID) | |
{ | |
infostream<<"Server::ProcessData(): Cancelling: Peer" | |
@@ -2609,24 +2578,27 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) | |
/* | |
Send the message to clients | |
*/ | |
- for(std::map<u16, RemoteClient*>::iterator | |
- i = m_clients.begin(); | |
- i != m_clients.end(); ++i) | |
{ | |
- // Get client and check that it is valid | |
- RemoteClient *client = i->second; | |
- assert(client->peer_id == i->first); | |
- if(client->serialization_version == SER_FMT_VER_INVALID) | |
- continue; | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
+ for(std::map<u16, RemoteClient*>::iterator | |
+ i = m_clients.begin(); | |
+ i != m_clients.end(); ++i) | |
+ { | |
+ // Get client and check that it is valid | |
+ RemoteClient *client = i->second; | |
+ assert(client->peer_id == i->first); | |
+ if(client->serialization_version == SER_FMT_VER_INVALID) | |
+ continue; | |
- // 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; | |
+ // 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); | |
+ SendChatMessage(client->peer_id, line); | |
+ } | |
} | |
} | |
} | |
@@ -3308,7 +3280,7 @@ void Server::setInventoryModified(const InventoryLocation &loc) | |
break; | |
case InventoryLocation::DETACHED: | |
{ | |
- sendDetachedInventoryToAll(loc.name); | |
+ sendDetachedInventory(loc.name,PEER_ID_INEXISTENT); | |
} | |
break; | |
default: | |
@@ -3545,8 +3517,16 @@ void Server::SendChatMessage(u16 peer_id, const std::wstring &message) | |
// Make data buffer | |
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); | |
+ | |
+ if (peer_id != PEER_ID_INEXISTENT) | |
+ { | |
+ // Send as reliable | |
+ m_con.Send(peer_id, 0, data, true); | |
+ } | |
+ else | |
+ { | |
+ SendToAllInitializedClients(0,data,true); | |
+ } | |
} | |
void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec, | |
@@ -3590,27 +3570,15 @@ void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f accelerat | |
// Make data buffer | |
std::string s = os.str(); | |
SharedBuffer<u8> data((u8*)s.c_str(), s.size()); | |
+ | |
+ if (peer_id != PEER_ID_INEXISTENT) | |
+ { | |
// Send as reliable | |
m_con.Send(peer_id, 0, data, true); | |
-} | |
- | |
-// Spawns a particle on all peers | |
-void Server::SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration, | |
- float expirationtime, float size, bool collisiondetection, | |
- std::string texture) | |
-{ | |
- for(std::map<u16, RemoteClient*>::iterator | |
- i = m_clients.begin(); | |
- i != m_clients.end(); i++) | |
+ } | |
+ else | |
{ | |
- // Get client and check that it is valid | |
- RemoteClient *client = i->second; | |
- assert(client->peer_id == i->first); | |
- if(client->serialization_version == SER_FMT_VER_INVALID) | |
- continue; | |
- | |
- SendSpawnParticle(client->peer_id, pos, velocity, acceleration, | |
- expirationtime, size, collisiondetection, texture); | |
+ SendToAllInitializedClients(0,data,true); | |
} | |
} | |
@@ -3643,28 +3611,14 @@ void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3 | |
// Make data buffer | |
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); | |
-} | |
-// Adds a ParticleSpawner on all peers | |
-void Server::SendAddParticleSpawnerAll(u16 amount, float spawntime, v3f minpos, v3f maxpos, | |
- v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime, | |
- float minsize, float maxsize, bool collisiondetection, std::string texture, u32 id) | |
-{ | |
- for(std::map<u16, RemoteClient*>::iterator | |
- i = m_clients.begin(); | |
- i != m_clients.end(); i++) | |
+ if (peer_id != PEER_ID_INEXISTENT) | |
{ | |
- // Get client and check that it is valid | |
- RemoteClient *client = i->second; | |
- assert(client->peer_id == i->first); | |
- if(client->serialization_version == SER_FMT_VER_INVALID) | |
- continue; | |
- | |
- SendAddParticleSpawner(client->peer_id, amount, spawntime, | |
- minpos, maxpos, minvel, maxvel, minacc, maxacc, | |
- minexptime, maxexptime, minsize, maxsize, collisiondetection, texture, id); | |
+ // Send as reliable | |
+ m_con.Send(peer_id, 0, data, true); | |
+ } | |
+ else { | |
+ SendToAllInitializedClients(0,data,true); | |
} | |
} | |
@@ -3680,24 +3634,15 @@ void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id) | |
// Make data buffer | |
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); | |
-} | |
- | |
-void Server::SendDeleteParticleSpawnerAll(u32 id) | |
-{ | |
- for(std::map<u16, RemoteClient*>::iterator | |
- i = m_clients.begin(); | |
- i != m_clients.end(); i++) | |
- { | |
- // Get client and check that it is valid | |
- RemoteClient *client = i->second; | |
- assert(client->peer_id == i->first); | |
- if(client->serialization_version == SER_FMT_VER_INVALID) | |
- continue; | |
- SendDeleteParticleSpawner(client->peer_id, id); | |
+ if (peer_id != PEER_ID_INEXISTENT) { | |
+ // Send as reliable | |
+ m_con.Send(peer_id, 0, data, true); | |
} | |
+ else { | |
+ SendToAllInitializedClients(0,data,true); | |
+ } | |
+ | |
} | |
void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form) | |
@@ -3807,19 +3752,21 @@ void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value) | |
m_con.Send(peer_id, 0, data, true); | |
} | |
-void Server::BroadcastChatMessage(const std::wstring &message) | |
+void Server::SendToAllInitializedClients(u16 channelnum, | |
+ SharedBuffer<u8> data, | |
+ bool reliable) | |
{ | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
for(std::map<u16, RemoteClient*>::iterator | |
i = m_clients.begin(); | |
i != m_clients.end(); ++i) | |
{ | |
- // Get client and check that it is valid | |
RemoteClient *client = i->second; | |
- assert(client->peer_id == i->first); | |
- if(client->serialization_version == SER_FMT_VER_INVALID) | |
- continue; | |
- SendChatMessage(client->peer_id, message); | |
+ if (client->net_proto_version != 0) | |
+ { | |
+ m_con.Send(client->peer_id, channelnum, data, reliable); | |
+ } | |
} | |
} | |
@@ -3833,8 +3780,13 @@ void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed) | |
writeU16(&data[2], time); | |
writeF1000(&data[4], time_speed); | |
- // Send as reliable | |
- m_con.Send(peer_id, 0, data, true); | |
+ if (peer_id == PEER_ID_INEXISTENT) { | |
+ SendToAllInitializedClients(0,data,true); | |
+ } | |
+ else { | |
+ // Send as reliable | |
+ m_con.Send(peer_id, 0, data, true); | |
+ } | |
} | |
void Server::SendPlayerHP(u16 peer_id) | |
@@ -3942,6 +3894,8 @@ s32 Server::playSound(const SimpleSoundSpec &spec, | |
// If position is not found while it should be, cancel sound | |
if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL)) | |
return -1; | |
+ | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
// Filter destination clients | |
std::set<RemoteClient*> dst_clients; | |
if(params.to_player != "") | |
@@ -4048,6 +4002,7 @@ void Server::sendRemoveNode(v3s16 p, u16 ignore_id, | |
writeS16(&reply[4], p.Y); | |
writeS16(&reply[6], p.Z); | |
+ JMutexAutoLock clientslock(m_clients_mutex); | |
for(std::map<u16, RemoteClient*>::iterator | |
i = m_clients.begin(); | |
i != m_clients.end(); ++i) | |
@@ -4214,7 +4169,7 @@ void Server::SendBlocks(float dtime) | |
DSTACK(__FUNCTION_NAME); | |
JMutexAutoLock envlock(m_env_mutex); | |
- JMutexAutoLock conlock(m_con_mutex); | |
+ JMutexAutoLock conlock(m_clients_mutex); | |
ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients"); | |
@@ -4588,19 +4543,15 @@ void Server::sendDetachedInventory(const std::string &name, u16 peer_id) | |
// Make data buffer | |
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); | |
-} | |
- | |
-void Server::sendDetachedInventoryToAll(const std::string &name) | |
-{ | |
- DSTACK(__FUNCTION_NAME); | |
- for(std::map<u16, RemoteClient*>::iterator | |
- i = m_clients.begin(); | |
- i != m_clients.end(); ++i){ | |
- RemoteClient *client = i->second; | |
- sendDetachedInventory(name, client->peer_id); | |
+ if (peer_id != PEER_ID_INEXISTENT) | |
+ { | |
+ // Send as reliable | |
+ m_con.Send(peer_id, 0, data, true); | |
+ } | |
+ else | |
+ { | |
+ SendToAllInitializedClients(0,data,true); | |
} | |
} | |
@@ -4685,112 +4636,115 @@ void Server::DenyAccess(u16 peer_id, const std::wstring &reason) | |
void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason) | |
{ | |
DSTACK(__FUNCTION_NAME); | |
+ std::wstring message; | |
+ { | |
+ JMutexAutoLock conlock(m_clients_mutex); | |
- // Error check | |
- std::map<u16, RemoteClient*>::iterator n; | |
- n = m_clients.find(peer_id); | |
- // The client may not exist; clients are immediately removed if their | |
- // access is denied, and this event occurs later then. | |
- if(n == m_clients.end()) | |
- return; | |
+ // Error check | |
+ std::map<u16, RemoteClient*>::iterator n; | |
+ n = m_clients.find(peer_id); | |
+ // The client may not exist; clients are immediately removed if their | |
+ // access is denied, and this event occurs later then. | |
+ if(n == m_clients.end()) | |
+ return; | |
- /* | |
- Mark objects to be not known by the client | |
- */ | |
- RemoteClient *client = n->second; | |
- // Handle objects | |
- for(std::set<u16>::iterator | |
- i = client->m_known_objects.begin(); | |
- i != client->m_known_objects.end(); ++i) | |
- { | |
- // Get object | |
- u16 id = *i; | |
- ServerActiveObject* obj = m_env->getActiveObject(id); | |
+ /* | |
+ Mark objects to be not known by the client | |
+ */ | |
+ RemoteClient *client = n->second; | |
+ // Handle objects | |
+ for(std::set<u16>::iterator | |
+ i = client->m_known_objects.begin(); | |
+ i != client->m_known_objects.end(); ++i) | |
+ { | |
+ // Get object | |
+ u16 id = *i; | |
+ ServerActiveObject* obj = m_env->getActiveObject(id); | |
- if(obj && obj->m_known_by_count > 0) | |
- obj->m_known_by_count--; | |
- } | |
+ if(obj && obj->m_known_by_count > 0) | |
+ obj->m_known_by_count--; | |
+ } | |
- /* | |
- Clear references to playing sounds | |
- */ | |
- for(std::map<s32, ServerPlayingSound>::iterator | |
- i = m_playing_sounds.begin(); | |
- i != m_playing_sounds.end();) | |
- { | |
- ServerPlayingSound &psound = i->second; | |
- psound.clients.erase(peer_id); | |
- if(psound.clients.size() == 0) | |
- m_playing_sounds.erase(i++); | |
- else | |
- i++; | |
- } | |
+ /* | |
+ Clear references to playing sounds | |
+ */ | |
+ for(std::map<s32, ServerPlayingSound>::iterator | |
+ i = m_playing_sounds.begin(); | |
+ i != m_playing_sounds.end();) | |
+ { | |
+ ServerPlayingSound &psound = i->second; | |
+ psound.clients.erase(peer_id); | |
+ if(psound.clients.size() == 0) | |
+ m_playing_sounds.erase(i++); | |
+ else | |
+ i++; | |
+ } | |
- Player *player = m_env->getPlayer(peer_id); | |
+ Player *player = m_env->getPlayer(peer_id); | |
- // Collect information about leaving in chat | |
- std::wstring message; | |
- { | |
- if(player != NULL && reason != CDR_DENY) | |
+ // Collect information about leaving in chat | |
{ | |
- std::wstring name = narrow_to_wide(player->getName()); | |
- message += L"*** "; | |
- message += name; | |
- message += L" left the game."; | |
- if(reason == CDR_TIMEOUT) | |
- message += L" (timed out)"; | |
+ if(player != NULL && reason != CDR_DENY) | |
+ { | |
+ std::wstring name = narrow_to_wide(player->getName()); | |
+ message += L"*** "; | |
+ message += name; | |
+ message += L" left the game."; | |
+ if(reason == CDR_TIMEOUT) | |
+ message += L" (timed out)"; | |
+ } | |
} | |
- } | |
- /* Run scripts and remove from environment */ | |
- { | |
- if(player != NULL) | |
+ /* Run scripts and remove from environment */ | |
{ | |
- PlayerSAO *playersao = player->getPlayerSAO(); | |
- assert(playersao); | |
+ if(player != NULL) | |
+ { | |
+ PlayerSAO *playersao = player->getPlayerSAO(); | |
+ assert(playersao); | |
- m_script->on_leaveplayer(playersao); | |
+ m_script->on_leaveplayer(playersao); | |
- playersao->disconnected(); | |
+ playersao->disconnected(); | |
+ } | |
} | |
- } | |
- /* | |
- Print out action | |
- */ | |
- { | |
- if(player != NULL && reason != CDR_DENY) | |
+ /* | |
+ Print out action | |
+ */ | |
{ | |
- std::ostringstream os(std::ios_base::binary); | |
- for(std::map<u16, RemoteClient*>::iterator | |
- i = m_clients.begin(); | |
- i != m_clients.end(); ++i) | |
+ if(player != NULL && reason != CDR_DENY) | |
{ | |
- RemoteClient *client = i->second; | |
- assert(client->peer_id == i->first); | |
- if(client->serialization_version == SER_FMT_VER_INVALID) | |
- continue; | |
- // Get player | |
- Player *player = m_env->getPlayer(client->peer_id); | |
- if(!player) | |
- continue; | |
- // Get name of player | |
- os<<player->getName()<<" "; | |
- } | |
+ std::ostringstream os(std::ios_base::binary); | |
+ for(std::map<u16, RemoteClient*>::iterator | |
+ i = m_clients.begin(); | |
+ i != m_clients.end(); ++i) | |
+ { | |
+ RemoteClient *client = i->second; | |
+ assert(client->peer_id == i->first); | |
+ if(client->serialization_version == SER_FMT_VER_INVALID) | |
+ continue; | |
+ // Get player | |
+ Player *player = m_env->getPlayer(client->peer_id); | |
+ if(!player) | |
+ continue; | |
+ // Get name of player | |
+ os<<player->getName()<<" "; | |
+ } | |
- actionstream<<player->getName()<<" " | |
- <<(reason==CDR_TIMEOUT?"times out.":"leaves game.") | |
- <<" List of players: "<<os.str()<<std::endl; | |
+ actionstream<<player->getName()<<" " | |
+ <<(reason==CDR_TIMEOUT?"times out.":"leaves game.") | |
+ <<" List of players: "<<os.str()<<std::endl; | |
+ } | |
} | |
- } | |
- // Delete client | |
- delete m_clients[peer_id]; | |
- m_clients.erase(peer_id); | |
+ // Delete client | |
+ delete m_clients[peer_id]; | |
+ m_clients.erase(peer_id); | |
+ } | |
// Send leave chat message to all remaining clients | |
if(message.length() != 0) | |
- BroadcastChatMessage(message); | |
+ SendChatMessage(PEER_ID_INEXISTENT,message); | |
} | |
void Server::UpdateCrafting(u16 peer_id) | |
@@ -4814,14 +4768,15 @@ void Server::UpdateCrafting(u16 peer_id) | |
plist->changeItem(0, preview); | |
} | |
-RemoteClient* Server::getClient(u16 peer_id) | |
+RemoteClient* Server::getClient(u16 peer_id,bool uninitialized) | |
{ | |
- RemoteClient *client = getClientNoEx(peer_id); | |
+ RemoteClient *client = getClientNoEx(peer_id,uninitialized); | |
if(!client) | |
throw ClientNotFoundException("Client not found"); | |
+ | |
return client; | |
} | |
-RemoteClient* Server::getClientNoEx(u16 peer_id) | |
+RemoteClient* Server::getClientNoEx(u16 peer_id,bool uninitialized) | |
{ | |
std::map<u16, RemoteClient*>::iterator n; | |
n = m_clients.find(peer_id); | |
@@ -4829,7 +4784,11 @@ RemoteClient* Server::getClientNoEx(u16 peer_id) | |
// access is denied, and this event occurs later then. | |
if(n == m_clients.end()) | |
return NULL; | |
- return n->second; | |
+ | |
+ if ((uninitialized) || (n->second->net_proto_version != 0)) | |
+ return n->second; | |
+ else | |
+ return NULL; | |
} | |
std::string Server::getPlayerName(u16 peer_id) | |
@@ -5045,7 +5004,7 @@ void Server::hudSetHotbarSelectedImage(Player *player, std::string name) { | |
void Server::notifyPlayers(const std::wstring msg) | |
{ | |
- BroadcastChatMessage(msg); | |
+ SendChatMessage(PEER_ID_INEXISTENT,msg); | |
} | |
void Server::spawnParticle(const char *playername, v3f pos, | |
@@ -5064,7 +5023,7 @@ void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration, | |
float expirationtime, float size, | |
bool collisiondetection, std::string texture) | |
{ | |
- SendSpawnParticleAll(pos, velocity, acceleration, | |
+ SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration, | |
expirationtime, size, collisiondetection, texture); | |
} | |
@@ -5123,7 +5082,7 @@ u32 Server::addParticleSpawnerAll(u16 amount, float spawntime, | |
} | |
} | |
- SendAddParticleSpawnerAll(amount, spawntime, | |
+ SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime, | |
minpos, maxpos, minvel, maxvel, minacc, maxacc, | |
minexptime, maxexptime, minsize, maxsize, | |
collisiondetection, texture, id); | |
@@ -5150,7 +5109,7 @@ void Server::deleteParticleSpawnerAll(u32 id) | |
std::remove(m_particlespawner_ids.begin(), | |
m_particlespawner_ids.end(), id), | |
m_particlespawner_ids.end()); | |
- SendDeleteParticleSpawnerAll(id); | |
+ SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id); | |
} | |
Inventory* Server::createDetachedInventory(const std::string &name) | |
@@ -5164,7 +5123,8 @@ Inventory* Server::createDetachedInventory(const std::string &name) | |
Inventory *inv = new Inventory(m_itemdef); | |
assert(inv); | |
m_detached_inventories[name] = inv; | |
- sendDetachedInventoryToAll(name); | |
+ //TODO find a better way to do this | |
+ sendDetachedInventory(name,PEER_ID_INEXISTENT); | |
return inv; | |
} | |
@@ -5441,10 +5401,10 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id) | |
void Server::handlePeerChange(PeerChange &c) | |
{ | |
JMutexAutoLock envlock(m_env_mutex); | |
- JMutexAutoLock conlock(m_con_mutex); | |
if(c.type == PEER_ADDED) | |
{ | |
+ JMutexAutoLock conlock(m_clients_mutex); | |
/* | |
Add | |
*/ | |
diff --git a/src/server.h b/src/server.h | |
index aeae216..770ac96 100644 | |
--- a/src/server.h | |
+++ b/src/server.h | |
@@ -507,7 +507,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, | |
// Envlock and conlock should be locked when calling these | |
void SendInventory(u16 peer_id); | |
void SendChatMessage(u16 peer_id, const std::wstring &message); | |
- void BroadcastChatMessage(const std::wstring &message); | |
+ void SendToAllInitializedClients(u16 channelnum,SharedBuffer<u8> data,bool reliable); | |
void SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed); | |
void SendPlayerHP(u16 peer_id); | |
void SendPlayerBreath(u16 peer_id); | |
@@ -546,10 +546,9 @@ class Server : public con::PeerHandler, public MapEventReceiver, | |
const std::list<std::string> &tosend); | |
void sendDetachedInventory(const std::string &name, u16 peer_id); | |
- void sendDetachedInventoryToAll(const std::string &name); | |
void sendDetachedInventories(u16 peer_id); | |
- // Adds a ParticleSpawner on peer with peer_id | |
+ // Adds a ParticleSpawner on peer with peer_id (PEER_ID_INEXISTENT == all) | |
void SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, | |
v3f minpos, v3f maxpos, | |
v3f minvel, v3f maxvel, | |
@@ -558,32 +557,15 @@ class Server : public con::PeerHandler, public MapEventReceiver, | |
float minsize, float maxsize, | |
bool collisiondetection, std::string texture, u32 id); | |
- // Adds a ParticleSpawner on all peers | |
- void SendAddParticleSpawnerAll(u16 amount, float spawntime, | |
- v3f minpos, v3f maxpos, | |
- v3f minvel, v3f maxvel, | |
- v3f minacc, v3f maxacc, | |
- float minexptime, float maxexptime, | |
- float minsize, float maxsize, | |
- bool collisiondetection, std::string texture, u32 id); | |
- | |
- // Deletes ParticleSpawner on a single client | |
+ // Deletes ParticleSpawner on peer with peer_id (PEER_ID_INEXISTENT == all) | |
void SendDeleteParticleSpawner(u16 peer_id, u32 id); | |
- // Deletes ParticleSpawner on all clients | |
- void SendDeleteParticleSpawnerAll(u32 id); | |
- | |
- // Spawns particle on single client | |
+ // Spawns particle on peer with peer_id (PEER_ID_INEXISTENT == all) | |
void SendSpawnParticle(u16 peer_id, | |
v3f pos, v3f velocity, v3f acceleration, | |
float expirationtime, float size, | |
bool collisiondetection, std::string texture); | |
- // Spawns particle on all clients | |
- void SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration, | |
- float expirationtime, float size, | |
- bool collisiondetection, std::string texture); | |
- | |
/* | |
Something random | |
*/ | |
@@ -602,8 +584,8 @@ class Server : public con::PeerHandler, public MapEventReceiver, | |
void UpdateCrafting(u16 peer_id); | |
// When called, connection mutex should be locked | |
- RemoteClient* getClient(u16 peer_id); | |
- RemoteClient* getClientNoEx(u16 peer_id); | |
+ RemoteClient* getClient(u16 peer_id,bool uninitialized=false); | |
+ RemoteClient* getClientNoEx(u16 peer_id,bool uninitialized=false); | |
// When called, environment mutex should be locked | |
std::string getPlayerName(u16 peer_id); | |
@@ -657,7 +639,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, | |
// Connection | |
con::Connection m_con; | |
- JMutex m_con_mutex; | |
+ JMutex m_clients_mutex; | |
// Connected clients (behind the con mutex) | |
std::map<u16, RemoteClient*> m_clients; | |
std::vector<std::string> m_clients_names; //for announcing masterserver |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment