Performance fixes.
[oweals/minetest.git] / src / server.cpp
index fd9e1ce7b5a82ae7ceb779d5e08243ec794f09b8..c948427ad559b3c584f1f8910f39a43d9c87cb21 100644 (file)
@@ -44,7 +44,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "craftdef.h"
 #include "emerge.h"
 #include "mapgen.h"
-#include "biome.h"
+#include "mg_biome.h"
 #include "content_mapnode.h"
 #include "content_nodemeta.h"
 #include "content_abm.h"
@@ -181,7 +181,6 @@ Server::Server(
                        this),
        m_banmanager(NULL),
        m_rollback(NULL),
-       m_rollback_sink_enabled(true),
        m_enable_rollback_recording(false),
        m_emerge(NULL),
        m_script(NULL),
@@ -241,12 +240,11 @@ Server::Server(
                throw ServerError("Failed to initialize world");
 
        // Create ban manager
-       std::string ban_path = m_path_world+DIR_DELIM+"ipban.txt";
+       std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
        m_banmanager = new BanManager(ban_path);
 
        // Create rollback manager
-       std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt";
-       m_rollback = createRollbackManager(rollback_path, this);
+       m_rollback = new RollbackManager(m_path_world, this);
 
        ModConfiguration modconf(m_path_world);
        m_mods = modconf.getMods();
@@ -297,6 +295,12 @@ Server::Server(
        // Lock environment
        JMutexAutoLock envlock(m_env_mutex);
 
+       // Load mapgen params from Settings
+       m_emerge->loadMapgenParams();
+
+       // Create the Map (loads map_meta.txt, overriding configured mapgen params)
+       ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
+
        // Initialize scripting
        infostream<<"Server: Initializing Lua"<<std::endl;
 
@@ -304,10 +308,8 @@ Server::Server(
 
        std::string scriptpath = getBuiltinLuaPath() + DIR_DELIM "init.lua";
 
-       if (!m_script->loadScript(scriptpath)) {
+       if (!m_script->loadScript(scriptpath))
                throw ModError("Failed to load and run " + scriptpath);
-       }
-
 
        // Print 'em
        infostream<<"Server: Loading mods: ";
@@ -338,19 +340,16 @@ Server::Server(
        // Apply item aliases in the node definition manager
        m_nodedef->updateAliases(m_itemdef);
 
-       // Load the mapgen params from global settings now after any
-       // initial overrides have been set by the mods
-       m_emerge->loadMapgenParams();
+       m_nodedef->setNodeRegistrationStatus(true);
+
+       // Perform pending node name resolutions
+       m_nodedef->runNodeResolverCallbacks();
 
        // Initialize Environment
-       ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
        m_env = new ServerEnvironment(servermap, m_script, this, m_path_world);
 
        m_clients.setEnv(m_env);
 
-       // Run some callbacks after the MG params have been set up but before activation
-       m_script->environment_OnMapgenInit(&m_emerge->params);
-
        // Initialize mapgens
        m_emerge->initMapgens();
 
@@ -567,7 +566,7 @@ void Server::AsyncRunStep(bool initial_step)
                m_env->step(dtime);
        }
 
-       const float map_timer_and_unload_dtime = 2.92;
+       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);
@@ -663,7 +662,7 @@ void Server::AsyncRunStep(bool initial_step)
                /*
                        Set the modified blocks unsent for all the clients
                */
-               if(modified_blocks.size() > 0)
+               if(!modified_blocks.empty())
                {
                        SetBlocksNotSent(modified_blocks);
                }
@@ -684,6 +683,7 @@ void Server::AsyncRunStep(bool initial_step)
                                        m_env->getGameTime(),
                                        m_lag,
                                        m_gamespec.id,
+                                       m_emerge->params.mg_name,
                                        m_mods);
                        counter = 0.01;
                }
@@ -704,7 +704,14 @@ void Server::AsyncRunStep(bool initial_step)
 
                // Radius inside which objects are active
                s16 radius = g_settings->getS16("active_object_send_range_blocks");
+               s16 player_radius = g_settings->getS16("player_transfer_distance");
+
+               if (player_radius == 0 && g_settings->exists("unlimited_player_transfer_distance") &&
+                               !g_settings->getBool("unlimited_player_transfer_distance"))
+                       player_radius = radius;
+
                radius *= MAP_BLOCKSIZE;
+               player_radius *= MAP_BLOCKSIZE;
 
                for(std::map<u16, RemoteClient*>::iterator
                        i = clients.begin();
@@ -730,13 +737,13 @@ void Server::AsyncRunStep(bool initial_step)
 
                        std::set<u16> removed_objects;
                        std::set<u16> added_objects;
-                       m_env->getRemovedActiveObjects(pos, radius,
+                       m_env->getRemovedActiveObjects(pos, radius, player_radius,
                                        client->m_known_objects, removed_objects);
-                       m_env->getAddedActiveObjects(pos, radius,
+                       m_env->getAddedActiveObjects(pos, radius, player_radius,
                                        client->m_known_objects, added_objects);
 
                        // Ignore if nothing happened
-                       if(removed_objects.size() == 0 && added_objects.size() == 0)
+                       if(removed_objects.empty() && added_objects.empty())
                        {
                                //infostream<<"active objects: none changed"<<std::endl;
                                continue;
@@ -1042,7 +1049,7 @@ void Server::AsyncRunStep(bool initial_step)
                        /*
                                Set blocks not sent to far players
                        */
-                       if(far_players.size() > 0)
+                       if(!far_players.empty())
                        {
                                // Convert list format to that wanted by SetBlocksNotSent
                                std::map<v3s16, MapBlock*> modified_blocks2;
@@ -1169,10 +1176,15 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
        std::string playername = "";
        PlayerSAO *playersao = NULL;
        m_clients.Lock();
-       RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
-       if (client != NULL) {
-               playername = client->getName();
-               playersao = emergePlayer(playername.c_str(), peer_id);
+       try {
+               RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
+               if (client != NULL) {
+                       playername = client->getName();
+                       playersao = emergePlayer(playername.c_str(), peer_id);
+               }
+       } catch (std::exception &e) {
+               m_clients.Unlock();
+               throw;
        }
        m_clients.Unlock();
 
@@ -1347,7 +1359,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                u8 client_max = data[2];
                u8 our_max = SER_FMT_VER_HIGHEST_READ;
                // Use the highest version supported by both
-               u8 deployed = std::min(client_max, our_max);
+               int deployed = std::min(client_max, our_max);
                // If it's lower than the lowest supported, give up.
                if(deployed < SER_FMT_VER_LOWEST)
                        deployed = SER_FMT_VER_INVALID;
@@ -1496,7 +1508,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                                <<"tried to connect from "<<addr_s<<" "
                                                <<"but it was disallowed for the following reason: "
                                                <<reason<<std::endl;
-                               DenyAccess(peer_id, narrow_to_wide(reason.c_str()));
+                               DenyAccess(peer_id, narrow_to_wide(reason));
                                return;
                        }
                }
@@ -2408,17 +2420,18 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                        somebody is cheating, by checking the timing.
                                */
                                MapNode n(CONTENT_IGNORE);
-                               try
-                               {
-                                       n = m_env->getMap().getNode(p_under);
-                               }
-                               catch(InvalidPositionException &e)
-                               {
+                               bool pos_ok;
+                               n = m_env->getMap().getNodeNoEx(p_under, &pos_ok);
+                               if (pos_ok)
+                                       n = m_env->getMap().getNodeNoEx(p_under, &pos_ok);
+
+                               if (!pos_ok) {
                                        infostream<<"Server: Not punching: Node not found."
                                                        <<" Adding block to emerge queue."
                                                        <<std::endl;
                                        m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
                                }
+
                                if(n.getContent() != CONTENT_IGNORE)
                                        m_script->node_on_punch(p_under, n, playersao, pointed);
                                // Cheat prevention
@@ -2463,16 +2476,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        // Only digging of nodes
                        if(pointed.type == POINTEDTHING_NODE)
                        {
-                               MapNode n(CONTENT_IGNORE);
-                               try
-                               {
-                                       n = m_env->getMap().getNode(p_under);
-                               }
-                               catch(InvalidPositionException &e)
-                               {
-                                       infostream<<"Server: Not finishing digging: Node not found."
-                                                       <<" Adding block to emerge queue."
-                                                       <<std::endl;
+                               bool pos_ok;
+                               MapNode n = m_env->getMap().getNodeNoEx(p_under, &pos_ok);
+                               if (!pos_ok) {
+                                       infostream << "Server: Not finishing digging: Node not found."
+                                                  << " Adding block to emerge queue."
+                                                  << std::endl;
                                        m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
                                }
 
@@ -2639,7 +2648,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        }
 
                } // action == 4
-               
+
 
                /*
                        Catch invalid actions
@@ -2664,7 +2673,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                continue;
                        ServerPlayingSound &psound = i->second;
                        psound.clients.erase(peer_id);
-                       if(psound.clients.size() == 0)
+                       if(psound.clients.empty())
                                m_playing_sounds.erase(i++);
                }
        }
@@ -3617,7 +3626,7 @@ s32 Server::playSound(const SimpleSoundSpec &spec,
                        dst_clients.push_back(*i);
                }
        }
-       if(dst_clients.size() == 0)
+       if(dst_clients.empty())
                return -1;
 
        // Create the sound
@@ -3869,7 +3878,7 @@ void Server::SendBlocks(float dtime)
                        RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
 
                        if (client == NULL)
-                               return;
+                               continue;
 
                        total_sending += client->SendingCount();
                        client->GetNextBlocks(m_env,m_emerge, dtime, queue);
@@ -4311,7 +4320,7 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
                {
                        ServerPlayingSound &psound = i->second;
                        psound.clients.erase(peer_id);
-                       if(psound.clients.size() == 0)
+                       if(psound.clients.empty())
                                m_playing_sounds.erase(i++);
                        else
                                i++;
@@ -4457,7 +4466,7 @@ std::wstring Server::getStatusString()
                        name = narrow_to_wide(player->getName());
                // Add name to information string
                if(!first)
-                       os<<L",";
+                       os<<L", ";
                else
                        first = false;
                os<<name;
@@ -4559,7 +4568,7 @@ bool Server::showFormspec(const char *playername, const std::string &formspec, c
 u32 Server::hudAdd(Player *player, HudElement *form) {
        if (!player)
                return -1;
-       
+
        u32 id = player->addHud(form);
 
        SendHUDAdd(player->peer_id, id, form);
@@ -4575,7 +4584,7 @@ bool Server::hudRemove(Player *player, u32 id) {
 
        if (!todel)
                return false;
-       
+
        delete todel;
 
        SendHUDRemove(player->peer_id, id);
@@ -4596,9 +4605,9 @@ bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
 
        SendHUDSetFlags(player->peer_id, flags, mask);
        player->hud_flags = flags;
-       
+
        PlayerSAO* playersao = player->getPlayerSAO();
-       
+
        if (playersao == NULL)
                return false;
 
@@ -4821,8 +4830,6 @@ bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
 {
        infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
        ServerMap *map = (ServerMap*)(&m_env->getMap());
-       // Disable rollback report sink while reverting
-       BoolScopeSet rollback_scope_disable(&m_rollback_sink_enabled, false);
 
        // Fail if no actions to handle
        if(actions.empty()){
@@ -4885,6 +4892,11 @@ IShaderSource* Server::getShaderSource()
 {
        return NULL;
 }
+scene::ISceneManager* Server::getSceneManager()
+{
+       return NULL;
+}
+
 u16 Server::allocateUnknownNodeId(const std::string &name)
 {
        return m_nodedef->allocateDummy(name);
@@ -4897,14 +4909,6 @@ MtEventManager* Server::getEventManager()
 {
        return m_event;
 }
-IRollbackReportSink* Server::getRollbackReportSink()
-{
-       if(!m_enable_rollback_recording)
-               return NULL;
-       if(!m_rollback_sink_enabled)
-               return NULL;
-       return m_rollback;
-}
 
 IWritableItemDefManager* Server::getWritableItemDefManager()
 {
@@ -5033,15 +5037,17 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
        // Create player if it doesn't exist
        if (!player) {
                newplayer = true;
-               player = new RemotePlayer(this);
-               player->updateName(name);
-               /* Set player position */
+               player = new RemotePlayer(this, name);
+               // Set player position
                infostream<<"Server: Finding spawn place for player \""
                                <<name<<"\""<<std::endl;
                v3f pos = findSpawnPos(m_env->getServerMap());
                player->setPosition(pos);
 
-               /* Add player to environment */
+               // Make sure the player is saved
+               player->setModified(true);
+
+               // Add player to environment
                m_env->addPlayer(player);
        }