]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/environment.cpp
Move hex.h to util/
[dragonfireclient.git] / src / environment.cpp
index 91f5ea2b6fe045c1a06c438f491cc3ebeb725389..bafc91c0020c6dde73db000922b91f39226c66a2 100644 (file)
@@ -36,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef SERVER
 #include "clientmap.h"
 #include "localplayer.h"
+#include "mapblock_mesh.h"
 #include "event.h"
 #endif
 #include "daynightratio.h"
@@ -54,14 +55,14 @@ Environment::Environment():
        m_enable_day_night_ratio_override(false),
        m_day_night_ratio_override(0.0f)
 {
+       m_cache_enable_shaders = g_settings->getBool("enable_shaders");
 }
 
 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);
        }
 }
@@ -87,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;
@@ -102,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;
@@ -114,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;
@@ -126,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;
@@ -138,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;
                }
@@ -157,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;
                }
@@ -175,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;
@@ -205,8 +198,7 @@ u32 Environment::getDayNightRatio()
 {
        if(m_enable_day_night_ratio_override)
                return m_day_night_ratio_override;
-       bool smooth = g_settings->getBool("enable_shaders");
-       return time_to_daynight_ratio(m_time_of_day_f*24000, smooth);
+       return time_to_daynight_ratio(m_time_of_day_f*24000, m_cache_enable_shaders);
 }
 
 void Environment::setTimeOfDaySpeed(float speed)
@@ -286,7 +278,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)
@@ -295,7 +287,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);
@@ -394,8 +386,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) {
@@ -420,7 +412,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);
@@ -443,51 +435,42 @@ void ServerEnvironment::savePlayer(const std::string &playername)
 
 Player *ServerEnvironment::loadPlayer(const std::string &playername)
 {
-       std::string players_path = m_path_world + DIR_DELIM "players";
+       std::string players_path = m_path_world + DIR_DELIM "players" DIR_DELIM;
 
        RemotePlayer *player = static_cast<RemotePlayer*>(getPlayer(playername.c_str()));
        bool newplayer = false;
-       bool foundplayer = false;
+       bool found = false;
        if (!player) {
-               player = new RemotePlayer(m_gamedef);
+               player = new RemotePlayer(m_gamedef, playername.c_str());
                newplayer = true;
        }
 
-       std::vector<fs::DirListNode> player_files = fs::GetDirListing(players_path);
-       for (u32 i = 0; i < player_files.size(); i++) {
-               if (player_files[i].dir)
-                       continue;
-               
-               // Full path to this file
-               std::string path = players_path + "/" + player_files[i].name;
-
-               // Load player to see what is its name
+       RemotePlayer testplayer(m_gamedef, "");
+       std::string path = players_path + playername;
+       for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) {
+               // Open file and deserialize
                std::ifstream is(path.c_str(), std::ios_base::binary);
                if (!is.good()) {
-                       infostream << "Failed to read " << path << std::endl;
-                       continue;
+                       return NULL;
                }
-               player->deSerialize(is, player_files[i].name);
-
-               if (!string_allowed(player->getName(), PLAYERNAME_ALLOWED_CHARS)) {
-                       infostream << "Not loading player with invalid name: "
-                                       << player->getName() << std::endl;
-                       continue;
-               }
-
-               if (player->getName() == playername) {
-                       // We found our player
-                       foundplayer = true;
+               testplayer.deSerialize(is, path);
+               is.close();
+               if (testplayer.getName() == playername) {
+                       *player = testplayer;
+                       found = true;
                        break;
                }
-
+               path = players_path + playername + itos(i);
        }
-       if (!foundplayer) {
+       if (!found) {
+               infostream << "Player file for player " << playername
+                               << " not found" << std::endl;
                return NULL;
        }
        if (newplayer) {
                addPlayer(player);
        }
+       player->setModified(false);
        return player;
 }
 
@@ -518,38 +501,29 @@ void ServerEnvironment::loadMeta()
 
        // Open file and deserialize
        std::ifstream is(path.c_str(), std::ios_base::binary);
-       if(is.good() == false)
-       {
-               infostream<<"ServerEnvironment::loadMeta(): Failed to open "
-                               <<path<<std::endl;
+       if (!is.good()) {
+               infostream << "ServerEnvironment::loadMeta(): Failed to open "
+                               << path << std::endl;
                throw SerializationError("Couldn't load env meta");
        }
 
        Settings args;
-       
-       for(;;)
-       {
-               if(is.eof())
-                       throw SerializationError
-                                       ("ServerEnvironment::loadMeta(): EnvArgsEnd not found");
-               std::string line;
-               std::getline(is, line);
-               std::string trimmedline = trim(line);
-               if(trimmedline == "EnvArgsEnd")
-                       break;
-               args.parseConfigLine(line);
+
+       if (!args.parseConfigLines(is, "EnvArgsEnd")) {
+               throw SerializationError("ServerEnvironment::loadMeta(): "
+                               "EnvArgsEnd not found!");
        }
-       
-       try{
+
+       try {
                m_game_time = args.getU64("game_time");
-       }catch(SettingNotFoundException &e){
+       } catch (SettingNotFoundException &e) {
                // Getting this is crucial, otherwise timestamps are useless
                throw SerializationError("Couldn't load env meta game_time");
        }
 
-       try{
+       try {
                m_time_of_day = args.getU64("time_of_day");
-       }catch(SettingNotFoundException &e){
+       } catch (SettingNotFoundException &e) {
                // This is not as important
                m_time_of_day = 9000;
        }
@@ -566,7 +540,7 @@ 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,
                        float dtime_s, ServerEnvironment *env,
@@ -621,10 +595,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);
                                        }
@@ -681,14 +655,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;
 
@@ -788,19 +761,26 @@ bool ServerEnvironment::setNode(v3s16 p, const MapNode &n)
 {
        INodeDefManager *ndef = m_gamedef->ndef();
        MapNode n_old = m_map->getNodeNoEx(p);
+
        // Call destructor
-       if(ndef->get(n_old).has_on_destruct)
+       if (ndef->get(n_old).has_on_destruct)
                m_script->node_on_destruct(p, n_old);
+
        // Replace node
-       bool succeeded = m_map->addNodeWithEvent(p, n);
-       if(!succeeded)
+       if (!m_map->addNodeWithEvent(p, n))
                return false;
+
+       // Update active VoxelManipulator if a mapgen thread
+       m_map->updateVManip(p);
+
        // Call post-destructor
-       if(ndef->get(n_old).has_after_destruct)
+       if (ndef->get(n_old).has_after_destruct)
                m_script->node_after_destruct(p, n_old);
+
        // Call constructor
-       if(ndef->get(n).has_on_construct)
+       if (ndef->get(n).has_on_construct)
                m_script->node_on_construct(p, n);
+
        return true;
 }
 
@@ -808,24 +788,36 @@ bool ServerEnvironment::removeNode(v3s16 p)
 {
        INodeDefManager *ndef = m_gamedef->ndef();
        MapNode n_old = m_map->getNodeNoEx(p);
+
        // Call destructor
-       if(ndef->get(n_old).has_on_destruct)
+       if (ndef->get(n_old).has_on_destruct)
                m_script->node_on_destruct(p, n_old);
+
        // Replace with air
        // This is slightly optimized compared to addNodeWithEvent(air)
-       bool succeeded = m_map->removeNodeWithEvent(p);
-       if(!succeeded)
+       if (!m_map->removeNodeWithEvent(p))
                return false;
+
+       // Update active VoxelManipulator if a mapgen thread
+       m_map->updateVManip(p);
+
        // Call post-destructor
-       if(ndef->get(n_old).has_after_destruct)
+       if (ndef->get(n_old).has_after_destruct)
                m_script->node_after_destruct(p, n_old);
+
        // Air doesn't require constructor
        return true;
 }
 
 bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n)
 {
-       return m_map->addNodeWithEvent(p, n, false);
+       if (!m_map->addNodeWithEvent(p, n, false))
+               return false;
+
+       // Update active VoxelManipulator if a mapgen thread
+       m_map->updateVManip(p);
+
+       return true;
 }
 
 std::set<u16> ServerEnvironment::getObjectsInsideRadius(v3f pos, float radius)
@@ -849,11 +841,10 @@ void ServerEnvironment::clearAllObjects()
 {
        infostream<<"ServerEnvironment::clearAllObjects(): "
                        <<"Removing all active objects"<<std::endl;
-       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;
                if(obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
                        continue;
@@ -886,15 +877,15 @@ void ServerEnvironment::clearAllObjects()
                // Id to be removed from m_active_objects
                objects_to_remove.push_back(id);
        }
+
        // 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);
        }
 
        // Get list of loaded blocks
-       std::list<v3s16> loaded_blocks;
+       std::vector<v3s16> loaded_blocks;
        infostream<<"ServerEnvironment::clearAllObjects(): "
                        <<"Listing all loaded blocks"<<std::endl;
        m_map->listAllLoadedBlocks(loaded_blocks);
@@ -903,7 +894,7 @@ void ServerEnvironment::clearAllObjects()
                        <<loaded_blocks.size()<<std::endl;
 
        // Get list of loadable blocks
-       std::list<v3s16> loadable_blocks;
+       std::vector<v3s16> loadable_blocks;
        infostream<<"ServerEnvironment::clearAllObjects(): "
                        <<"Listing all loadable blocks"<<std::endl;
        m_map->listAllLoadableBlocks(loadable_blocks);
@@ -913,9 +904,8 @@ void ServerEnvironment::clearAllObjects()
                        <<", now clearing"<<std::endl;
 
        // Grab a reference on each loaded block to avoid unloading it
-       for(std::list<v3s16>::iterator i = loaded_blocks.begin();
-                       i != loaded_blocks.end(); ++i)
-       {
+       for(std::vector<v3s16>::iterator i = loaded_blocks.begin();
+                       i != loaded_blocks.end(); ++i) {
                v3s16 p = *i;
                MapBlock *block = m_map->getBlockNoCreateNoEx(p);
                assert(block);
@@ -929,9 +919,8 @@ void ServerEnvironment::clearAllObjects()
        u32 num_blocks_checked = 0;
        u32 num_blocks_cleared = 0;
        u32 num_objs_cleared = 0;
-       for(std::list<v3s16>::iterator i = loadable_blocks.begin();
-                       i != loadable_blocks.end(); ++i)
-       {
+       for(std::vector<v3s16>::iterator i = loadable_blocks.begin();
+                       i != loadable_blocks.end(); ++i) {
                v3s16 p = *i;
                MapBlock *block = m_map->emergeBlock(p, false);
                if(!block){
@@ -967,9 +956,8 @@ void ServerEnvironment::clearAllObjects()
        m_map->unloadUnreferencedBlocks();
 
        // Drop references that were added above
-       for(std::list<v3s16>::iterator i = loaded_blocks.begin();
-                       i != loaded_blocks.end(); ++i)
-       {
+       for(std::vector<v3s16>::iterator i = loaded_blocks.begin();
+                       i != loaded_blocks.end(); ++i) {
                v3s16 p = *i;
                MapBlock *block = m_map->getBlockNoCreateNoEx(p);
                assert(block);
@@ -1010,7 +998,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;
@@ -1033,15 +1021,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);
@@ -1224,11 +1212,6 @@ void ServerEnvironment::step(float dtime)
                                i != m_active_objects.end(); ++i)
                {
                        ServerActiveObject* obj = i->second;
-                       // Remove non-peaceful mobs on peaceful mode
-                       if(g_settings->getBool("only_peaceful_mobs")){
-                               if(!obj->isPeaceful())
-                                       obj->m_removed = true;
-                       }
                        // Don't step if is to be removed or stored statically
                        if(obj->m_removed || obj->m_pending_deactivation)
                                continue;
@@ -1349,11 +1332,17 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
        inside a radius around a position
 */
 void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
+               s16 player_radius,
                std::set<u16> &current_objects,
                std::set<u16> &added_objects)
 {
        v3f pos_f = intToFloat(pos, BS);
        f32 radius_f = radius * BS;
+       f32 player_radius_f = player_radius * BS;
+
+       if (player_radius_f < 0)
+               player_radius_f = 0;
+
        /*
                Go through the object list,
                - discard m_removed objects,
@@ -1373,12 +1362,15 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
                // Discard if removed or deactivating
                if(object->m_removed || object->m_pending_deactivation)
                        continue;
-               if(object->unlimitedTransferDistance() == false){
+
+               f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
+               if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
                        // Discard if too far
-                       f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
-                       if(distance_f > radius_f)
+                       if (distance_f > player_radius_f && player_radius_f != 0)
                                continue;
-               }
+               } else if (distance_f > radius_f)
+                       continue;
+
                // Discard if already on current_objects
                std::set<u16>::iterator n;
                n = current_objects.find(id);
@@ -1394,11 +1386,17 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
        inside a radius around a position
 */
 void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
+               s16 player_radius,
                std::set<u16> &current_objects,
                std::set<u16> &removed_objects)
 {
        v3f pos_f = intToFloat(pos, BS);
        f32 radius_f = radius * BS;
+       f32 player_radius_f = player_radius * BS;
+
+       if (player_radius_f < 0)
+               player_radius_f = 0;
+
        /*
                Go through current_objects; object is removed if:
                - object is not found in m_active_objects (this is actually an
@@ -1427,19 +1425,15 @@ void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
                        continue;
                }
                
-               // If transfer distance is unlimited, don't remove
-               if(object->unlimitedTransferDistance())
-                       continue;
-
                f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
-
-               if(distance_f >= radius_f)
-               {
-                       removed_objects.insert(id);
+               if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
+                       if (distance_f <= player_radius_f || player_radius_f == 0)
+                               continue;
+               } else if (distance_f <= radius_f)
                        continue;
-               }
-               
-               // Not removed
+
+               // Object is no longer visible
+               removed_objects.insert(id);
        }
 }
 
@@ -1534,11 +1528,10 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
 */
 void ServerEnvironment::removeRemovedObjects()
 {
-       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) {
                u16 id = i->first;
                ServerActiveObject* obj = i->second;
                // This shouldn't happen but check it
@@ -1608,13 +1601,13 @@ void ServerEnvironment::removeRemovedObjects()
                // Delete
                if(obj->environmentDeletes())
                        delete obj;
+
                // Id to be removed from m_active_objects
                objects_to_remove.push_back(id);
        }
        // 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);
        }
 }
@@ -1658,10 +1651,11 @@ static void print_hexdump(std::ostream &o, const std::string &data)
 */
 void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
 {
-       if(block==NULL)
+       if(block == NULL)
                return;
+
        // Ignore if no stored objects (to not set changed flag)
-       if(block->m_static_objects.m_stored.size() == 0)
+       if(block->m_static_objects.m_stored.empty())
                return;
        verbosestream<<"ServerEnvironment::activateObjects(): "
                        <<"activating objects of block "<<PP(block->getPos())
@@ -1682,20 +1676,17 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
        }
 
        // Activate stored objects
-       std::list<StaticObject> new_stored;
+       std::vector<StaticObject> new_stored;
        for(std::list<StaticObject>::iterator
                        i = block->m_static_objects.m_stored.begin();
-                       i != block->m_static_objects.m_stored.end(); ++i)
-       {
-               /*infostream<<"Server: Creating an active object from "
-                               <<"static data"<<std::endl;*/
+                       i != block->m_static_objects.m_stored.end(); ++i) {
                StaticObject &s_obj = *i;
+
                // Create an active object from the data
                ServerActiveObject *obj = ServerActiveObject::create
-                               (s_obj.type, this, 0, s_obj.pos, s_obj.data);
+                               ((ActiveObjectType) s_obj.type, this, 0, s_obj.pos, s_obj.data);
                // If couldn't create object, store static data back.
-               if(obj==NULL)
-               {
+               if(obj == NULL) {
                        errorstream<<"ServerEnvironment::activateObjects(): "
                                        <<"failed to create active object from static object "
                                        <<"in block "<<PP(s_obj.pos/BS)
@@ -1714,10 +1705,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);
        }
@@ -1757,11 +1747,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);
                
@@ -1978,9 +1967,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);
        }
 }
@@ -2051,9 +2039,8 @@ void ClientEnvironment::addPlayer(Player *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;
@@ -2309,35 +2296,38 @@ 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);
 
                }
-               
-               // Update lighting on all players on client
-               float light = 1.0;
-               try{
-                       // Get node at head
-                       v3s16 p = player->getLightPosition();
-                       MapNode n = m_map->getNode(p);
-                       light = n.getLightBlendF1((float)getDayNightRatio()/1000, m_gamedef->ndef());
-               }
-               catch(InvalidPositionException &e){
-                       light = blend_light_f1((float)getDayNightRatio()/1000, LIGHT_SUN, 0);
-               }
-               player->light = light;
        }
-       
+
+       // Update lighting on local player (used for wield item)
+       u32 day_night_ratio = getDayNightRatio();
+       {
+               // Get node at head
+
+               // On InvalidPositionException, use this as default
+               // (day: LIGHT_SUN, night: 0)
+               MapNode node_at_lplayer(CONTENT_AIR, 0x0f, 0);
+
+               v3s16 p = lplayer->getLightPosition();
+               node_at_lplayer = m_map->getNodeNoEx(p);
+
+               u16 light = getInteriorLight(node_at_lplayer, 0, m_gamedef->ndef());
+               u8 day = light & 0xff;
+               u8 night = (light >> 8) & 0xff;
+               finalColorBlend(lplayer->light_color, day, night, day_night_ratio);
+       }
+
        /*
                Step active objects and update lighting of them
        */
@@ -2356,15 +2346,16 @@ void ClientEnvironment::step(float dtime)
                {
                        // Update lighting
                        u8 light = 0;
-                       try{
-                               // Get node at head
-                               v3s16 p = obj->getLightPosition();
-                               MapNode n = m_map->getNode(p);
-                               light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
-                       }
-                       catch(InvalidPositionException &e){
-                               light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
-                       }
+                       bool pos_ok;
+
+                       // Get node at head
+                       v3s16 p = obj->getLightPosition();
+                       MapNode n = m_map->getNodeNoEx(p, &pos_ok);
+                       if (pos_ok)
+                               light = n.getLightBlend(day_night_ratio, m_gamedef->ndef());
+                       else
+                               light = blend_light(day_night_ratio, LIGHT_SUN, 0);
+
                        obj->updateLight(light);
                }
        }
@@ -2455,15 +2446,16 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
        object->addToScene(m_smgr, m_texturesource, m_irr);
        { // Update lighting immediately
                u8 light = 0;
-               try{
-                       // Get node at head
-                       v3s16 p = object->getLightPosition();
-                       MapNode n = m_map->getNode(p);
+               bool pos_ok;
+
+               // Get node at head
+               v3s16 p = object->getLightPosition();
+               MapNode n = m_map->getNodeNoEx(p, &pos_ok);
+               if (pos_ok)
                        light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
-               }
-               catch(InvalidPositionException &e){
+               else
                        light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
-               }
+
                object->updateLight(light);
        }
        return object->getId();
@@ -2473,7 +2465,7 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
                const std::string &init_data)
 {
        ClientActiveObject* obj =
-                       ClientActiveObject::create(type, m_gamedef, this);
+                       ClientActiveObject::create((ActiveObjectType) type, m_gamedef, this);
        if(obj == NULL)
        {
                infostream<<"ClientEnvironment::addActiveObject(): "
@@ -2552,6 +2544,8 @@ void ClientEnvironment::damageLocalPlayer(u8 damage, bool handle_hp)
        assert(lplayer);
        
        if(handle_hp){
+               if (lplayer->hp == 0) // Don't damage a dead player
+                       return;
                if(lplayer->hp > damage)
                        lplayer->hp -= damage;
                else