]> git.lizzy.rs Git - minetest.git/blobdiff - src/environment.cpp
Create main menu tab "Settings" for client settings
[minetest.git] / src / environment.cpp
index 81021ad83a677b41861b64da3a06606314e76be7..cfe82fb8b537a7a82f5719060e40bc3fa72a0292 100644 (file)
@@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "nodemetadata.h"
 #include "main.h" // For g_settings, g_profiler
 #include "gamedef.h"
+#include "serverremoteplayer.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
@@ -202,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
 */
@@ -437,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);
@@ -458,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();
@@ -467,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;
                }
@@ -476,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);
@@ -491,7 +508,9 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
                }
 
                if(newplayer)
+               {
                        addPlayer(player);
+               }
        }
 }
 
@@ -562,6 +581,7 @@ struct ActiveABM
 {
        ActiveBlockModifier *abm;
        int chance;
+       std::set<content_t> required_neighbors;
 };
 
 class ABMHandler
@@ -584,21 +604,35 @@ class ABMHandler
                        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++){
@@ -643,6 +677,29 @@ class ABMHandler
                                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
@@ -713,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(): "
@@ -723,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
@@ -748,7 +824,8 @@ void ServerEnvironment::clearAllObjects()
                scriptapi_rm_object_reference(m_lua, obj);
 
                // Delete active object
-               delete obj;
+               if(obj->environmentDeletes())
+                       delete obj;
                // Id to be removed from m_active_objects
                objects_to_remove.push_back(id);
        }
@@ -1179,7 +1256,8 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
                succeeded = false;
        }
 
-       delete obj;
+       if(obj->environmentDeletes())
+               delete obj;
 
        return succeeded;
 }
@@ -1213,10 +1291,12 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
                // Discard if removed
                if(object->m_removed)
                        continue;
-               // Discard if too far
-               f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
-               if(distance_f > radius_f)
-                       continue;
+               if(object->unlimitedTransferDistance() == false){
+                       // Discard if too far
+                       f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
+                       if(distance_f > radius_f)
+                               continue;
+               }
                // Discard if already on current_objects
                core::map<u16, bool>::Node *n;
                n = current_objects.find(id);
@@ -1251,24 +1331,33 @@ void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
        {
                u16 id = i.getNode()->getKey();
                ServerActiveObject *object = getActiveObject(id);
-               if(object == NULL)
-               {
+
+               if(object == NULL){
                        infostream<<"ServerEnvironment::getRemovedActiveObjects():"
                                        <<" object in current_objects is NULL"<<std::endl;
+                       removed_objects.insert(id, false);
+                       continue;
                }
-               else if(object->m_removed == false)
+
+               if(object->m_removed)
                {
-                       f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
-                       /*infostream<<"removed == false"
-                                       <<"distance_f = "<<distance_f
-                                       <<", radius_f = "<<radius_f<<std::endl;*/
-                       if(distance_f < radius_f)
-                       {
-                               // Not removed
-                               continue;
-                       }
+                       removed_objects.insert(id, false);
+                       continue;
                }
-               removed_objects.insert(id, false);
+               
+               // 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, false);
+                       continue;
+               }
+               
+               // Not removed
        }
 }
 
@@ -1294,7 +1383,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
                {
                        errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
                                        <<"no free ids available"<<std::endl;
-                       delete object;
+                       if(object->environmentDeletes())
+                               delete object;
                        return 0;
                }
                object->setId(new_id);
@@ -1307,7 +1397,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
        {
                errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
                                <<"id is not free ("<<object->getId()<<")"<<std::endl;
-               delete object;
+               if(object->environmentDeletes())
+                       delete object;
                return 0;
        }
        /*infostream<<"ServerEnvironment::addActiveObjectRaw(): "
@@ -1320,34 +1411,38 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
                        <<m_active_objects.size()<<" active objects."
                        <<std::endl;
        
-       // Add static object to active static list of the block
-       v3f objectpos = object->getBasePosition();
-       std::string staticdata = object->getStaticData();
-       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)
-       {
-               block->m_static_objects.m_active.insert(object->getId(), s_obj);
-               object->m_static_exists = true;
-               object->m_static_block = blockpos;
-
-               if(set_changed)
-                       block->raiseModified(MOD_STATE_WRITE_NEEDED, 
-                                       "addActiveObjectRaw");
-       }
-       else{
-               errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
-                               <<"could not find block for storing id="<<object->getId()
-                               <<" statically"<<std::endl;
-       }
-       
        // Register reference in scripting api (must be done before post-init)
        scriptapi_add_object_reference(m_lua, object);
        // Post-initialize object
        object->addedToEnvironment();
+       
+       // Add static data to block
+       if(object->isStaticAllowed())
+       {
+               // Add static object to active static list of the block
+               v3f objectpos = object->getBasePosition();
+               std::string staticdata = object->getStaticData();
+               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)
+               {
+                       block->m_static_objects.m_active.insert(object->getId(), s_obj);
+                       object->m_static_exists = true;
+                       object->m_static_block = blockpos;
 
+                       if(set_changed)
+                               block->raiseModified(MOD_STATE_WRITE_NEEDED, 
+                                               "addActiveObjectRaw");
+               }
+               else{
+                       errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
+                                       <<"could not find block for storing id="<<object->getId()
+                                       <<" statically"<<std::endl;
+               }
+       }
+       
        return object->getId();
 }
 
@@ -1405,7 +1500,8 @@ void ServerEnvironment::removeRemovedObjects()
                scriptapi_rm_object_reference(m_lua, obj);
 
                // Delete
-               delete obj;
+               if(obj->environmentDeletes())
+                       delete obj;
                // Id to be removed from m_active_objects
                objects_to_remove.push_back(id);
        }
@@ -1547,18 +1643,14 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                        i.atEnd()==false; i++)
        {
                ServerActiveObject* obj = i.getNode()->getValue();
-
-               // This shouldn't happen but check it
-               if(obj == NULL)
-               {
-                       errorstream<<"NULL object found in ServerEnvironment"
-                                       <<std::endl;
-                       assert(0);
+               assert(obj);
+               
+               // Do not deactivate if static data creation not allowed
+               if(!force_delete && !obj->isStaticAllowed())
                        continue;
-               }
 
                // If pending deactivation, let removeRemovedObjects() do it
-               if(obj->m_pending_deactivation)
+               if(!force_delete && obj->m_pending_deactivation)
                        continue;
 
                u16 id = i.getNode()->getKey();         
@@ -1568,7 +1660,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
 
                // If block is active, don't remove
-               if(m_active_blocks.contains(blockpos_o))
+               if(!force_delete && m_active_blocks.contains(blockpos_o))
                        continue;
 
                verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
@@ -1582,89 +1674,94 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                        Update the static data
                */
 
-               // Create new static object
-               std::string staticdata_new = obj->getStaticData();
-               StaticObject s_obj(obj->getType(), objectpos, staticdata_new);
-               
-               bool stays_in_same_block = false;
-               bool data_changed = true;
+               if(obj->isStaticAllowed())
+               {
+                       // Create new static object
+                       std::string staticdata_new = obj->getStaticData();
+                       StaticObject s_obj(obj->getType(), objectpos, staticdata_new);
+                       
+                       bool stays_in_same_block = false;
+                       bool data_changed = true;
 
-               if(obj->m_static_exists){
-                       if(obj->m_static_block == blockpos_o)
-                               stays_in_same_block = true;
+                       if(obj->m_static_exists){
+                               if(obj->m_static_block == blockpos_o)
+                                       stays_in_same_block = true;
 
-                       MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
-                       
-                       core::map<u16, StaticObject>::Node *n =
-                                       block->m_static_objects.m_active.find(id);
-                       if(n){
-                               StaticObject static_old = n->getValue();
-
-                               float save_movem = obj->getMinimumSavedMovement();
-
-                               if(static_old.data == staticdata_new &&
-                                               (static_old.pos - objectpos).getLength() < save_movem)
-                                       data_changed = false;
-                       } else {
-                               errorstream<<"ServerEnvironment::deactivateFarObjects(): "
-                                               <<"id="<<id<<" m_static_exists=true but "
-                                               <<"static data doesn't actually exist in "
-                                               <<PP(obj->m_static_block)<<std::endl;
+                               MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
+                               
+                               core::map<u16, StaticObject>::Node *n =
+                                               block->m_static_objects.m_active.find(id);
+                               if(n){
+                                       StaticObject static_old = n->getValue();
+
+                                       float save_movem = obj->getMinimumSavedMovement();
+
+                                       if(static_old.data == staticdata_new &&
+                                                       (static_old.pos - objectpos).getLength() < save_movem)
+                                               data_changed = false;
+                               } else {
+                                       errorstream<<"ServerEnvironment::deactivateFarObjects(): "
+                                                       <<"id="<<id<<" m_static_exists=true but "
+                                                       <<"static data doesn't actually exist in "
+                                                       <<PP(obj->m_static_block)<<std::endl;
+                               }
                        }
-               }
 
-               bool shall_be_written = (!stays_in_same_block || data_changed);
-               
-               // Delete old static object
-               if(obj->m_static_exists)
-               {
-                       MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
-                       if(block)
+                       bool shall_be_written = (!stays_in_same_block || data_changed);
+                       
+                       // Delete old static object
+                       if(obj->m_static_exists)
                        {
-                               block->m_static_objects.remove(id);
-                               obj->m_static_exists = false;
-                               // Only mark block as modified if data changed considerably
-                               if(shall_be_written)
-                                       block->raiseModified(MOD_STATE_WRITE_NEEDED,
-                                                       "deactivateFarObjects: Static data "
-                                                       "changed considerably");
+                               MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
+                               if(block)
+                               {
+                                       block->m_static_objects.remove(id);
+                                       obj->m_static_exists = false;
+                                       // Only mark block as modified if data changed considerably
+                                       if(shall_be_written)
+                                               block->raiseModified(MOD_STATE_WRITE_NEEDED,
+                                                               "deactivateFarObjects: Static data "
+                                                               "changed considerably");
+                               }
                        }
-               }
 
-               // 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);
+                       // 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);
 
-               if(block)
-               {
-                       if(block->m_static_objects.m_stored.size() >= 49){
-                               errorstream<<"ServerEnv: Trying to store id="<<obj->getId()
-                                               <<" statically but block "<<PP(blockpos)
-                                               <<" already contains "
-                                               <<block->m_static_objects.m_stored.size()
-                                               <<" (over 49) objects."
-                                               <<" Forcing delete."<<std::endl;
-                               force_delete = true;
-                       } else {
-                               u16 new_id = pending_delete ? id : 0;
-                               block->m_static_objects.insert(new_id, s_obj);
-                               
-                               // Only mark block as modified if data changed considerably
-                               if(shall_be_written)
-                                       block->raiseModified(MOD_STATE_WRITE_NEEDED,
-                                                       "deactivateFarObjects: Static data "
-                                                       "changed considerably");
-                               
-                               obj->m_static_exists = true;
-                               obj->m_static_block = block->getPos();
+                       if(block)
+                       {
+                               if(block->m_static_objects.m_stored.size() >= 49){
+                                       errorstream<<"ServerEnv: Trying to store id="<<obj->getId()
+                                                       <<" statically but block "<<PP(blockpos)
+                                                       <<" already contains "
+                                                       <<block->m_static_objects.m_stored.size()
+                                                       <<" (over 49) objects."
+                                                       <<" Forcing delete."<<std::endl;
+                                       force_delete = true;
+                               } else {
+                                       u16 new_id = pending_delete ? id : 0;
+                                       block->m_static_objects.insert(new_id, s_obj);
+                                       
+                                       // Only mark block as modified if data changed considerably
+                                       if(shall_be_written)
+                                               block->raiseModified(MOD_STATE_WRITE_NEEDED,
+                                                               "deactivateFarObjects: Static data "
+                                                               "changed considerably");
+                                       
+                                       obj->m_static_exists = true;
+                                       obj->m_static_block = block->getPos();
+                               }
+                       }
+                       else{
+                               if(!force_delete){
+                                       errorstream<<"ServerEnv: Could not find or generate "
+                                                       <<"a block for storing id="<<obj->getId()
+                                                       <<" statically"<<std::endl;
+                                       continue;
+                               }
                        }
-               }
-               else{
-                       errorstream<<"ServerEnv: Could not find or generate "
-                                       <<"a block for storing id="<<obj->getId()
-                                       <<" statically"<<std::endl;
-                       continue;
                }
 
                /*
@@ -1672,7 +1769,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                        Otherwise delete it immediately.
                */
 
-               if(pending_delete)
+               if(pending_delete && !force_delete)
                {
                        verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
                                        <<"object id="<<id<<" is known by clients"
@@ -1692,7 +1789,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                scriptapi_rm_object_reference(m_lua, obj);
 
                // Delete active object
-               delete obj;
+               if(obj->environmentDeletes())
+                       delete obj;
                // Id to be removed from m_active_objects
                objects_to_remove.push_back(id);
        }
@@ -1708,19 +1806,21 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
 
 #ifndef SERVER
 
+#include "clientsimpleobject.h"
+
 /*
        ClientEnvironment
 */
 
 ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
-               ITextureSource *texturesource, IGameDef *gamedef):
+               ITextureSource *texturesource, IGameDef *gamedef,
+               IrrlichtDevice *irr):
        m_map(map),
        m_smgr(smgr),
        m_texturesource(texturesource),
-       m_gamedef(gamedef)
+       m_gamedef(gamedef),
+       m_irr(irr)
 {
-       assert(m_map);
-       assert(m_smgr);
 }
 
 ClientEnvironment::~ClientEnvironment()
@@ -1733,6 +1833,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();
 }
@@ -1887,15 +1993,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;
-                               m_client_event_queue.push_back(event);
+                               damageLocalPlayer(damage, true);
                        }
                }
        }
@@ -1925,10 +2023,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;
-                       m_client_event_queue.push_back(event);
+                       damageLocalPlayer(damage_per_second, true);
                }
        }
        
@@ -1959,7 +2054,9 @@ 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);
+               }
                player->updateLight(light);
 
                /*
@@ -2006,7 +2103,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
@@ -2014,10 +2110,28 @@ 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);
                }
        }
+
+       /*
+               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::updateMeshes(v3s16 blockpos)
@@ -2029,6 +2143,11 @@ void ClientEnvironment::expireMeshes(bool only_daynight_diffed)
 {
        m_map->expireMeshes(only_daynight_diffed);
 }
+       
+void ClientEnvironment::addSimpleObject(ClientSimpleObject *simple)
+{
+       m_simple_objects.push_back(simple);
+}
 
 ClientActiveObject* ClientEnvironment::getActiveObject(u16 id)
 {
@@ -2096,7 +2215,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
        infostream<<"ClientEnvironment::addActiveObject(): "
                        <<"added (id="<<object->getId()<<")"<<std::endl;
        m_active_objects.insert(object->getId(), object);
-       object->addToScene(m_smgr, m_texturesource);
+       object->addToScene(m_smgr, m_texturesource, m_irr);
        { // Update lighting immediately
                u8 light = 0;
                try{
@@ -2105,7 +2224,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();
@@ -2114,7 +2235,8 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
 void ClientEnvironment::addActiveObject(u16 id, u8 type,
                const std::string &init_data)
 {
-       ClientActiveObject* obj = ClientActiveObject::create(type, m_gamedef);
+       ClientActiveObject* obj =
+                       ClientActiveObject::create(type, m_gamedef, this);
        if(obj == NULL)
        {
                infostream<<"ClientEnvironment::addActiveObject(): "
@@ -2132,7 +2254,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)
@@ -2164,19 +2286,22 @@ void ClientEnvironment::processActiveObjectMessage(u16 id,
        Callbacks for activeobjects
 */
 
-void ClientEnvironment::damageLocalPlayer(u8 damage)
+void ClientEnvironment::damageLocalPlayer(u8 damage, bool handle_hp)
 {
        LocalPlayer *lplayer = getLocalPlayer();
        assert(lplayer);
-
-       if(lplayer->hp > damage)
-               lplayer->hp -= damage;
-       else
-               lplayer->hp = 0;
+       
+       if(handle_hp){
+               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 = handle_hp;
        m_client_event_queue.push_back(event);
 }