Fix how address is logged when a wrong password is supplied
[oweals/minetest.git] / src / server.cpp
index cb7e35ecd5e84b4a3d6fd6baa52a56e5cda6860a..b0f69f1c384fc472badeac8fe6ae2abf0400f6bd 100644 (file)
@@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "ban.h"
 #include "environment.h"
 #include "map.h"
 #include "ban.h"
 #include "environment.h"
 #include "map.h"
-#include "jthread/jmutexautolock.h"
+#include "threading/mutex_auto_lock.h"
 #include "constants.h"
 #include "voxel.h"
 #include "config.h"
 #include "constants.h"
 #include "voxel.h"
 #include "config.h"
@@ -71,61 +71,44 @@ public:
        {}
 };
 
        {}
 };
 
-class ServerThread : public JThread
+class ServerThread : public Thread
 {
 {
-       Server *m_server;
-
 public:
 
        ServerThread(Server *server):
 public:
 
        ServerThread(Server *server):
-               JThread(),
+               Thread("Server"),
                m_server(server)
                m_server(server)
-       {
-       }
+       {}
+
+       void *run();
 
 
-       void * Thread();
+private:
+       Server *m_server;
 };
 
 };
 
-void * ServerThread::Thread()
+void *ServerThread::run()
 {
 {
-       log_register_thread("ServerThread");
-
        DSTACK(__FUNCTION_NAME);
        BEGIN_DEBUG_EXCEPTION_HANDLER
 
        m_server->AsyncRunStep(true);
 
        DSTACK(__FUNCTION_NAME);
        BEGIN_DEBUG_EXCEPTION_HANDLER
 
        m_server->AsyncRunStep(true);
 
-       ThreadStarted();
-
-       porting::setThreadName("ServerThread");
-
-       while(!StopRequested())
-       {
-               try{
+       while (!stopRequested()) {
+               try {
                        //TimeTaker timer("AsyncRunStep() + Receive()");
 
                        m_server->AsyncRunStep();
 
                        m_server->Receive();
 
                        //TimeTaker timer("AsyncRunStep() + Receive()");
 
                        m_server->AsyncRunStep();
 
                        m_server->Receive();
 
-               }
-               catch(con::NoIncomingDataException &e)
-               {
-               }
-               catch(con::PeerNotFoundException &e)
-               {
+               } catch (con::NoIncomingDataException &e) {
+               } catch (con::PeerNotFoundException &e) {
                        infostream<<"Server: PeerNotFoundException"<<std::endl;
                        infostream<<"Server: PeerNotFoundException"<<std::endl;
-               }
-               catch(ClientNotFoundException &e)
-               {
-               }
-               catch(con::ConnectionBindFailed &e)
-               {
-                       m_server->setAsyncFatalError(e.what());
-               }
-               catch(LuaError &e)
-               {
+               } catch (ClientNotFoundException &e) {
+               } catch (con::ConnectionBindFailed &e) {
                        m_server->setAsyncFatalError(e.what());
                        m_server->setAsyncFatalError(e.what());
+               } catch (LuaError &e) {
+                       m_server->setAsyncFatalError("Lua: " + std::string(e.what()));
                }
        }
 
                }
        }
 
@@ -278,8 +261,8 @@ Server::Server(
                errorstream << std::endl;
        }
 
                errorstream << std::endl;
        }
 
-       // Lock environment
-       JMutexAutoLock envlock(m_env_mutex);
+       //lock environment
+       MutexAutoLock envlock(m_env_mutex);
 
        // Load mapgen params from Settings
        m_emerge->loadMapgenParams();
 
        // Load mapgen params from Settings
        m_emerge->loadMapgenParams();
@@ -302,14 +285,14 @@ Server::Server(
        // Print mods
        infostream << "Server: Loading mods: ";
        for(std::vector<ModSpec>::iterator i = m_mods.begin();
        // Print mods
        infostream << "Server: Loading mods: ";
        for(std::vector<ModSpec>::iterator i = m_mods.begin();
-                       i != m_mods.end(); i++) {
+                       i != m_mods.end(); ++i) {
                const ModSpec &mod = *i;
                infostream << mod.name << " ";
        }
        infostream << std::endl;
        // Load and run "mod" scripts
        for (std::vector<ModSpec>::iterator i = m_mods.begin();
                const ModSpec &mod = *i;
                infostream << mod.name << " ";
        }
        infostream << std::endl;
        // Load and run "mod" scripts
        for (std::vector<ModSpec>::iterator i = m_mods.begin();
-                       i != m_mods.end(); i++) {
+                       i != m_mods.end(); ++i) {
                const ModSpec &mod = *i;
                if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
                        std::ostringstream err;
                const ModSpec &mod = *i;
                if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
                        std::ostringstream err;
@@ -390,7 +373,7 @@ Server::~Server()
        SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down");
 
        {
        SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down");
 
        {
-               JMutexAutoLock envlock(m_env_mutex);
+               MutexAutoLock envlock(m_env_mutex);
 
                // Execute script shutdown hooks
                m_script->on_shutdown();
 
                // Execute script shutdown hooks
                m_script->on_shutdown();
@@ -443,7 +426,7 @@ Server::~Server()
        // Delete detached inventories
        for (std::map<std::string, Inventory*>::iterator
                        i = m_detached_inventories.begin();
        // Delete detached inventories
        for (std::map<std::string, Inventory*>::iterator
                        i = m_detached_inventories.begin();
-                       i != m_detached_inventories.end(); i++) {
+                       i != m_detached_inventories.end(); ++i) {
                delete i->second;
        }
 }
                delete i->second;
        }
 }
@@ -458,14 +441,14 @@ void Server::start(Address bind_addr)
                        << bind_addr.serializeString() <<"..."<<std::endl;
 
        // Stop thread if already running
                        << bind_addr.serializeString() <<"..."<<std::endl;
 
        // Stop thread if already running
-       m_thread->Stop();
+       m_thread->stop();
 
        // Initialize connection
        m_con.SetTimeoutMs(30);
        m_con.Serve(bind_addr);
 
        // Start thread
 
        // Initialize connection
        m_con.SetTimeoutMs(30);
        m_con.Serve(bind_addr);
 
        // Start thread
-       m_thread->Start();
+       m_thread->start();
 
        // ASCII art for the win!
        actionstream
 
        // ASCII art for the win!
        actionstream
@@ -488,9 +471,9 @@ void Server::stop()
        infostream<<"Server: Stopping and waiting threads"<<std::endl;
 
        // Stop threads (set run=false first so both start stopping)
        infostream<<"Server: Stopping and waiting threads"<<std::endl;
 
        // Stop threads (set run=false first so both start stopping)
-       m_thread->Stop();
+       m_thread->stop();
        //m_emergethread.setRun(false);
        //m_emergethread.setRun(false);
-       m_thread->Wait();
+       m_thread->wait();
        //m_emergethread.stop();
 
        infostream<<"Server: Threads stopped"<<std::endl;
        //m_emergethread.stop();
 
        infostream<<"Server: Threads stopped"<<std::endl;
@@ -503,7 +486,7 @@ void Server::step(float dtime)
        if(dtime > 2.0)
                dtime = 2.0;
        {
        if(dtime > 2.0)
                dtime = 2.0;
        {
-               JMutexAutoLock lock(m_step_dtime_mutex);
+               MutexAutoLock lock(m_step_dtime_mutex);
                m_step_dtime += dtime;
        }
        // Throw if fatal error occurred in thread
                m_step_dtime += dtime;
        }
        // Throw if fatal error occurred in thread
@@ -532,7 +515,7 @@ void Server::AsyncRunStep(bool initial_step)
 
        float dtime;
        {
 
        float dtime;
        {
-               JMutexAutoLock lock1(m_step_dtime_mutex);
+               MutexAutoLock lock1(m_step_dtime_mutex);
                dtime = m_step_dtime;
        }
 
                dtime = m_step_dtime;
        }
 
@@ -550,7 +533,7 @@ void Server::AsyncRunStep(bool initial_step)
        //infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
 
        {
        //infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
 
        {
-               JMutexAutoLock lock1(m_step_dtime_mutex);
+               MutexAutoLock lock1(m_step_dtime_mutex);
                m_step_dtime -= dtime;
        }
 
                m_step_dtime -= dtime;
        }
 
@@ -581,7 +564,7 @@ void Server::AsyncRunStep(bool initial_step)
        }
 
        {
        }
 
        {
-               JMutexAutoLock lock(m_env_mutex);
+               MutexAutoLock lock(m_env_mutex);
                // Figure out and report maximum lag to environment
                float max_lag = m_env->getMaxLagEstimate();
                max_lag *= 0.9998; // Decrease slowly (about half per 5 minutes)
                // Figure out and report maximum lag to environment
                float max_lag = m_env->getMaxLagEstimate();
                max_lag *= 0.9998; // Decrease slowly (about half per 5 minutes)
@@ -601,11 +584,12 @@ void Server::AsyncRunStep(bool initial_step)
        static const float map_timer_and_unload_dtime = 2.92;
        if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
        {
        static const float map_timer_and_unload_dtime = 2.92;
        if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
        {
-               JMutexAutoLock lock(m_env_mutex);
+               MutexAutoLock lock(m_env_mutex);
                // Run Map's timers and unload unused data
                ScopeProfiler sp(g_profiler, "Server: map timer and unload");
                m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
                // Run Map's timers and unload unused data
                ScopeProfiler sp(g_profiler, "Server: map timer and unload");
                m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
-                               g_settings->getFloat("server_unload_unused_data_timeout"));
+                       g_settings->getFloat("server_unload_unused_data_timeout"),
+                       U32_MAX);
        }
 
        /*
        }
 
        /*
@@ -618,7 +602,7 @@ void Server::AsyncRunStep(bool initial_step)
        {
                m_liquid_transform_timer -= m_liquid_transform_every;
 
        {
                m_liquid_transform_timer -= m_liquid_transform_every;
 
-               JMutexAutoLock lock(m_env_mutex);
+               MutexAutoLock lock(m_env_mutex);
 
                ScopeProfiler sp(g_profiler, "Server: liquid transform");
 
 
                ScopeProfiler sp(g_profiler, "Server: liquid transform");
 
@@ -679,9 +663,9 @@ void Server::AsyncRunStep(bool initial_step)
        */
        {
                //infostream<<"Server: Checking added and deleted active objects"<<std::endl;
        */
        {
                //infostream<<"Server: Checking added and deleted active objects"<<std::endl;
-               JMutexAutoLock envlock(m_env_mutex);
+               MutexAutoLock envlock(m_env_mutex);
 
 
-               m_clients.Lock();
+               m_clients.lock();
                std::map<u16, RemoteClient*> clients = m_clients.getClientList();
                ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
 
                std::map<u16, RemoteClient*> clients = m_clients.getClientList();
                ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
 
@@ -696,10 +680,9 @@ void Server::AsyncRunStep(bool initial_step)
                radius *= MAP_BLOCKSIZE;
                player_radius *= MAP_BLOCKSIZE;
 
                radius *= MAP_BLOCKSIZE;
                player_radius *= MAP_BLOCKSIZE;
 
-               for(std::map<u16, RemoteClient*>::iterator
+               for (std::map<u16, RemoteClient*>::iterator
                        i = clients.begin();
                        i = clients.begin();
-                       i != clients.end(); ++i)
-               {
+                       i != clients.end(); ++i) {
                        RemoteClient *client = i->second;
 
                        // If definitions and textures have not been sent, don't
                        RemoteClient *client = i->second;
 
                        // If definitions and textures have not been sent, don't
@@ -708,27 +691,23 @@ void Server::AsyncRunStep(bool initial_step)
                                continue;
 
                        Player *player = m_env->getPlayer(client->peer_id);
                                continue;
 
                        Player *player = m_env->getPlayer(client->peer_id);
-                       if(player==NULL)
-                       {
+                       if(player == NULL) {
                                // This can happen if the client timeouts somehow
                                /*infostream<<"WARNING: "<<__FUNCTION_NAME<<": Client "
                                                <<client->peer_id
                                                <<" has no associated player"<<std::endl;*/
                                continue;
                        }
                                // This can happen if the client timeouts somehow
                                /*infostream<<"WARNING: "<<__FUNCTION_NAME<<": Client "
                                                <<client->peer_id
                                                <<" has no associated player"<<std::endl;*/
                                continue;
                        }
-                       v3s16 pos = floatToInt(player->getPosition(), BS);
 
 
-                       std::set<u16> removed_objects;
-                       std::set<u16> added_objects;
-                       m_env->getRemovedActiveObjects(pos, radius, player_radius,
+                       std::queue<u16> removed_objects;
+                       std::queue<u16> added_objects;
+                       m_env->getRemovedActiveObjects(player, radius, player_radius,
                                        client->m_known_objects, removed_objects);
                                        client->m_known_objects, removed_objects);
-                       m_env->getAddedActiveObjects(pos, radius, player_radius,
+                       m_env->getAddedActiveObjects(player, radius, player_radius,
                                        client->m_known_objects, added_objects);
 
                        // Ignore if nothing happened
                                        client->m_known_objects, added_objects);
 
                        // Ignore if nothing happened
-                       if(removed_objects.empty() && added_objects.empty())
-                       {
-                               //infostream<<"active objects: none changed"<<std::endl;
+                       if (removed_objects.empty() && added_objects.empty()) {
                                continue;
                        }
 
                                continue;
                        }
 
@@ -739,12 +718,9 @@ void Server::AsyncRunStep(bool initial_step)
                        // Handle removed objects
                        writeU16((u8*)buf, removed_objects.size());
                        data_buffer.append(buf, 2);
                        // Handle removed objects
                        writeU16((u8*)buf, removed_objects.size());
                        data_buffer.append(buf, 2);
-                       for(std::set<u16>::iterator
-                                       i = removed_objects.begin();
-                                       i != removed_objects.end(); ++i)
-                       {
+                       while (!removed_objects.empty()) {
                                // Get object
                                // Get object
-                               u16 id = *i;
+                               u16 id = removed_objects.front();
                                ServerActiveObject* obj = m_env->getActiveObject(id);
 
                                // Add to data buffer for sending
                                ServerActiveObject* obj = m_env->getActiveObject(id);
 
                                // Add to data buffer for sending
@@ -756,17 +732,15 @@ void Server::AsyncRunStep(bool initial_step)
 
                                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--;
+                               removed_objects.pop();
                        }
 
                        // Handle added objects
                        writeU16((u8*)buf, added_objects.size());
                        data_buffer.append(buf, 2);
                        }
 
                        // Handle added objects
                        writeU16((u8*)buf, added_objects.size());
                        data_buffer.append(buf, 2);
-                       for(std::set<u16>::iterator
-                                       i = added_objects.begin();
-                                       i != added_objects.end(); ++i)
-                       {
+                       while (!added_objects.empty()) {
                                // Get object
                                // Get object
-                               u16 id = *i;
+                               u16 id = added_objects.front();
                                ServerActiveObject* obj = m_env->getActiveObject(id);
 
                                // Get object type
                                ServerActiveObject* obj = m_env->getActiveObject(id);
 
                                // Get object type
@@ -794,6 +768,8 @@ void Server::AsyncRunStep(bool initial_step)
 
                                if(obj)
                                        obj->m_known_by_count++;
 
                                if(obj)
                                        obj->m_known_by_count++;
+
+                               added_objects.pop();
                        }
 
                        u32 pktSize = SendActiveObjectRemoveAdd(client->peer_id, data_buffer);
                        }
 
                        u32 pktSize = SendActiveObjectRemoveAdd(client->peer_id, data_buffer);
@@ -802,14 +778,14 @@ void Server::AsyncRunStep(bool initial_step)
                                        << added_objects.size() << " added, "
                                        << "packet size is " << pktSize << std::endl;
                }
                                        << added_objects.size() << " added, "
                                        << "packet size is " << pktSize << std::endl;
                }
-               m_clients.Unlock();
+               m_clients.unlock();
        }
 
        /*
                Send object messages
        */
        {
        }
 
        /*
                Send object messages
        */
        {
-               JMutexAutoLock envlock(m_env_mutex);
+               MutexAutoLock envlock(m_env_mutex);
                ScopeProfiler sp(g_profiler, "Server: sending object messages");
 
                // Key = object id
                ScopeProfiler sp(g_profiler, "Server: sending object messages");
 
                // Key = object id
@@ -835,7 +811,7 @@ void Server::AsyncRunStep(bool initial_step)
                        message_list->push_back(aom);
                }
 
                        message_list->push_back(aom);
                }
 
-               m_clients.Lock();
+               m_clients.lock();
                std::map<u16, RemoteClient*> clients = m_clients.getClientList();
                // Route data to every client
                for (std::map<u16, RemoteClient*>::iterator
                std::map<u16, RemoteClient*> clients = m_clients.getClientList();
                // Route data to every client
                for (std::map<u16, RemoteClient*>::iterator
@@ -886,7 +862,7 @@ void Server::AsyncRunStep(bool initial_step)
                                SendActiveObjectMessages(client->peer_id, unreliable_data, false);
                        }
                }
                                SendActiveObjectMessages(client->peer_id, unreliable_data, false);
                        }
                }
-               m_clients.Unlock();
+               m_clients.unlock();
 
                // Clear buffered_messages
                for(std::map<u16, std::vector<ActiveObjectMessage>* >::iterator
 
                // Clear buffered_messages
                for(std::map<u16, std::vector<ActiveObjectMessage>* >::iterator
@@ -901,7 +877,7 @@ void Server::AsyncRunStep(bool initial_step)
        */
        {
                // We will be accessing the environment
        */
        {
                // We will be accessing the environment
-               JMutexAutoLock lock(m_env_mutex);
+               MutexAutoLock lock(m_env_mutex);
 
                // Don't send too many at a time
                //u32 count = 0;
 
                // Don't send too many at a time
                //u32 count = 0;
@@ -1022,7 +998,7 @@ void Server::AsyncRunStep(bool initial_step)
                if(counter >= g_settings->getFloat("server_map_save_interval"))
                {
                        counter = 0.0;
                if(counter >= g_settings->getFloat("server_map_save_interval"))
                {
                        counter = 0.0;
-                       JMutexAutoLock lock(m_env_mutex);
+                       MutexAutoLock lock(m_env_mutex);
 
                        ScopeProfiler sp(g_profiler, "Server: saving stuff");
 
 
                        ScopeProfiler sp(g_profiler, "Server: saving stuff");
 
@@ -1078,7 +1054,7 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
 {
        std::string playername = "";
        PlayerSAO *playersao = NULL;
 {
        std::string playername = "";
        PlayerSAO *playersao = NULL;
-       m_clients.Lock();
+       m_clients.lock();
        try {
                RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
                if (client != NULL) {
        try {
                RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
                if (client != NULL) {
@@ -1086,10 +1062,10 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
                        playersao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version);
                }
        } catch (std::exception &e) {
                        playersao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version);
                }
        } catch (std::exception &e) {
-               m_clients.Unlock();
+               m_clients.unlock();
                throw;
        }
                throw;
        }
-       m_clients.Unlock();
+       m_clients.unlock();
 
        RemotePlayer *player =
                static_cast<RemotePlayer*>(m_env->getPlayer(playername.c_str()));
 
        RemotePlayer *player =
                static_cast<RemotePlayer*>(m_env->getPlayer(playername.c_str()));
@@ -1165,7 +1141,7 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
                actionstream<<player->getName() <<" joins game. List of players: ";
 
                for (std::vector<std::string>::iterator i = names.begin();
                actionstream<<player->getName() <<" joins game. List of players: ";
 
                for (std::vector<std::string>::iterator i = names.begin();
-                               i != names.end(); i++) {
+                               i != names.end(); ++i) {
                        actionstream << *i << " ";
                }
 
                        actionstream << *i << " ";
                }
 
@@ -1184,7 +1160,7 @@ void Server::ProcessData(NetworkPacket *pkt)
 {
        DSTACK(__FUNCTION_NAME);
        // Environment is locked first.
 {
        DSTACK(__FUNCTION_NAME);
        // Environment is locked first.
-       JMutexAutoLock envlock(m_env_mutex);
+       MutexAutoLock envlock(m_env_mutex);
 
        ScopeProfiler sp(g_profiler, "Server::ProcessData");
        u32 peer_id = pkt->getPeerId();
 
        ScopeProfiler sp(g_profiler, "Server::ProcessData");
        u32 peer_id = pkt->getPeerId();
@@ -1366,14 +1342,14 @@ void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend)
 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
 {
        std::vector<u16> clients = m_clients.getClientIDs();
 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
 {
        std::vector<u16> clients = m_clients.getClientIDs();
-       m_clients.Lock();
+       m_clients.lock();
        // Set the modified blocks unsent for all the clients
        for (std::vector<u16>::iterator i = clients.begin();
                 i != clients.end(); ++i) {
                        if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i))
                                client->SetBlocksNotSent(block);
        }
        // Set the modified blocks unsent for all the clients
        for (std::vector<u16>::iterator i = clients.begin();
                 i != clients.end(); ++i) {
                        if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i))
                                client->SetBlocksNotSent(block);
        }
-       m_clients.Unlock();
+       m_clients.unlock();
 }
 
 void Server::peerAdded(con::Peer *peer)
 }
 
 void Server::peerAdded(con::Peer *peer)
@@ -1423,11 +1399,11 @@ bool Server::getClientInfo(
        )
 {
        *state = m_clients.getClientState(peer_id);
        )
 {
        *state = m_clients.getClientState(peer_id);
-       m_clients.Lock();
+       m_clients.lock();
        RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
 
        if (client == NULL) {
        RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
 
        if (client == NULL) {
-               m_clients.Unlock();
+               m_clients.unlock();
                return false;
        }
 
                return false;
        }
 
@@ -1440,7 +1416,7 @@ bool Server::getClientInfo(
        *patch = client->getPatch();
        *vers_string = client->getPatch();
 
        *patch = client->getPatch();
        *vers_string = client->getPatch();
 
-       m_clients.Unlock();
+       m_clients.unlock();
 
        return true;
 }
 
        return true;
 }
@@ -1928,7 +1904,7 @@ void Server::SendPlayerPrivileges(u16 peer_id)
        pkt << (u16) privs.size();
 
        for(std::set<std::string>::const_iterator i = privs.begin();
        pkt << (u16) privs.size();
 
        for(std::set<std::string>::const_iterator i = privs.begin();
-                       i != privs.end(); i++) {
+                       i != privs.end(); ++i) {
                pkt << (*i);
        }
 
                pkt << (*i);
        }
 
@@ -2028,7 +2004,7 @@ s32 Server::playSound(const SimpleSoundSpec &spec,
                        << (u8) params.type << pos << params.object << params.loop;
 
        for(std::vector<u16>::iterator i = dst_clients.begin();
                        << (u8) params.type << pos << params.object << params.loop;
 
        for(std::vector<u16>::iterator i = dst_clients.begin();
-                       i != dst_clients.end(); i++) {
+                       i != dst_clients.end(); ++i) {
                psound.clients.insert(*i);
                m_clients.send(*i, 0, &pkt, true);
        }
                psound.clients.insert(*i);
                m_clients.send(*i, 0, &pkt, true);
        }
@@ -2047,7 +2023,7 @@ void Server::stopSound(s32 handle)
        pkt << handle;
 
        for(std::set<u16>::iterator i = psound.clients.begin();
        pkt << handle;
 
        for(std::set<u16>::iterator i = psound.clients.begin();
-                       i != psound.clients.end(); i++) {
+                       i != psound.clients.end(); ++i) {
                // Send as reliable
                m_clients.send(*i, 0, &pkt, true);
        }
                // Send as reliable
                m_clients.send(*i, 0, &pkt, true);
        }
@@ -2108,7 +2084,7 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
                }
 
                NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
                }
 
                NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
-               m_clients.Lock();
+               m_clients.lock();
                RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
                if (client != 0) {
                        pkt << p << n.param0 << n.param1 << n.param2
                RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
                if (client != 0) {
                        pkt << p << n.param0 << n.param1 << n.param2
@@ -2118,11 +2094,11 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
                                if (client->net_proto_version <= 21) {
                                        // Old clients always clear metadata; fix it
                                        // by sending the full block again.
                                if (client->net_proto_version <= 21) {
                                        // Old clients always clear metadata; fix it
                                        // by sending the full block again.
-                                       client->SetBlockNotSent(p);
+                                       client->SetBlockNotSent(getNodeBlockPos(p));
                                }
                        }
                }
                                }
                        }
                }
-               m_clients.Unlock();
+               m_clients.unlock();
 
                // Send as reliable
                if (pkt.getSize() > 0)
 
                // Send as reliable
                if (pkt.getSize() > 0)
@@ -2133,13 +2109,13 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
 void Server::setBlockNotSent(v3s16 p)
 {
        std::vector<u16> clients = m_clients.getClientIDs();
 void Server::setBlockNotSent(v3s16 p)
 {
        std::vector<u16> clients = m_clients.getClientIDs();
-       m_clients.Lock();
+       m_clients.lock();
        for(std::vector<u16>::iterator i = clients.begin();
                i != clients.end(); ++i) {
                RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
                client->SetBlockNotSent(p);
        }
        for(std::vector<u16>::iterator i = clients.begin();
                i != clients.end(); ++i) {
                RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
                client->SetBlockNotSent(p);
        }
-       m_clients.Unlock();
+       m_clients.unlock();
 }
 
 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
 }
 
 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
@@ -2168,7 +2144,7 @@ void Server::SendBlocks(float dtime)
 {
        DSTACK(__FUNCTION_NAME);
 
 {
        DSTACK(__FUNCTION_NAME);
 
-       JMutexAutoLock envlock(m_env_mutex);
+       MutexAutoLock envlock(m_env_mutex);
        //TODO check if one big lock could be faster then multiple small ones
 
        ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
        //TODO check if one big lock could be faster then multiple small ones
 
        ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
@@ -2182,7 +2158,7 @@ void Server::SendBlocks(float dtime)
 
                std::vector<u16> clients = m_clients.getClientIDs();
 
 
                std::vector<u16> clients = m_clients.getClientIDs();
 
-               m_clients.Lock();
+               m_clients.lock();
                for(std::vector<u16>::iterator i = clients.begin();
                        i != clients.end(); ++i) {
                        RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
                for(std::vector<u16>::iterator i = clients.begin();
                        i != clients.end(); ++i) {
                        RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
@@ -2193,7 +2169,7 @@ void Server::SendBlocks(float dtime)
                        total_sending += client->SendingCount();
                        client->GetNextBlocks(m_env,m_emerge, dtime, queue);
                }
                        total_sending += client->SendingCount();
                        client->GetNextBlocks(m_env,m_emerge, dtime, queue);
                }
-               m_clients.Unlock();
+               m_clients.unlock();
        }
 
        // Sort.
        }
 
        // Sort.
@@ -2201,7 +2177,7 @@ void Server::SendBlocks(float dtime)
        // Lowest is most important.
        std::sort(queue.begin(), queue.end());
 
        // Lowest is most important.
        std::sort(queue.begin(), queue.end());
 
-       m_clients.Lock();
+       m_clients.lock();
        for(u32 i=0; i<queue.size(); i++)
        {
                //TODO: Calculate limit dynamically
        for(u32 i=0; i<queue.size(); i++)
        {
                //TODO: Calculate limit dynamically
@@ -2231,7 +2207,7 @@ void Server::SendBlocks(float dtime)
                client->SentBlock(q.pos);
                total_sending++;
        }
                client->SentBlock(q.pos);
                total_sending++;
        }
-       m_clients.Unlock();
+       m_clients.unlock();
 }
 
 void Server::fillMediaCache()
 }
 
 void Server::fillMediaCache()
@@ -2243,7 +2219,7 @@ void Server::fillMediaCache()
        // Collect all media file paths
        std::vector<std::string> paths;
        for(std::vector<ModSpec>::iterator i = m_mods.begin();
        // Collect all media file paths
        std::vector<std::string> paths;
        for(std::vector<ModSpec>::iterator i = m_mods.begin();
-                       i != m_mods.end(); i++) {
+                       i != m_mods.end(); ++i) {
                const ModSpec &mod = *i;
                paths.push_back(mod.path + DIR_DELIM + "textures");
                paths.push_back(mod.path + DIR_DELIM + "sounds");
                const ModSpec &mod = *i;
                paths.push_back(mod.path + DIR_DELIM + "textures");
                paths.push_back(mod.path + DIR_DELIM + "sounds");
@@ -2254,7 +2230,7 @@ void Server::fillMediaCache()
 
        // Collect media file information from paths into cache
        for(std::vector<std::string>::iterator i = paths.begin();
 
        // Collect media file information from paths into cache
        for(std::vector<std::string>::iterator i = paths.begin();
-                       i != paths.end(); i++) {
+                       i != paths.end(); ++i) {
                std::string mediapath = *i;
                std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
                for (u32 j = 0; j < dirlist.size(); j++) {
                std::string mediapath = *i;
                std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
                for (u32 j = 0; j < dirlist.size(); j++) {
@@ -2330,44 +2306,22 @@ void Server::fillMediaCache()
        }
 }
 
        }
 }
 
-struct SendableMediaAnnouncement
-{
-       std::string name;
-       std::string sha1_digest;
-
-       SendableMediaAnnouncement(const std::string &name_="",
-                                 const std::string &sha1_digest_=""):
-               name(name_),
-               sha1_digest(sha1_digest_)
-       {}
-};
-
 void Server::sendMediaAnnouncement(u16 peer_id)
 {
        DSTACK(__FUNCTION_NAME);
 
 void Server::sendMediaAnnouncement(u16 peer_id)
 {
        DSTACK(__FUNCTION_NAME);
 
-       verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
-                       <<std::endl;
-
-       std::vector<SendableMediaAnnouncement> file_announcements;
-
-       for (std::map<std::string, MediaInfo>::iterator i = m_media.begin();
-                       i != m_media.end(); i++){
-               // Put in list
-               file_announcements.push_back(
-                               SendableMediaAnnouncement(i->first, i->second.sha1_digest));
-       }
+       verbosestream << "Server: Announcing files to id(" << peer_id << ")"
+               << std::endl;
 
        // Make packet
        std::ostringstream os(std::ios_base::binary);
 
        NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
 
        // Make packet
        std::ostringstream os(std::ios_base::binary);
 
        NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
-       pkt << (u16) file_announcements.size();
+       pkt << (u16) m_media.size();
 
 
-       for (std::vector<SendableMediaAnnouncement>::iterator
-                       j = file_announcements.begin();
-                       j != file_announcements.end(); ++j) {
-               pkt << j->name << j->sha1_digest;
+       for (std::map<std::string, MediaInfo>::iterator i = m_media.begin();
+                       i != m_media.end(); ++i) {
+               pkt << i->first << i->second.sha1_digest;
        }
 
        pkt << g_settings->get("remote_media");
        }
 
        pkt << g_settings->get("remote_media");
@@ -2527,7 +2481,7 @@ void Server::sendDetachedInventories(u16 peer_id)
 
        for(std::map<std::string, Inventory*>::iterator
                        i = m_detached_inventories.begin();
 
        for(std::map<std::string, Inventory*>::iterator
                        i = m_detached_inventories.begin();
-                       i != m_detached_inventories.end(); i++) {
+                       i != m_detached_inventories.end(); ++i) {
                const std::string &name = i->first;
                //Inventory *inv = i->second;
                sendDetachedInventory(name, peer_id);
                const std::string &name = i->first;
                //Inventory *inv = i->second;
                sendDetachedInventory(name, peer_id);
@@ -2678,7 +2632,7 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
                        if(psound.clients.empty())
                                m_playing_sounds.erase(i++);
                        else
                        if(psound.clients.empty())
                                m_playing_sounds.erase(i++);
                        else
-                               i++;
+                               ++i;
                }
 
                Player *player = m_env->getPlayer(peer_id);
                }
 
                Player *player = m_env->getPlayer(peer_id);
@@ -2734,7 +2688,7 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
                        }
                }
                {
                        }
                }
                {
-                       JMutexAutoLock env_lock(m_env_mutex);
+                       MutexAutoLock env_lock(m_env_mutex);
                        m_clients.DeleteClient(peer_id);
                }
        }
                        m_clients.DeleteClient(peer_id);
                }
        }
@@ -2890,6 +2844,10 @@ std::string Server::getBanDescription(const std::string &ip_or_name)
 
 void Server::notifyPlayer(const char *name, const std::wstring &msg)
 {
 
 void Server::notifyPlayer(const char *name, const std::wstring &msg)
 {
+       // m_env will be NULL if the server is initializing
+       if (!m_env)
+               return;
+
        Player *player = m_env->getPlayer(name);
        if (!player)
                return;
        Player *player = m_env->getPlayer(name);
        if (!player)
                return;
@@ -2903,6 +2861,10 @@ void Server::notifyPlayer(const char *name, const std::wstring &msg)
 bool Server::showFormspec(const char *playername, const std::string &formspec,
        const std::string &formname)
 {
 bool Server::showFormspec(const char *playername, const std::string &formspec,
        const std::string &formname)
 {
+       // m_env will be NULL if the server is initializing
+       if (!m_env)
+               return false;
+
        Player *player = m_env->getPlayer(playername);
        if (!player)
                return false;
        Player *player = m_env->getPlayer(playername);
        if (!player)
                return false;
@@ -3067,64 +3029,45 @@ void Server::notifyPlayers(const std::wstring &msg)
        SendChatMessage(PEER_ID_INEXISTENT,msg);
 }
 
        SendChatMessage(PEER_ID_INEXISTENT,msg);
 }
 
-void Server::spawnParticle(const char *playername, v3f pos,
+void Server::spawnParticle(const std::string &playername, v3f pos,
        v3f velocity, v3f acceleration,
        float expirationtime, float size, bool
        collisiondetection, bool vertical, const std::string &texture)
 {
        v3f velocity, v3f acceleration,
        float expirationtime, float size, bool
        collisiondetection, bool vertical, const std::string &texture)
 {
-       Player *player = m_env->getPlayer(playername);
-       if(!player)
+       // m_env will be NULL if the server is initializing
+       if (!m_env)
                return;
                return;
-       SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
-                       expirationtime, size, collisiondetection, vertical, texture);
-}
 
 
-void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
-       float expirationtime, float size,
-       bool collisiondetection, bool vertical, const std::string &texture)
-{
-       SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration,
+       u16 peer_id = PEER_ID_INEXISTENT;
+       if (playername != "") {
+               Player* player = m_env->getPlayer(playername.c_str());
+               if (!player)
+                       return;
+               peer_id = player->peer_id;
+       }
+
+       SendSpawnParticle(peer_id, pos, velocity, acceleration,
                        expirationtime, size, collisiondetection, vertical, texture);
 }
 
                        expirationtime, size, collisiondetection, vertical, texture);
 }
 
-u32 Server::addParticleSpawner(const char *playername, u16 amount, float spawntime,
+u32 Server::addParticleSpawner(u16 amount, float spawntime,
        v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
        float minexptime, float maxexptime, float minsize, float maxsize,
        v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
        float minexptime, float maxexptime, float minsize, float maxsize,
-       bool collisiondetection, bool vertical, const std::string &texture)
+       bool collisiondetection, bool vertical, const std::string &texture,
+       const std::string &playername)
 {
 {
-       Player *player = m_env->getPlayer(playername);
-       if(!player)
+       // m_env will be NULL if the server is initializing
+       if (!m_env)
                return -1;
 
                return -1;
 
-       u32 id = 0;
-       for(;;) // look for unused particlespawner id
-       {
-               id++;
-               if (std::find(m_particlespawner_ids.begin(),
-                               m_particlespawner_ids.end(), id)
-                               == m_particlespawner_ids.end())
-               {
-                       m_particlespawner_ids.push_back(id);
-                       break;
-               }
+       u16 peer_id = PEER_ID_INEXISTENT;
+       if (playername != "") {
+               Player* player = m_env->getPlayer(playername.c_str());
+               if (!player)
+                       return -1;
+               peer_id = player->peer_id;
        }
 
        }
 
-       SendAddParticleSpawner(player->peer_id, amount, spawntime,
-               minpos, maxpos, minvel, maxvel, minacc, maxacc,
-               minexptime, maxexptime, minsize, maxsize,
-               collisiondetection, vertical, texture, id);
-
-       return id;
-}
-
-u32 Server::addParticleSpawnerAll(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, bool vertical, const std::string &texture)
-{
        u32 id = 0;
        for(;;) // look for unused particlespawner id
        {
        u32 id = 0;
        for(;;) // look for unused particlespawner id
        {
@@ -3138,7 +3081,7 @@ u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
                }
        }
 
                }
        }
 
-       SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime,
+       SendAddParticleSpawner(peer_id, amount, spawntime,
                minpos, maxpos, minvel, maxvel, minacc, maxacc,
                minexptime, maxexptime, minsize, maxsize,
                collisiondetection, vertical, texture, id);
                minpos, maxpos, minvel, maxvel, minacc, maxacc,
                minexptime, maxexptime, minsize, maxsize,
                collisiondetection, vertical, texture, id);
@@ -3146,26 +3089,25 @@ u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
        return id;
 }
 
        return id;
 }
 
-void Server::deleteParticleSpawner(const char *playername, u32 id)
+void Server::deleteParticleSpawner(const std::string &playername, u32 id)
 {
 {
-       Player *player = m_env->getPlayer(playername);
-       if(!player)
-               return;
+       // m_env will be NULL if the server is initializing
+       if (!m_env)
+               throw ServerError("Can't delete particle spawners during initialisation!");
 
 
-       m_particlespawner_ids.erase(
-                       std::remove(m_particlespawner_ids.begin(),
-                       m_particlespawner_ids.end(), id),
-                       m_particlespawner_ids.end());
-       SendDeleteParticleSpawner(player->peer_id, id);
-}
+       u16 peer_id = PEER_ID_INEXISTENT;
+       if (playername != "") {
+               Player* player = m_env->getPlayer(playername.c_str());
+               if (!player)
+                       return;
+               peer_id = player->peer_id;
+       }
 
 
-void Server::deleteParticleSpawnerAll(u32 id)
-{
        m_particlespawner_ids.erase(
                        std::remove(m_particlespawner_ids.begin(),
                        m_particlespawner_ids.end(), id),
                        m_particlespawner_ids.end());
        m_particlespawner_ids.erase(
                        std::remove(m_particlespawner_ids.begin(),
                        m_particlespawner_ids.end(), id),
                        m_particlespawner_ids.end());
-       SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
+       SendDeleteParticleSpawner(peer_id, id);
 }
 
 Inventory* Server::createDetachedInventory(const std::string &name)
 }
 
 Inventory* Server::createDetachedInventory(const std::string &name)
@@ -3203,7 +3145,7 @@ bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
 
        for(std::list<RollbackAction>::const_iterator
                        i = actions.begin();
 
        for(std::list<RollbackAction>::const_iterator
                        i = actions.begin();
-                       i != actions.end(); i++)
+                       i != actions.end(); ++i)
        {
                const RollbackAction &action = *i;
                num_tried++;
        {
                const RollbackAction &action = *i;
                num_tried++;
@@ -3321,10 +3263,6 @@ v3f Server::findSpawnPos()
                return nodeposf * BS;
        }
 
                return nodeposf * BS;
        }
 
-       // Default position is static_spawnpoint
-       // We will return it if we don't found a good place
-       v3s16 nodepos(nodeposf.X, nodeposf.Y, nodeposf.Z);
-
        s16 water_level = map.getWaterLevel();
 
        bool is_good = false;
        s16 water_level = map.getWaterLevel();
 
        bool is_good = false;
@@ -3344,7 +3282,7 @@ v3f Server::findSpawnPos()
                if (groundheight > water_level + 6) // Don't go to high places
                        continue;
 
                if (groundheight > water_level + 6) // Don't go to high places
                        continue;
 
-               nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
+               v3s16 nodepos(nodepos2d.X, groundheight, nodepos2d.Y);
 
                s32 air_count = 0;
                for (s32 i = 0; i < 10; i++) {
 
                s32 air_count = 0;
                for (s32 i = 0; i < 10; i++) {
@@ -3353,7 +3291,11 @@ v3f Server::findSpawnPos()
                        content_t c = map.getNodeNoEx(nodepos).getContent();
                        if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
                                air_count++;
                        content_t c = map.getNodeNoEx(nodepos).getContent();
                        if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
                                air_count++;
-                               if (air_count >= 2){
+                               if (air_count >= 2) {
+                                       nodeposf = intToFloat(nodepos, BS);
+                                       // Don't spawn the player outside map boundaries
+                                       if (objectpos_over_limit(nodeposf))
+                                               continue;
                                        is_good = true;
                                        break;
                                }
                                        is_good = true;
                                        break;
                                }
@@ -3362,7 +3304,7 @@ v3f Server::findSpawnPos()
                }
        }
 
                }
        }
 
-       return intToFloat(nodepos, BS);
+       return nodeposf;
 }
 
 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
 }
 
 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
@@ -3411,6 +3353,16 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version
 
                // Add player to environment
                m_env->addPlayer(player);
 
                // Add player to environment
                m_env->addPlayer(player);
+       } else {
+               // If the player exists, ensure that they respawn inside legal bounds
+               // This fixes an assert crash when the player can't be added
+               // to the environment
+               if (objectpos_over_limit(player->getPosition())) {
+                       actionstream << "Respawn position for player \""
+                               << name << "\" outside limits, resetting" << std::endl;
+                       v3f pos = findSpawnPos();
+                       player->setPosition(pos);
+               }
        }
 
        // Create a new player active object
        }
 
        // Create a new player active object