Remove most exceptions from getNode() (and variants)
[oweals/minetest.git] / src / server.cpp
index 40857f84d72954b673c90ddda6af9d5b91cd83f2..d1f3997e92d794eafe029da271e6c3cc060503dd 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"
@@ -338,6 +338,9 @@ Server::Server(
        // Apply item aliases in the node definition manager
        m_nodedef->updateAliases(m_itemdef);
 
+       // Perform pending node name resolutions
+       m_nodedef->getResolver()->resolveNodes();
+
        // Load the mapgen params from global settings now after any
        // initial overrides have been set by the mods
        m_emerge->loadMapgenParams();
@@ -684,6 +687,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 +708,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,9 +741,9 @@ 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
@@ -1169,10 +1180,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();
 
@@ -1448,14 +1464,21 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                /*
                        Set up player
                */
-
-               // Get player name
                char playername[PLAYERNAME_SIZE];
-               for(u32 i=0; i<PLAYERNAME_SIZE-1; i++)
-               {
-                       playername[i] = data[3+i];
+               unsigned int playername_length = 0;
+               for (; playername_length < PLAYERNAME_SIZE; playername_length++ ) {
+                       playername[playername_length] = data[3+playername_length];
+                       if (data[3+playername_length] == 0)
+                               break;
+               }
+
+               if (playername_length == PLAYERNAME_SIZE) {
+                       actionstream<<"Server: Player with name exceeding max length "
+                                       <<"tried to connect from "<<addr_s<<std::endl;
+                       DenyAccess(peer_id, L"Name too long");
+                       return;
                }
-               playername[PLAYERNAME_SIZE-1] = 0;
+
 
                if(playername[0]=='\0')
                {
@@ -2401,17 +2424,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
@@ -2456,16 +2480,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);
                                }
 
@@ -2545,14 +2565,17 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                if(is_valid_dig && n.getContent() != CONTENT_IGNORE)
                                        m_script->node_on_dig(p_under, n, playersao);
 
+                               v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
+                               RemoteClient *client = getClient(peer_id);
                                // Send unusual result (that is, node not being removed)
                                if(m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR)
                                {
                                        // Re-send block to revert change on client-side
-                                       RemoteClient *client = getClient(peer_id);
-                                       v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
                                        client->SetBlockNotSent(blockpos);
                                }
+                               else {
+                                       client->ResendBlockIfOnWire(blockpos);
+                               }
                        }
                } // action == 2
 
@@ -2594,15 +2617,21 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
                        // If item has node placement prediction, always send the
                        // blocks to make sure the client knows what exactly happened
-                       if(item.getDefinition(m_itemdef).node_placement_prediction != ""){
-                               RemoteClient *client = getClient(peer_id);
-                               v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
+                       RemoteClient *client = getClient(peer_id);
+                       v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
+                       v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
+                       if(item.getDefinition(m_itemdef).node_placement_prediction != "") {
                                client->SetBlockNotSent(blockpos);
-                               v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
-                               if(blockpos2 != blockpos){
+                               if(blockpos2 != blockpos) {
                                        client->SetBlockNotSent(blockpos2);
                                }
                        }
+                       else {
+                               client->ResendBlockIfOnWire(blockpos);
+                               if(blockpos2 != blockpos) {
+                                       client->ResendBlockIfOnWire(blockpos2);
+                               }
+                       }
                } // action == 3
 
                /*
@@ -3853,7 +3882,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);
@@ -4580,8 +4609,13 @@ 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;
 
-       m_script->player_event(player->getPlayerSAO(),"hud_changed");
+       m_script->player_event(playersao, "hud_changed");
        return true;
 }
 
@@ -4864,6 +4898,11 @@ IShaderSource* Server::getShaderSource()
 {
        return NULL;
 }
+scene::ISceneManager* Server::getSceneManager()
+{
+       return NULL;
+}
+
 u16 Server::allocateUnknownNodeId(const std::string &name)
 {
        return m_nodedef->allocateDummy(name);
@@ -5012,15 +5051,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);
        }