]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/environment.cpp
Make shift the default descent control on ladders and when flying
[dragonfireclient.git] / src / environment.cpp
index 5e8f5edbaa81691fb89ce5b6cc1ecb7efb4765dd..b88f55dead838a51b25f3c0a89c50fad8e9ddde7 100644 (file)
@@ -3,16 +3,16 @@ Minetest-c55
 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License along
+You should have received a copy of the GNU Lesser General Public License along
 with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
@@ -39,8 +39,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gamedef.h"
 #ifndef SERVER
 #include "clientmap.h"
+#include "localplayer.h"
 #endif
 #include "daynightratio.h"
+#include "map.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
@@ -324,6 +326,7 @@ ServerEnvironment::ServerEnvironment(ServerMap *map, lua_State *L,
        m_emerger(emerger),
        m_random_spawn_timer(3),
        m_send_recommended_timer(0),
+       m_active_block_interval_overload_skip(0),
        m_game_time(0),
        m_game_time_fraction_counter(0)
 {
@@ -348,6 +351,17 @@ ServerEnvironment::~ServerEnvironment()
        }
 }
 
+Map & ServerEnvironment::getMap()
+{
+       return *m_map;
+}
+
+ServerMap & ServerEnvironment::getServerMap()
+{
+       return *m_map;
+}
+
+
 void ServerEnvironment::serializePlayers(const std::string &savedir)
 {
        std::string players_path = savedir + "/players";
@@ -632,13 +646,15 @@ class ABMHandler
                                i->timer -= trigger_interval;
                                actual_interval = trigger_interval;
                        }
-                       ActiveABM aabm;
-                       aabm.abm = abm;
                        float intervals = actual_interval / trigger_interval;
+                       if(intervals == 0)
+                               continue;
                        float chance = abm->getTriggerChance();
                        if(chance == 0)
                                chance = 1;
-                       aabm.chance = 1.0 / pow((float)1.0/chance, (float)intervals);
+                       ActiveABM aabm;
+                       aabm.abm = abm;
+                       aabm.chance = chance / intervals;
                        if(aabm.chance == 0)
                                aabm.chance = 1;
                        // Trigger neighbors
@@ -646,27 +662,30 @@ class ABMHandler
                                        = 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);
+                                       i != required_neighbors_s.end(); i++)
+                       {
+                               ndef->getIds(*i, aabm.required_neighbors);
                        }
                        // 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++){
-                               content_t c = ndef->getId(*i);
-                               if(c == CONTENT_IGNORE)
-                                       continue;
-                               std::map<content_t, std::list<ActiveABM> >::iterator j;
-                               j = m_aabms.find(c);
-                               if(j == m_aabms.end()){
-                                       std::list<ActiveABM> aabmlist;
-                                       m_aabms[c] = aabmlist;
+                                       i = contents_s.begin(); i != contents_s.end(); i++)
+                       {
+                               std::set<content_t> ids;
+                               ndef->getIds(*i, ids);
+                               for(std::set<content_t>::const_iterator k = ids.begin();
+                                               k != ids.end(); k++)
+                               {
+                                       content_t c = *k;
+                                       std::map<content_t, std::list<ActiveABM> >::iterator j;
                                        j = m_aabms.find(c);
+                                       if(j == m_aabms.end()){
+                                               std::list<ActiveABM> aabmlist;
+                                               m_aabms[c] = aabmlist;
+                                               j = m_aabms.find(c);
+                                       }
+                                       j->second.push_back(aabm);
                                }
-                               j->second.push_back(aabm);
                        }
                }
        }
@@ -767,17 +786,18 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
        // Activate stored objects
        activateObjects(block);
 
-       // Run node metadata
-       bool changed = block->m_node_metadata->step((float)dtime_s);
-       if(changed)
-       {
-               MapEditEvent event;
-               event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
-               event.p = block->getPos();
-               m_map->dispatchEvent(&event);
-
-               block->raiseModified(MOD_STATE_WRITE_NEEDED,
-                               "node metadata modified in activateBlock");
+       // Run node timers
+       std::map<v3s16, NodeTimer> elapsed_timers =
+               block->m_node_timers.step((float)dtime_s);
+       if(!elapsed_timers.empty()){
+               MapNode n;
+               for(std::map<v3s16, NodeTimer>::iterator
+                               i = elapsed_timers.begin();
+                               i != elapsed_timers.end(); i++){
+                       n = block->getNodeNoEx(i->first);
+                       if(scriptapi_node_on_timer(m_lua,i->first,n,i->second.elapsed))
+                               block->setNodeTimer(i->first,NodeTimer(i->second.timeout,0));
+               }
        }
 
        /* Handle ActiveBlockModifiers */
@@ -1058,24 +1078,31 @@ void ServerEnvironment::step(float dtime)
                                block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD,
                                                "Timestamp older than 60s (step)");
 
-                       // Run node metadata
-                       bool changed = block->m_node_metadata->step(dtime);
-                       if(changed)
-                       {
-                               MapEditEvent event;
-                               event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
-                               event.p = p;
-                               m_map->dispatchEvent(&event);
-
-                               block->raiseModified(MOD_STATE_WRITE_NEEDED,
-                                               "node metadata modified in step");
+                       // Run node timers
+                       std::map<v3s16, NodeTimer> elapsed_timers =
+                               block->m_node_timers.step((float)dtime);
+                       if(!elapsed_timers.empty()){
+                               MapNode n;
+                               for(std::map<v3s16, NodeTimer>::iterator
+                                               i = elapsed_timers.begin();
+                                               i != elapsed_timers.end(); i++){
+                                       n = block->getNodeNoEx(i->first);
+                                       p = i->first + block->getPosRelative();
+                                       if(scriptapi_node_on_timer(m_lua,p,n,i->second.elapsed))
+                                               block->setNodeTimer(i->first,NodeTimer(i->second.timeout,0));
+                               }
                        }
                }
        }
        
        const float abm_interval = 1.0;
        if(m_active_block_modifier_interval.step(dtime, abm_interval))
-       {
+       do{ // breakable
+               if(m_active_block_interval_overload_skip > 0){
+                       ScopeProfiler sp(g_profiler, "SEnv: ABM overload skips");
+                       m_active_block_interval_overload_skip--;
+                       break;
+               }
                ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg /1s", SPT_AVG);
                TimeTaker timer("modify in active blocks");
                
@@ -1108,8 +1135,9 @@ void ServerEnvironment::step(float dtime)
                        infostream<<"WARNING: active block modifiers took "
                                        <<time_ms<<"ms (longer than "
                                        <<max_time_ms<<"ms)"<<std::endl;
+                       m_active_block_interval_overload_skip = (time_ms / max_time_ms) + 1;
                }
-       }
+       }while(0);
        
        /*
                Step script environment (run global on_step())
@@ -1742,6 +1770,15 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
                                        force_delete = true;
                                } else {
                                        u16 new_id = pending_delete ? id : 0;
+                                       // If static counterpart already exists, remove it first.
+                                       // This shouldn't happen, but happens rarely for some
+                                       // unknown reason. Unsuccessful attempts have been made to
+                                       // find said reason.
+                                       if(new_id && block->m_static_objects.m_active.find(new_id)){
+                                               infostream<<"ServerEnv: WARNING: Performing hack #83274"
+                                                               <<std::endl;
+                                               block->m_static_objects.remove(new_id);
+                                       }
                                        block->m_static_objects.insert(new_id, s_obj);
                                        
                                        // Only mark block as modified if data changed considerably
@@ -1885,7 +1922,8 @@ void ClientEnvironment::step(float dtime)
        stepTimeOfDay(dtime);
 
        // Get some settings
-       bool free_move = g_settings->getBool("free_move");
+       bool fly_allowed = m_gamedef->checkLocalPrivilege("fly");
+       bool free_move = fly_allowed && g_settings->getBool("free_move");
 
        // Get local player
        LocalPlayer *lplayer = getLocalPlayer();
@@ -1999,13 +2037,15 @@ void ClientEnvironment::step(float dtime)
                if(info.t == COLLISION_FALL)
                {
                        //f32 tolerance = BS*10; // 2 without damage
-                       f32 tolerance = BS*12; // 3 without damage
+                       //f32 tolerance = BS*12; // 3 without damage
+                       f32 tolerance = BS*14; // 5 without damage
                        f32 factor = 1;
                        if(info.speed > tolerance)
                        {
                                f32 damage_f = (info.speed - tolerance)/BS*factor;
                                u16 damage = (u16)(damage_f+0.5);
-                               damageLocalPlayer(damage, true);
+                               if(damage != 0)
+                                       damageLocalPlayer(damage, true);
                        }
                }
        }