Skip to content

Instantly share code, notes, and snippets.

@sapier
Created January 12, 2014 11:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sapier/8383662 to your computer and use it in GitHub Desktop.
Save sapier/8383662 to your computer and use it in GitHub Desktop.
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