]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/environment.cpp
Fix key change menu a bit
[dragonfireclient.git] / src / environment.cpp
index 833ed93c2d566bf4f4ea55493a67d52418ad0097..3a294086c8ac78a6ee19b9bce7cff7a17868a76c 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
 */
@@ -564,6 +581,7 @@ struct ActiveABM
 {
        ActiveBlockModifier *abm;
        int chance;
+       std::set<content_t> required_neighbors;
 };
 
 class ABMHandler
@@ -586,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++){
@@ -645,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
@@ -715,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(): "
@@ -750,7 +822,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);
        }
@@ -1181,7 +1254,8 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
                succeeded = false;
        }
 
-       delete obj;
+       if(obj->environmentDeletes())
+               delete obj;
 
        return succeeded;
 }
@@ -1215,10 +1289,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);
@@ -1253,24 +1329,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;
+               }
+               
+               // 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;
                }
-               removed_objects.insert(id, false);
+               
+               // Not removed
        }
 }
 
@@ -1296,7 +1381,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);
@@ -1309,7 +1395,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(): "
@@ -1411,7 +1498,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);
        }
@@ -1699,7 +1787,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);
        }
@@ -1902,6 +1991,7 @@ void ClientEnvironment::step(float dtime)
                                ClientEnvEvent event;
                                event.type = CEE_PLAYER_DAMAGE;
                                event.player_damage.amount = damage;
+                               event.player_damage.send_to_server = true;
                                m_client_event_queue.push_back(event);
                        }
                }
@@ -1935,6 +2025,7 @@ void ClientEnvironment::step(float dtime)
                        ClientEnvEvent event;
                        event.type = CEE_PLAYER_DAMAGE;
                        event.player_damage.amount = damage_per_second;
+                       event.player_damage.send_to_server = true;
                        m_client_event_queue.push_back(event);
                }
        }
@@ -2172,19 +2263,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);
 }