]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/environment.cpp
Implement urlencode and urldecode
[dragonfireclient.git] / src / environment.cpp
index 03b436890b333d4c7fe8db968806889264da7ce1..7fe5d356aa4993a2dc6e8da51b456ac87556b32f 100644 (file)
@@ -354,7 +354,7 @@ ServerMap & ServerEnvironment::getServerMap()
        return *m_map;
 }
 
-bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize)
+bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16 *p)
 {
        float distance = pos1.getDistanceFrom(pos2);
 
@@ -372,6 +372,9 @@ bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize)
                MapNode n = getMap().getNodeNoEx(pos);
 
                if(n.param0 != CONTENT_AIR) {
+                       if (p) {
+                               *p = pos;
+                       }
                        return false;
                }
        }
@@ -809,16 +812,6 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
        
        // Activate stored objects
        activateObjects(block, dtime_s);
-       
-       // Calculate weather conditions
-       if (m_use_weather) {
-               m_map->updateBlockHeat(this, block->getPos() *  MAP_BLOCKSIZE, block);
-               m_map->updateBlockHumidity(this, block->getPos() * MAP_BLOCKSIZE, block);
-       } else {
-               block->heat     = HEAT_UNDEFINED;
-               block->humidity = HUMIDITY_UNDEFINED;
-               block->weather_update_time = 0;
-       }
 
        // Run node timers
        std::map<v3s16, NodeTimer> elapsed_timers =
@@ -884,6 +877,11 @@ bool ServerEnvironment::removeNode(v3s16 p)
        return true;
 }
 
+bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n)
+{
+       return m_map->addNodeWithEvent(p, n, false);
+}
+
 std::set<u16> ServerEnvironment::getObjectsInsideRadius(v3f pos, float radius)
 {
        std::set<u16> objects;
@@ -1427,8 +1425,8 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
                ServerActiveObject *object = i->second;
                if(object == NULL)
                        continue;
-               // Discard if removed
-               if(object->m_removed)
+               // Discard if removed or deactivating
+               if(object->m_removed || object->m_pending_deactivation)
                        continue;
                if(object->unlimitedTransferDistance() == false){
                        // Discard if too far
@@ -1478,7 +1476,7 @@ void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
                        continue;
                }
 
-               if(object->m_removed)
+               if(object->m_removed || object->m_pending_deactivation)
                {
                        removed_objects.insert(id);
                        continue;
@@ -1566,9 +1564,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
                StaticObject s_obj(object->getType(), objectpos, staticdata);
                // Add to the block where the object is located in
                v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
-               MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
-               if(block)
-               {
+               MapBlock *block = m_map->emergeBlock(blockpos);
+               if(block){
                        block->m_static_objects.m_active[object->getId()] = s_obj;
                        object->m_static_exists = true;
                        object->m_static_block = blockpos;
@@ -1576,11 +1573,10 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
                        if(set_changed)
                                block->raiseModified(MOD_STATE_WRITE_NEEDED, 
                                                "addActiveObjectRaw");
-               }
-               else{
+               } else {
                        v3s16 p = floatToInt(objectpos, BS);
                        errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
-                                       <<"could not find block for storing id="<<object->getId()
+                                       <<"could not emerge block for storing id="<<object->getId()
                                        <<" statically (pos="<<PP(p)<<")"<<std::endl;
                }
        }
@@ -1626,18 +1622,39 @@ void ServerEnvironment::removeRemovedObjects()
                        if (block) {
                                block->m_static_objects.remove(id);
                                block->raiseModified(MOD_STATE_WRITE_NEEDED,
-                                               "removeRemovedObjects");
+                                               "removeRemovedObjects/remove");
                                obj->m_static_exists = false;
                        } else {
-                               infostream << "failed to emerge block from which "
-                                       "an object to be removed was loaded from. id="<<id<<std::endl;
+                               infostream<<"Failed to emerge block from which an object to "
+                                               <<"be removed was loaded from. id="<<id<<std::endl;
                        }
                }
 
-               // If m_known_by_count > 0, don't actually remove.
+               // If m_known_by_count > 0, don't actually remove. On some future
+               // invocation this will be 0, which is when removal will continue.
                if(obj->m_known_by_count > 0)
                        continue;
-               
+
+               /*
+                       Move static data from active to stored if not marked as removed
+               */
+               if(obj->m_static_exists && !obj->m_removed){
+                       MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
+                       if (block) {
+                               std::map<u16, StaticObject>::iterator i =
+                                               block->m_static_objects.m_active.find(id);
+                               if(i != block->m_static_objects.m_active.end()){
+                                       block->m_static_objects.m_stored.push_back(i->second);
+                                       block->m_static_objects.m_active.erase(id);
+                                       block->raiseModified(MOD_STATE_WRITE_NEEDED,
+                                                       "removeRemovedObjects/deactivate");
+                               }
+                       } else {
+                               infostream<<"Failed to emerge block from which an object to "
+                                               <<"be deactivated was loaded from. id="<<id<<std::endl;
+                       }
+               }
+
                // Tell the object about removal
                obj->removingFromEnvironment();
                // Deregister in scripting api
@@ -1718,10 +1735,9 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
                                "large amount of objects");
                return;
        }
-       // A list for objects that couldn't be converted to active for some
-       // reason. They will be stored back.
+
+       // Activate stored objects
        std::list<StaticObject> new_stored;
-       // Loop through stored static objects
        for(std::list<StaticObject>::iterator
                        i = block->m_static_objects.m_stored.begin();
                        i != block->m_static_objects.m_stored.end(); ++i)
@@ -1760,6 +1776,19 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
                StaticObject &s_obj = *i;
                block->m_static_objects.m_stored.push_back(s_obj);
        }
+
+       // Turn the active counterparts of activated objects not pending for
+       // deactivation
+       for(std::map<u16, StaticObject>::iterator
+                       i = block->m_static_objects.m_active.begin();
+                       i != block->m_static_objects.m_active.end(); ++i)
+       {
+               u16 id = i->first;
+               ServerActiveObject *object = getActiveObject(id);
+               assert(object);
+               object->m_pending_deactivation = false;
+       }
+
        /*
                Note: Block hasn't really been modified here.
                The objects have just been activated and moved from the stored
@@ -1805,6 +1834,47 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                // The block in which the object resides in
                v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
 
+               // If object's static data is stored in a deactivated block and object
+               // is actually located in an active block, re-save to the block in
+               // which the object is actually located in.
+               if(!force_delete &&
+                               obj->m_static_exists &&
+                               !m_active_blocks.contains(obj->m_static_block) &&
+                                m_active_blocks.contains(blockpos_o))
+               {
+                       v3s16 old_static_block = obj->m_static_block;
+
+                       // Save to block where object is located
+                       MapBlock *block = m_map->emergeBlock(blockpos_o, false);
+                       if(!block){
+                               errorstream<<"ServerEnvironment::deactivateFarObjects(): "
+                                               <<"Could not save object id="<<id
+                                               <<" to it's current block "<<PP(blockpos_o)
+                                               <<std::endl;
+                               continue;
+                       }
+                       std::string staticdata_new = obj->getStaticData();
+                       StaticObject s_obj(obj->getType(), objectpos, staticdata_new);
+                       block->m_static_objects.insert(id, s_obj);
+                       obj->m_static_block = blockpos_o;
+                       block->raiseModified(MOD_STATE_WRITE_NEEDED,
+                                       "deactivateFarObjects: Static data moved in");
+
+                       // Delete from block where object was located
+                       block = m_map->emergeBlock(old_static_block, false);
+                       if(!block){
+                               errorstream<<"ServerEnvironment::deactivateFarObjects(): "
+                                               <<"Could not delete object id="<<id
+                                               <<" from it's previous block "<<PP(old_static_block)
+                                               <<std::endl;
+                               continue;
+                       }
+                       block->m_static_objects.remove(id);
+                       block->raiseModified(MOD_STATE_WRITE_NEEDED,
+                                       "deactivateFarObjects: Static data moved out");
+                       continue;
+               }
+
                // If block is active, don't remove
                if(!force_delete && m_active_blocks.contains(blockpos_o))
                        continue;
@@ -1879,6 +1949,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                                block = m_map->emergeBlock(blockpos);
                        } catch(InvalidPositionException &e){
                                // Handled via NULL pointer
+                               // NOTE: emergeBlock's failure is usually determined by it
+                               //       actually returning NULL
                        }
 
                        if(block)
@@ -1892,17 +1964,21 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                                                        <<" Forcing delete."<<std::endl;
                                        force_delete = true;
                                } else {
-                                       // If static counterpart already exists, remove it first.
-                                       // This shouldn't happen, but happens rarely for some
-                                       // unknown reason. Unsuccessful attempts have been made to
-                                       // find said reason.
+                                       // If static counterpart already exists in target block,
+                                       // remove it first.
+                                       // This shouldn't happen because the object is removed from
+                                       // the previous block before this according to
+                                       // obj->m_static_block, but happens rarely for some unknown
+                                       // reason. Unsuccessful attempts have been made to find
+                                       // said reason.
                                        if(id && block->m_static_objects.m_active.find(id) != block->m_static_objects.m_active.end()){
                                                infostream<<"ServerEnv: WARNING: Performing hack #83274"
                                                                <<std::endl;
                                                block->m_static_objects.remove(id);
                                        }
-                                       //store static data
-                                       block->m_static_objects.insert(0, s_obj);
+                                       // Store static data
+                                       u16 store_id = pending_delete ? id : 0;
+                                       block->m_static_objects.insert(store_id, s_obj);
                                        
                                        // Only mark block as modified if data changed considerably
                                        if(shall_be_written)