Add congestion control settings to minetest.conf
[oweals/minetest.git] / src / environment.cpp
index 24943ad5fa94fe128fadbf318f460f1d86d35340..e70cb39b784d42a38a6e93f118e408a9e3c3e5f9 100644 (file)
@@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #endif
 #include "daynightratio.h"
 #include "map.h"
+#include "util/serialize.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
@@ -328,7 +329,8 @@ ServerEnvironment::ServerEnvironment(ServerMap *map, lua_State *L,
        m_send_recommended_timer(0),
        m_active_block_interval_overload_skip(0),
        m_game_time(0),
-       m_game_time_fraction_counter(0)
+       m_game_time_fraction_counter(0),
+       m_recommended_send_interval(0.1)
 {
 }
 
@@ -743,19 +745,25 @@ neighbor_found:
                                u32 active_object_count = block->m_static_objects.m_active.size();
                                // Find out how many objects this and all the neighbors contain
                                u32 active_object_count_wider = 0;
+                               u32 wider_unknown_count = 0;
                                for(s16 x=-1; x<=1; x++)
                                for(s16 y=-1; y<=1; y++)
                                for(s16 z=-1; z<=1; z++)
                                {
                                        MapBlock *block2 = map->getBlockNoCreateNoEx(
                                                        block->getPos() + v3s16(x,y,z));
-                                       if(block2==NULL)
+                                       if(block2==NULL){
+                                               wider_unknown_count = 0;
                                                continue;
+                                       }
                                        active_object_count_wider +=
                                                        block2->m_static_objects.m_active.size()
                                                        + block2->m_static_objects.m_stored.size();
                                }
-
+                               // Extrapolate
+                               u32 wider_known_count = 3*3*3 - wider_unknown_count;
+                               active_object_count_wider += wider_unknown_count * active_object_count_wider / wider_known_count;
+                               
                                // Call all the trigger variations
                                i->abm->trigger(m_env, p, n);
                                i->abm->trigger(m_env, p, n,
@@ -784,7 +792,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
                        <<dtime_s<<" seconds old."<<std::endl;*/
        
        // Activate stored objects
-       activateObjects(block);
+       activateObjects(block, dtime_s);
 
        // Run node timers
        std::map<v3s16, NodeTimer> elapsed_timers =
@@ -933,6 +941,11 @@ void ServerEnvironment::step(float dtime)
        /* Step time of day */
        stepTimeOfDay(dtime);
 
+       // Update this one
+       // NOTE: This is kind of funny on a singleplayer game, but doesn't
+       // really matter that much.
+       m_recommended_send_interval = g_settings->getFloat("dedicated_server_step");
+
        /*
                Increment game time
        */
@@ -1243,7 +1256,7 @@ u16 getFreeServerActiveObjectId(
 u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
 {
        assert(object);
-       u16 id = addActiveObjectRaw(object, true);
+       u16 id = addActiveObjectRaw(object, true, 0);
        return id;
 }
 
@@ -1402,7 +1415,7 @@ ActiveObjectMessage ServerEnvironment::getActiveObjectMessage()
 */
 
 u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
-               bool set_changed)
+               bool set_changed, u32 dtime_s)
 {
        assert(object);
        if(object->getId() == 0){
@@ -1442,7 +1455,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
        // Register reference in scripting api (must be done before post-init)
        scriptapi_add_object_reference(m_lua, object);
        // Post-initialize object
-       object->addedToEnvironment();
+       object->addedToEnvironment(dtime_s);
        
        // Add static data to block
        if(object->isStaticAllowed())
@@ -1465,9 +1478,10 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
                                                "addActiveObjectRaw");
                }
                else{
+                       v3s16 p = floatToInt(objectpos, BS);
                        errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
                                        <<"could not find block for storing id="<<object->getId()
-                                       <<" statically"<<std::endl;
+                                       <<" statically (pos="<<PP(p)<<")"<<std::endl;
                }
        }
        
@@ -1578,7 +1592,7 @@ static void print_hexdump(std::ostream &o, const std::string &data)
 /*
        Convert stored objects from blocks near the players to active.
 */
-void ServerEnvironment::activateObjects(MapBlock *block)
+void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
 {
        if(block==NULL)
                return;
@@ -1602,7 +1616,7 @@ void ServerEnvironment::activateObjects(MapBlock *block)
                                "large amount of objects");
                return;
        }
-       // A list for objects that couldn't be converted to static for some
+       // A list for objects that couldn't be converted to active for some
        // reason. They will be stored back.
        core::list<StaticObject> new_stored;
        // Loop through stored static objects
@@ -1632,7 +1646,7 @@ void ServerEnvironment::activateObjects(MapBlock *block)
                                <<"activated static object pos="<<PP(s_obj.pos/BS)
                                <<" type="<<(int)s_obj.type<<std::endl;
                // This will also add the object to the active static list
-               addActiveObjectRaw(obj, false);
+               addActiveObjectRaw(obj, false, dtime_s);
        }
        // Clear stored list
        block->m_static_objects.m_stored.clear();
@@ -1756,7 +1770,12 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                        // Add to the block where the object is located in
                        v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
                        // Get or generate the block
-                       MapBlock *block = m_map->emergeBlock(blockpos);
+                       MapBlock *block = NULL;
+                       try{
+                               block = m_map->emergeBlock(blockpos);
+                       } catch(InvalidPositionException &e){
+                               // Handled via NULL pointer
+                       }
 
                        if(block)
                        {
@@ -1793,9 +1812,10 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                        }
                        else{
                                if(!force_delete){
+                                       v3s16 p = floatToInt(objectpos, BS);
                                        errorstream<<"ServerEnv: Could not find or generate "
                                                        <<"a block for storing id="<<obj->getId()
-                                                       <<" statically"<<std::endl;
+                                                       <<" statically (pos="<<PP(p)<<")"<<std::endl;
                                        continue;
                                }
                        }
@@ -2033,10 +2053,18 @@ void ClientEnvironment::step(float dtime)
                        i = player_collisions.begin();
                        i != player_collisions.end(); i++)
        {
+               CollisionInfo &info = *i;
+               v3f speed_diff = info.new_speed - info.old_speed;;
+               // Handle only fall damage
+               // (because otherwise walking against something in fast_move kills you)
+               if(speed_diff.Y < 0 || info.old_speed.Y >= 0)
+                       continue;
+               // Get rid of other components
+               speed_diff.X = 0;
+               speed_diff.Z = 0;
                f32 pre_factor = 1; // 1 hp per node/s
                f32 tolerance = BS*14; // 5 without damage
                f32 post_factor = 1; // 1 hp per node/s
-               CollisionInfo &info = *i;
                if(info.type == COLLISION_NODE)
                {
                        const ContentFeatures &f = m_gamedef->ndef()->
@@ -2045,8 +2073,7 @@ void ClientEnvironment::step(float dtime)
                        int addp = itemgroup_get(f.groups, "fall_damage_add_percent");
                        pre_factor = 1.0 + (float)addp/100.0;
                }
-               float speed = (info.new_speed - info.old_speed).getLength();
-               speed *= pre_factor;
+               float speed = pre_factor * speed_diff.getLength();
                if(speed > tolerance)
                {
                        f32 damage_f = (speed - tolerance)/BS * post_factor;
@@ -2122,6 +2149,7 @@ void ClientEnvironment::step(float dtime)
                Step active objects and update lighting of them
        */
        
+       bool update_lighting = m_active_object_light_update_interval.step(dtime, 0.21);
        for(core::map<u16, ClientActiveObject*>::Iterator
                        i = m_active_objects.getIterator();
                        i.atEnd()==false; i++)
@@ -2130,7 +2158,7 @@ void ClientEnvironment::step(float dtime)
                // Step object
                obj->step(dtime, this);
 
-               if(m_active_object_light_update_interval.step(dtime, 0.21))
+               if(update_lighting)
                {
                        // Update lighting
                        u8 light = 0;
@@ -2275,8 +2303,9 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
        {
                errorstream<<"ClientEnvironment::addActiveObject():"
                                <<" id="<<id<<" type="<<type
-                               <<": SerializationError in initialize(),"
-                               <<" init_data="<<serializeJsonString(init_data)
+                               <<": SerializationError in initialize(): "
+                               <<e.what()
+                               <<": init_data="<<serializeJsonString(init_data)
                                <<std::endl;
        }
 
@@ -2294,7 +2323,7 @@ void ClientEnvironment::removeActiveObject(u16 id)
                                <<"id="<<id<<" not found"<<std::endl;
                return;
        }
-       obj->removeFromScene();
+       obj->removeFromScene(true);
        delete obj;
        m_active_objects.remove(id);
 }