]> git.lizzy.rs Git - minetest.git/blobdiff - src/environment.cpp
Fix various damage related bugs (client-side)
[minetest.git] / src / environment.cpp
index e805a59a5a453e75e41531fa0b8d27c06f569dec..f83414a6a2a4ebd91c1baecbe60b2d243f7cad78 100644 (file)
@@ -61,9 +61,8 @@ Environment::Environment():
 Environment::~Environment()
 {
        // Deallocate players
-       for(std::list<Player*>::iterator i = m_players.begin();
-                       i != m_players.end(); ++i)
-       {
+       for(std::vector<Player*>::iterator i = m_players.begin();
+                       i != m_players.end(); ++i) {
                delete (*i);
        }
 }
@@ -78,9 +77,9 @@ void Environment::addPlayer(Player *player)
        */
        // If peer id is non-zero, it has to be unique.
        if(player->peer_id != 0)
-               assert(getPlayer(player->peer_id) == NULL);
+               FATAL_ERROR_IF(getPlayer(player->peer_id) != NULL, "Peer id not unique");
        // Name has to be unique.
-       assert(getPlayer(player->getName()) == NULL);
+       FATAL_ERROR_IF(getPlayer(player->getName()) != NULL, "Player name not unique");
        // Add.
        m_players.push_back(player);
 }
@@ -89,7 +88,7 @@ void Environment::removePlayer(u16 peer_id)
 {
        DSTACK(__FUNCTION_NAME);
 
-       for(std::list<Player*>::iterator i = m_players.begin();
+       for(std::vector<Player*>::iterator i = m_players.begin();
                        i != m_players.end();)
        {
                Player *player = *i;
@@ -104,7 +103,7 @@ void Environment::removePlayer(u16 peer_id)
 
 void Environment::removePlayer(const char *name)
 {
-       for (std::list<Player*>::iterator it = m_players.begin();
+       for (std::vector<Player*>::iterator it = m_players.begin();
                        it != m_players.end(); ++it) {
                if (strcmp((*it)->getName(), name) == 0) {
                        delete *it;
@@ -116,9 +115,8 @@ void Environment::removePlayer(const char *name)
 
 Player * Environment::getPlayer(u16 peer_id)
 {
-       for(std::list<Player*>::iterator i = m_players.begin();
-                       i != m_players.end(); ++i)
-       {
+       for(std::vector<Player*>::iterator i = m_players.begin();
+                       i != m_players.end(); ++i) {
                Player *player = *i;
                if(player->peer_id == peer_id)
                        return player;
@@ -128,9 +126,8 @@ Player * Environment::getPlayer(u16 peer_id)
 
 Player * Environment::getPlayer(const char *name)
 {
-       for(std::list<Player*>::iterator i = m_players.begin();
-                       i != m_players.end(); ++i)
-       {
+       for(std::vector<Player*>::iterator i = m_players.begin();
+                       i != m_players.end(); ++i) {
                Player *player = *i;
                if(strcmp(player->getName(), name) == 0)
                        return player;
@@ -140,15 +137,13 @@ Player * Environment::getPlayer(const char *name)
 
 Player * Environment::getRandomConnectedPlayer()
 {
-       std::list<Player*> connected_players = getPlayers(true);
+       std::vector<Player*> connected_players = getPlayers(true);
        u32 chosen_one = myrand() % connected_players.size();
        u32 j = 0;
-       for(std::list<Player*>::iterator
+       for(std::vector<Player*>::iterator
                        i = connected_players.begin();
-                       i != connected_players.end(); ++i)
-       {
-               if(j == chosen_one)
-               {
+                       i != connected_players.end(); ++i) {
+               if(j == chosen_one) {
                        Player *player = *i;
                        return player;
                }
@@ -159,17 +154,15 @@ Player * Environment::getRandomConnectedPlayer()
 
 Player * Environment::getNearestConnectedPlayer(v3f pos)
 {
-       std::list<Player*> connected_players = getPlayers(true);
+       std::vector<Player*> connected_players = getPlayers(true);
        f32 nearest_d = 0;
        Player *nearest_player = NULL;
-       for(std::list<Player*>::iterator
+       for(std::vector<Player*>::iterator
                        i = connected_players.begin();
-                       i != connected_players.end(); ++i)
-       {
+                       i != connected_players.end(); ++i) {
                Player *player = *i;
                f32 d = player->getPosition().getDistanceFrom(pos);
-               if(d < nearest_d || nearest_player == NULL)
-               {
+               if(d < nearest_d || nearest_player == NULL) {
                        nearest_d = d;
                        nearest_player = player;
                }
@@ -177,22 +170,20 @@ Player * Environment::getNearestConnectedPlayer(v3f pos)
        return nearest_player;
 }
 
-std::list<Player*> Environment::getPlayers()
+std::vector<Player*> Environment::getPlayers()
 {
        return m_players;
 }
 
-std::list<Player*> Environment::getPlayers(bool ignore_disconnected)
+std::vector<Player*> Environment::getPlayers(bool ignore_disconnected)
 {
-       std::list<Player*> newlist;
-       for(std::list<Player*>::iterator
+       std::vector<Player*> newlist;
+       for(std::vector<Player*>::iterator
                        i = m_players.begin();
-                       i != m_players.end(); ++i)
-       {
+                       i != m_players.end(); ++i) {
                Player *player = *i;
                
-               if(ignore_disconnected)
-               {
+               if(ignore_disconnected) {
                        // Ignore disconnected players
                        if(player->peer_id == 0)
                                continue;
@@ -212,24 +203,42 @@ u32 Environment::getDayNightRatio()
 
 void Environment::setTimeOfDaySpeed(float speed)
 {
-       JMutexAutoLock(this->m_lock);
+       JMutexAutoLock(this->m_timeofday_lock);
        m_time_of_day_speed = speed;
 }
 
 float Environment::getTimeOfDaySpeed()
 {
-       JMutexAutoLock(this->m_lock);
+       JMutexAutoLock(this->m_timeofday_lock);
        float retval = m_time_of_day_speed;
        return retval;
 }
 
+void Environment::setTimeOfDay(u32 time)
+{
+       JMutexAutoLock(this->m_time_lock);
+       m_time_of_day = time;
+       m_time_of_day_f = (float)time / 24000.0;
+}
+
+u32 Environment::getTimeOfDay()
+{
+       JMutexAutoLock(this->m_time_lock);
+       u32 retval = m_time_of_day;
+       return retval;
+}
+
+float Environment::getTimeOfDayF()
+{
+       JMutexAutoLock(this->m_time_lock);
+       float retval = m_time_of_day_f;
+       return retval;
+}
+
 void Environment::stepTimeOfDay(float dtime)
 {
-       float day_speed = 0;
-       {
-               JMutexAutoLock(this->m_lock);
-               day_speed = m_time_of_day_speed;
-       }
+       // getTimeOfDaySpeed lock the value we need to prevent MT problems
+       float day_speed = getTimeOfDaySpeed();
        
        m_time_counter += dtime;
        f32 speed = day_speed * 24000./(24.*3600);
@@ -287,7 +296,7 @@ void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list)
        }
 }
 
-void ActiveBlockList::update(std::list<v3s16> &active_positions,
+void ActiveBlockList::update(std::vector<v3s16> &active_positions,
                s16 radius,
                std::set<v3s16> &blocks_removed,
                std::set<v3s16> &blocks_added)
@@ -296,7 +305,7 @@ void ActiveBlockList::update(std::list<v3s16> &active_positions,
                Create the new list
        */
        std::set<v3s16> newlist = m_forceloaded_list;
-       for(std::list<v3s16>::iterator i = active_positions.begin();
+       for(std::vector<v3s16>::iterator i = active_positions.begin();
                        i != active_positions.end(); ++i)
        {
                fillRadiusBlock(*i, radius, newlist);
@@ -373,7 +382,7 @@ ServerEnvironment::~ServerEnvironment()
        m_map->drop();
 
        // Delete ActiveBlockModifiers
-       for(std::list<ABMWithState>::iterator
+       for(std::vector<ABMWithState>::iterator
                        i = m_abms.begin(); i != m_abms.end(); ++i){
                delete i->abm;
        }
@@ -395,8 +404,8 @@ bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16
 
        //calculate normalized direction vector
        v3f normalized_vector = v3f((pos2.X - pos1.X)/distance,
-                                                               (pos2.Y - pos1.Y)/distance,
-                                                               (pos2.Z - pos1.Z)/distance);
+                               (pos2.Y - pos1.Y)/distance,
+                               (pos2.Z - pos1.Z)/distance);
 
        //find out if there's a node on path between pos1 and pos2
        for (float i = 1; i < distance; i += stepsize) {
@@ -421,7 +430,7 @@ void ServerEnvironment::saveLoadedPlayers()
        std::string players_path = m_path_world + DIR_DELIM "players";
        fs::CreateDir(players_path);
 
-       for (std::list<Player*>::iterator it = m_players.begin();
+       for (std::vector<Player*>::iterator it = m_players.begin();
                        it != m_players.end();
                        ++it) {
                RemotePlayer *player = static_cast<RemotePlayer*>(*it);
@@ -549,9 +558,9 @@ class ABMHandler
 {
 private:
        ServerEnvironment *m_env;
-       std::map<content_t, std::list<ActiveABM> > m_aabms;
+       std::map<content_t, std::vector<ActiveABM> > m_aabms;
 public:
-       ABMHandler(std::list<ABMWithState> &abms,
+       ABMHandler(std::vector<ABMWithState> &abms,
                        float dtime_s, ServerEnvironment *env,
                        bool use_timers):
                m_env(env)
@@ -559,8 +568,8 @@ class ABMHandler
                if(dtime_s < 0.001)
                        return;
                INodeDefManager *ndef = env->getGameDef()->ndef();
-               for(std::list<ABMWithState>::iterator
-                               i = abms.begin(); i != abms.end(); ++i){
+               for(std::vector<ABMWithState>::iterator
+                               i = abms.begin(); i != abms.end(); ++i) {
                        ActiveBlockModifier *abm = i->abm;
                        float trigger_interval = abm->getTriggerInterval();
                        if(trigger_interval < 0.001)
@@ -604,10 +613,10 @@ class ABMHandler
                                                k != ids.end(); k++)
                                {
                                        content_t c = *k;
-                                       std::map<content_t, std::list<ActiveABM> >::iterator j;
+                                       std::map<content_t, std::vector<ActiveABM> >::iterator j;
                                        j = m_aabms.find(c);
                                        if(j == m_aabms.end()){
-                                               std::list<ActiveABM> aabmlist;
+                                               std::vector<ActiveABM> aabmlist;
                                                m_aabms[c] = aabmlist;
                                                j = m_aabms.find(c);
                                        }
@@ -664,14 +673,13 @@ class ABMHandler
                        content_t c = n.getContent();
                        v3s16 p = p0 + block->getPosRelative();
 
-                       std::map<content_t, std::list<ActiveABM> >::iterator j;
+                       std::map<content_t, std::vector<ActiveABM> >::iterator j;
                        j = m_aabms.find(c);
                        if(j == m_aabms.end())
                                continue;
 
-                       for(std::list<ActiveABM>::iterator
-                                       i = j->second.begin(); i != j->second.end(); i++)
-                       {
+                       for(std::vector<ActiveABM>::iterator
+                                       i = j->second.begin(); i != j->second.end(); i++) {
                                if(myrand() % i->chance != 0)
                                        continue;
 
@@ -918,7 +926,7 @@ void ServerEnvironment::clearAllObjects()
                        i != loaded_blocks.end(); ++i) {
                v3s16 p = *i;
                MapBlock *block = m_map->getBlockNoCreateNoEx(p);
-               assert(block);
+               assert(block != NULL);
                block->refGrab();
        }
 
@@ -1008,7 +1016,7 @@ void ServerEnvironment::step(float dtime)
        */
        {
                ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG);
-               for(std::list<Player*>::iterator i = m_players.begin();
+               for(std::vector<Player*>::iterator i = m_players.begin();
                                i != m_players.end(); ++i)
                {
                        Player *player = *i;
@@ -1031,15 +1039,15 @@ void ServerEnvironment::step(float dtime)
                /*
                        Get player block positions
                */
-               std::list<v3s16> players_blockpos;
-               for(std::list<Player*>::iterator
+               std::vector<v3s16> players_blockpos;
+               for(std::vector<Player*>::iterator
                                i = m_players.begin();
-                               i != m_players.end(); ++i)
-               {
+                               i != m_players.end(); ++i) {
                        Player *player = *i;
                        // Ignore disconnected players
                        if(player->peer_id == 0)
                                continue;
+
                        v3s16 blockpos = getNodeBlockPos(
                                        floatToInt(player->getPosition(), BS));
                        players_blockpos.push_back(blockpos);
@@ -1174,7 +1182,7 @@ void ServerEnvironment::step(float dtime)
                                        <<") being handled"<<std::endl;*/
 
                        MapBlock *block = m_map->getBlockNoCreateNoEx(p);
-                       if(block==NULL)
+                       if(block == NULL)
                                continue;
                        
                        // Set current time as timestamp
@@ -1231,7 +1239,8 @@ void ServerEnvironment::step(float dtime)
                        while(!obj->m_messages_out.empty())
                        {
                                m_active_object_messages.push_back(
-                                               obj->m_messages_out.pop_front());
+                                               obj->m_messages_out.front());
+                               obj->m_messages_out.pop();
                        }
                }
        }
@@ -1286,7 +1295,7 @@ u16 getFreeServerActiveObjectId(
 
 u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
 {
-       assert(object);
+       assert(object); // Pre-condition
        m_added_objects++;
        u16 id = addActiveObjectRaw(object, true, 0);
        return id;
@@ -1464,7 +1473,7 @@ ActiveObjectMessage ServerEnvironment::getActiveObjectMessage()
 u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
                bool set_changed, u32 dtime_s)
 {
-       assert(object);
+       assert(object); // Pre-condition
        if(object->getId() == 0){
                u16 new_id = getFreeServerActiveObjectId(m_active_objects);
                if(new_id == 0)
@@ -1667,12 +1676,13 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
        // Ignore if no stored objects (to not set changed flag)
        if(block->m_static_objects.m_stored.empty())
                return;
+
        verbosestream<<"ServerEnvironment::activateObjects(): "
                        <<"activating objects of block "<<PP(block->getPos())
                        <<" ("<<block->m_static_objects.m_stored.size()
                        <<" objects)"<<std::endl;
        bool large_amount = (block->m_static_objects.m_stored.size() > g_settings->getU16("max_objects_per_block"));
-       if(large_amount){
+       if (large_amount) {
                errorstream<<"suspiciously large amount of objects detected: "
                                <<block->m_static_objects.m_stored.size()<<" in "
                                <<PP(block->getPos())
@@ -1686,8 +1696,8 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
        }
 
        // Activate stored objects
-       std::list<StaticObject> new_stored;
-       for(std::list<StaticObject>::iterator
+       std::vector<StaticObject> new_stored;
+       for (std::vector<StaticObject>::iterator
                        i = block->m_static_objects.m_stored.begin();
                        i != block->m_static_objects.m_stored.end(); ++i) {
                StaticObject &s_obj = *i;
@@ -1715,10 +1725,9 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
        // Clear stored list
        block->m_static_objects.m_stored.clear();
        // Add leftover failed stuff to stored list
-       for(std::list<StaticObject>::iterator
+       for(std::vector<StaticObject>::iterator
                        i = new_stored.begin();
-                       i != new_stored.end(); ++i)
-       {
+                       i != new_stored.end(); ++i) {
                StaticObject &s_obj = *i;
                block->m_static_objects.m_stored.push_back(s_obj);
        }
@@ -1758,11 +1767,10 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
 */
 void ServerEnvironment::deactivateFarObjects(bool force_delete)
 {
-       std::list<u16> objects_to_remove;
+       std::vector<u16> objects_to_remove;
        for(std::map<u16, ServerActiveObject*>::iterator
                        i = m_active_objects.begin();
-                       i != m_active_objects.end(); ++i)
-       {
+                       i != m_active_objects.end(); ++i) {
                ServerActiveObject* obj = i->second;
                assert(obj);
                
@@ -1979,9 +1987,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
        }
 
        // Remove references from m_active_objects
-       for(std::list<u16>::iterator i = objects_to_remove.begin();
-                       i != objects_to_remove.end(); ++i)
-       {
+       for(std::vector<u16>::iterator i = objects_to_remove.begin();
+                       i != objects_to_remove.end(); ++i) {
                m_active_objects.erase(*i);
        }
 }
@@ -2018,9 +2025,8 @@ ClientEnvironment::~ClientEnvironment()
                delete i->second;
        }
 
-       for(std::list<ClientSimpleObject*>::iterator
-                       i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i)
-       {
+       for(std::vector<ClientSimpleObject*>::iterator
+                       i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i) {
                delete *i;
        }
 
@@ -2045,16 +2051,16 @@ void ClientEnvironment::addPlayer(Player *player)
                It is a failure if player is local and there already is a local
                player
        */
-       assert(!(player->isLocal() == true && getLocalPlayer() != NULL));
+       FATAL_ERROR_IF(player->isLocal() == true && getLocalPlayer() != NULL,
+               "Player is local but there is already a local player");
 
        Environment::addPlayer(player);
 }
 
 LocalPlayer * ClientEnvironment::getLocalPlayer()
 {
-       for(std::list<Player*>::iterator i = m_players.begin();
-                       i != m_players.end(); ++i)
-       {
+       for(std::vector<Player*>::iterator i = m_players.begin();
+                       i != m_players.end(); ++i) {
                Player *player = *i;
                if(player->isLocal())
                        return (LocalPlayer*)player;
@@ -2077,7 +2083,7 @@ void ClientEnvironment::step(float dtime)
        LocalPlayer *lplayer = getLocalPlayer();
        assert(lplayer);
        // collision info queue
-       std::list<CollisionInfo> player_collisions;
+       std::vector<CollisionInfo> player_collisions;
        
        /*
                Get the speed the player is going
@@ -2192,10 +2198,8 @@ void ClientEnvironment::step(float dtime)
                
        //std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
        
-       for(std::list<CollisionInfo>::iterator
-                       i = player_collisions.begin();
-                       i != player_collisions.end(); ++i)
-       {
+       for(std::vector<CollisionInfo>::iterator 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
@@ -2310,16 +2314,14 @@ void ClientEnvironment::step(float dtime)
        /*
                Stuff that can be done in an arbitarily large dtime
        */
-       for(std::list<Player*>::iterator i = m_players.begin();
-                       i != m_players.end(); ++i)
-       {
+       for(std::vector<Player*>::iterator i = m_players.begin();
+                       i != m_players.end(); ++i) {
                Player *player = *i;
                
                /*
                        Handle non-local players
                */
-               if(player->isLocal() == false)
-               {
+               if(player->isLocal() == false) {
                        // Move
                        player->move(dtime, this, 100*BS);
 
@@ -2380,16 +2382,18 @@ void ClientEnvironment::step(float dtime)
                Step and handle simple objects
        */
        g_profiler->avg("CEnv: num of simple objects", m_simple_objects.size());
-       for(std::list<ClientSimpleObject*>::iterator
-                       i = m_simple_objects.begin(); i != m_simple_objects.end();)
-       {
-               ClientSimpleObject *simple = *i;
-               std::list<ClientSimpleObject*>::iterator cur = i;
-               ++i;
+       for(std::vector<ClientSimpleObject*>::iterator
+                       i = m_simple_objects.begin(); i != m_simple_objects.end();) {
+               std::vector<ClientSimpleObject*>::iterator cur = i;
+               ClientSimpleObject *simple = *cur;
+
                simple->step(dtime);
-               if(simple->m_to_be_removed){
+               if(simple->m_to_be_removed) {
                        delete simple;
-                       m_simple_objects.erase(cur);
+                       i = m_simple_objects.erase(cur);
+               }
+               else {
+                       ++i;
                }
        }
 }
@@ -2436,7 +2440,7 @@ u16 getFreeClientActiveObjectId(
 
 u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
 {
-       assert(object);
+       assert(object); // Pre-condition
        if(object->getId() == 0)
        {
                u16 new_id = getFreeClientActiveObjectId(m_active_objects);
@@ -2559,14 +2563,10 @@ void ClientEnvironment::damageLocalPlayer(u8 damage, bool handle_hp)
        LocalPlayer *lplayer = getLocalPlayer();
        assert(lplayer);
        
-       if(handle_hp){
-               if (lplayer->hp == 0) // Don't damage a dead player
-                       return;
-               if(lplayer->hp > damage)
-                       lplayer->hp -= damage;
-               else
-                       lplayer->hp = 0;
-       }
+       if (handle_hp && lplayer->hp > damage)
+               lplayer->hp -= damage;
+       else
+               lplayer->hp = 0;
 
        ClientEnvEvent event;
        event.type = CEE_PLAYER_DAMAGE;