Revert old 4BS/s walk speed for now
[oweals/minetest.git] / src / environment.cpp
index 67ea05cf60e83e9df021c594acd1559bfbca5f43..c3ff7b75a8160f1d96955c4185561021b2982432 100644 (file)
@@ -203,6 +203,22 @@ u32 Environment::getDayNightRatio()
        return time_to_daynight_ratio(m_time_of_day);
 }
 
+/*
+       ABMWithState
+*/
+
+ABMWithState::ABMWithState(ActiveBlockModifier *abm_):
+       abm(abm_),
+       timer(0)
+{
+       // Initialize timer to random value to spread processing
+       float itv = abm->getTriggerInterval();
+       itv = MYMAX(0.001, itv); // No less than 1ms
+       int minval = MYMAX(-0.51*itv, -60); // Clamp to
+       int maxval = MYMIN(0.51*itv, 60);   // +-60 seconds
+       timer = myrand_range(minval, maxval);
+}
+
 /*
        ActiveBlockList
 */
@@ -438,7 +454,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
                // Full path to this file
                std::string path = players_path + "/" + player_files[i].name;
 
-               infostream<<"Checking player file "<<path<<std::endl;
+               //infostream<<"Checking player file "<<path<<std::endl;
 
                // Load player to see what is its name
                ServerRemotePlayer testplayer(this);
@@ -459,8 +475,8 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
                                        <<testplayer.getName()<<std::endl;
                }
 
-               infostream<<"Loaded test player with name "<<testplayer.getName()
-                               <<std::endl;
+               /*infostream<<"Loaded test player with name "<<testplayer.getName()
+                               <<std::endl;*/
                
                // Search for the player
                std::string playername = testplayer.getName();
@@ -468,7 +484,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
                bool newplayer = false;
                if(player == NULL)
                {
-                       infostream<<"Is a new player"<<std::endl;
+                       //infostream<<"Is a new player"<<std::endl;
                        player = new ServerRemotePlayer(this);
                        newplayer = true;
                }
@@ -477,7 +493,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
 
                // Load player
                {
-                       infostream<<"Reading player "<<testplayer.getName()<<" from "
+                       verbosestream<<"Reading player "<<testplayer.getName()<<" from "
                                        <<path<<std::endl;
                        // Open file and deserialize
                        std::ifstream is(path.c_str(), std::ios_base::binary);
@@ -565,6 +581,7 @@ struct ActiveABM
 {
        ActiveBlockModifier *abm;
        int chance;
+       std::set<content_t> required_neighbors;
 };
 
 class ABMHandler
@@ -587,21 +604,35 @@ public:
                        float trigger_interval = abm->getTriggerInterval();
                        if(trigger_interval < 0.001)
                                trigger_interval = 0.001;
+                       float actual_interval = dtime_s;
                        if(use_timers){
                                i->timer += dtime_s;
                                if(i->timer < trigger_interval)
                                        continue;
                                i->timer -= trigger_interval;
+                               actual_interval = trigger_interval;
                        }
                        ActiveABM aabm;
                        aabm.abm = abm;
-                       float intervals = dtime_s / trigger_interval;
+                       float intervals = actual_interval / trigger_interval;
                        float chance = abm->getTriggerChance();
                        if(chance == 0)
                                chance = 1;
                        aabm.chance = 1.0 / pow((float)1.0/chance, (float)intervals);
                        if(aabm.chance == 0)
                                aabm.chance = 1;
+                       // Trigger neighbors
+                       std::set<std::string> required_neighbors_s
+                                       = abm->getRequiredNeighbors();
+                       for(std::set<std::string>::iterator
+                                       i = required_neighbors_s.begin();
+                                       i != required_neighbors_s.end(); i++){
+                               content_t c = ndef->getId(*i);
+                               if(c == CONTENT_IGNORE)
+                                       continue;
+                               aabm.required_neighbors.insert(c);
+                       }
+                       // Trigger contents
                        std::set<std::string> contents_s = abm->getTriggerContents();
                        for(std::set<std::string>::iterator
                                        i = contents_s.begin(); i != contents_s.end(); i++){
@@ -646,6 +677,29 @@ public:
                                if(myrand() % i->chance != 0)
                                        continue;
 
+                               // Check neighbors
+                               if(!i->required_neighbors.empty())
+                               {
+                                       v3s16 p1;
+                                       for(p1.X = p.X-1; p1.X <= p.X+1; p1.X++)
+                                       for(p1.Y = p.Y-1; p1.Y <= p.Y+1; p1.Y++)
+                                       for(p1.Z = p.Z-1; p1.Z <= p.Z+1; p1.Z++)
+                                       {
+                                               if(p1 == p)
+                                                       continue;
+                                               MapNode n = map->getNodeNoEx(p1);
+                                               content_t c = n.getContent();
+                                               std::set<content_t>::const_iterator k;
+                                               k = i->required_neighbors.find(c);
+                                               if(k != i->required_neighbors.end()){
+                                                       goto neighbor_found;
+                                               }
+                                       }
+                                       // No required neighbor found
+                                       continue;
+                               }
+neighbor_found:
+
                                // Find out how many objects the block contains
                                u32 active_object_count = block->m_static_objects.m_active.size();
                                // Find out how many objects this and all the neighbors contain
@@ -716,6 +770,23 @@ void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm)
        m_abms.push_back(ABMWithState(abm));
 }
 
+std::set<u16> ServerEnvironment::getObjectsInsideRadius(v3f pos, float radius)
+{
+       std::set<u16> objects;
+       for(core::map<u16, ServerActiveObject*>::Iterator
+                       i = m_active_objects.getIterator();
+                       i.atEnd()==false; i++)
+       {
+               ServerActiveObject* obj = i.getNode()->getValue();
+               u16 id = i.getNode()->getKey();
+               v3f objectpos = obj->getBasePosition();
+               if(objectpos.getDistanceFrom(pos) > radius)
+                       continue;
+               objects.insert(id);
+       }
+       return objects;
+}
+
 void ServerEnvironment::clearAllObjects()
 {
        infostream<<"ServerEnvironment::clearAllObjects(): "
@@ -726,6 +797,8 @@ void ServerEnvironment::clearAllObjects()
                        i.atEnd()==false; i++)
        {
                ServerActiveObject* obj = i.getNode()->getValue();
+               if(obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
+                       continue;
                u16 id = i.getNode()->getKey();         
                v3f objectpos = obj->getBasePosition(); 
                // Delete static object if block is loaded
@@ -817,9 +890,6 @@ void ServerEnvironment::step(float dtime)
        
        //TimeTaker timer("ServerEnv step");
 
-       // Get some settings
-       bool footprints = g_settings->getBool("footprints");
-
        /*
                Increment game time
        */
@@ -848,26 +918,6 @@ void ServerEnvironment::step(float dtime)
                        
                        // Move
                        player->move(dtime, *m_map, 100*BS);
-                       
-                       /*
-                               Add footsteps to grass
-                       */
-                       if(footprints)
-                       {
-                               // Get node that is at BS/4 under player
-                               v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
-                               try{
-                                       MapNode n = m_map->getNode(bottompos);
-                                       if(n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_GRASS"))
-                                       {
-                                               n.setContent(LEGN(m_gamedef->ndef(), "CONTENT_GRASS_FOOTSTEPS"));
-                                               m_map->setNode(bottompos, n);
-                                       }
-                               }
-                               catch(InvalidPositionException &e)
-                               {
-                               }
-                       }
                }
        }
 
@@ -1733,6 +1783,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
 
 #ifndef SERVER
 
+#include "clientsimpleobject.h"
+
 /*
        ClientEnvironment
 */
@@ -1758,6 +1810,12 @@ ClientEnvironment::~ClientEnvironment()
                delete i.getNode()->getValue();
        }
 
+       for(core::list<ClientSimpleObject*>::Iterator
+                       i = m_simple_objects.begin(); i != m_simple_objects.end(); i++)
+       {
+               delete *i;
+       }
+
        // Drop/delete map
        m_map->drop();
 }
@@ -1792,7 +1850,6 @@ void ClientEnvironment::step(float dtime)
 
        // Get some settings
        bool free_move = g_settings->getBool("free_move");
-       bool footprints = g_settings->getBool("footprints");
 
        // Get local player
        LocalPlayer *lplayer = getLocalPlayer();
@@ -1912,16 +1969,7 @@ void ClientEnvironment::step(float dtime)
                        {
                                f32 damage_f = (info.speed - tolerance)/BS*factor;
                                u16 damage = (u16)(damage_f+0.5);
-                               if(lplayer->hp > damage)
-                                       lplayer->hp -= damage;
-                               else
-                                       lplayer->hp = 0;
-
-                               ClientEnvEvent event;
-                               event.type = CEE_PLAYER_DAMAGE;
-                               event.player_damage.amount = damage;
-                               event.player_damage.send_to_server = true;
-                               m_client_event_queue.push_back(event);
+                               damageLocalPlayer(damage, true);
                        }
                }
        }
@@ -1951,11 +1999,7 @@ void ClientEnvironment::step(float dtime)
                
                if(damage_per_second != 0)
                {
-                       ClientEnvEvent event;
-                       event.type = CEE_PLAYER_DAMAGE;
-                       event.player_damage.amount = damage_per_second;
-                       event.player_damage.send_to_server = true;
-                       m_client_event_queue.push_back(event);
+                       damageLocalPlayer(damage_per_second, true);
                }
        }
        
@@ -1986,36 +2030,10 @@ void ClientEnvironment::step(float dtime)
                        MapNode n = m_map->getNode(p);
                        light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
                }
-               catch(InvalidPositionException &e) {}
-               player->updateLight(light);
-
-               /*
-                       Add footsteps to grass
-               */
-               if(footprints)
-               {
-                       // Get node that is at BS/4 under player
-                       v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
-                       try{
-                               MapNode n = m_map->getNode(bottompos);
-                               if(n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_GRASS"))
-                               {
-                                       n.setContent(LEGN(m_gamedef->ndef(), "CONTENT_GRASS_FOOTSTEPS"));
-                                       m_map->setNode(bottompos, n);
-                                       // Update mesh on client
-                                       if(m_map->mapType() == MAPTYPE_CLIENT)
-                                       {
-                                               v3s16 p_blocks = getNodeBlockPos(bottompos);
-                                               MapBlock *b = m_map->getBlockNoCreate(p_blocks);
-                                               //b->updateMesh(getDayNightRatio());
-                                               b->setMeshExpired(true);
-                                       }
-                               }
-                       }
-                       catch(InvalidPositionException &e)
-                       {
-                       }
+               catch(InvalidPositionException &e){
+                       light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
                }
+               player->updateLight(light);
        }
        
        /*
@@ -2033,7 +2051,6 @@ void ClientEnvironment::step(float dtime)
                if(m_active_object_light_update_interval.step(dtime, 0.21))
                {
                        // Update lighting
-                       //u8 light = LIGHT_MAX;
                        u8 light = 0;
                        try{
                                // Get node at head
@@ -2041,20 +2058,33 @@ void ClientEnvironment::step(float dtime)
                                MapNode n = m_map->getNode(p);
                                light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
                        }
-                       catch(InvalidPositionException &e) {}
+                       catch(InvalidPositionException &e){
+                               light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
+                       }
                        obj->updateLight(light);
                }
        }
-}
 
-void ClientEnvironment::updateMeshes(v3s16 blockpos)
-{
-       m_map->updateMeshes(blockpos, getDayNightRatio());
+       /*
+               Step and handle simple objects
+       */
+       for(core::list<ClientSimpleObject*>::Iterator
+                       i = m_simple_objects.begin(); i != m_simple_objects.end();)
+       {
+               ClientSimpleObject *simple = *i;
+               core::list<ClientSimpleObject*>::Iterator cur = i;
+               i++;
+               simple->step(dtime);
+               if(simple->m_to_be_removed){
+                       delete simple;
+                       m_simple_objects.erase(cur);
+               }
+       }
 }
-
-void ClientEnvironment::expireMeshes(bool only_daynight_diffed)
+       
+void ClientEnvironment::addSimpleObject(ClientSimpleObject *simple)
 {
-       m_map->expireMeshes(only_daynight_diffed);
+       m_simple_objects.push_back(simple);
 }
 
 ClientActiveObject* ClientEnvironment::getActiveObject(u16 id)
@@ -2132,7 +2162,9 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
                        MapNode n = m_map->getNode(p);
                        light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
                }
-               catch(InvalidPositionException &e) {}
+               catch(InvalidPositionException &e){
+                       light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
+               }
                object->updateLight(light);
        }
        return object->getId();
@@ -2160,7 +2192,7 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
 
 void ClientEnvironment::removeActiveObject(u16 id)
 {
-       infostream<<"ClientEnvironment::removeActiveObject(): "
+       verbosestream<<"ClientEnvironment::removeActiveObject(): "
                        <<"id="<<id<<std::endl;
        ClientActiveObject* obj = getActiveObject(id);
        if(obj == NULL)