Tooltips: Unify the tooltip[] and list[] description tooltip display functions (...
[oweals/minetest.git] / src / clientenvironment.cpp
index e831de109ee9363b463ded9f3cfc447c5459c656..cc7cb54ddcca2802bba65cdc7fa778c4a20b4537 100644 (file)
@@ -22,25 +22,30 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "clientenvironment.h"
 #include "clientsimpleobject.h"
 #include "clientmap.h"
+#include "scripting_client.h"
 #include "mapblock_mesh.h"
 #include "event.h"
 #include "collision.h"
 #include "profiler.h"
 #include "raycast.h"
 #include "voxelalgorithms.h"
+#include "settings.h"
+#include <algorithm>
 
 /*
        ClientEnvironment
 */
 
 ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
-       ITextureSource *texturesource, IGameDef *gamedef,
+       ITextureSource *texturesource, Client *client,
        IrrlichtDevice *irr):
+       Environment(client),
        m_map(map),
        m_local_player(NULL),
        m_smgr(smgr),
        m_texturesource(texturesource),
-       m_gamedef(gamedef),
+       m_client(client),
+       m_script(NULL),
        m_irr(irr)
 {
        char zero = 0;
@@ -62,6 +67,8 @@ ClientEnvironment::~ClientEnvironment()
 
        // Drop/delete map
        m_map->drop();
+
+       delete m_local_player;
 }
 
 Map & ClientEnvironment::getMap()
@@ -94,7 +101,7 @@ void ClientEnvironment::step(float dtime)
        stepTimeOfDay(dtime);
 
        // Get some settings
-       bool fly_allowed = m_gamedef->checkLocalPrivilege("fly");
+       bool fly_allowed = m_client->checkLocalPrivilege("fly");
        bool free_move = fly_allowed && g_settings->getBool("free_move");
 
        // Get local player
@@ -223,56 +230,53 @@ void ClientEnvironment::step(float dtime)
                f32 post_factor = 1; // 1 hp per node/s
                if(info.type == COLLISION_NODE)
                {
-                       const ContentFeatures &f = m_gamedef->ndef()->
+                       const ContentFeatures &f = m_client->ndef()->
                                get(m_map->getNodeNoEx(info.node_p));
                        // Determine fall damage multiplier
                        int addp = itemgroup_get(f.groups, "fall_damage_add_percent");
                        pre_factor = 1.0 + (float)addp/100.0;
                }
                float speed = pre_factor * speed_diff.getLength();
-               if(speed > tolerance)
-               {
-                       f32 damage_f = (speed - tolerance)/BS * post_factor;
-                       u16 damage = (u16)(damage_f+0.5);
-                       if(damage != 0){
+               if (speed > tolerance) {
+                       f32 damage_f = (speed - tolerance) / BS * post_factor;
+                       u8 damage = (u8)MYMIN(damage_f + 0.5, 255);
+                       if (damage != 0) {
                                damageLocalPlayer(damage, true);
                                MtEvent *e = new SimpleTriggerEvent("PlayerFallingDamage");
-                               m_gamedef->event()->put(e);
+                               m_client->event()->put(e);
                        }
                }
        }
 
-       /*
-               A quick draft of lava damage
-       */
-       if(m_lava_hurt_interval.step(dtime, 1.0))
-       {
-               v3f pf = lplayer->getPosition();
-
-               // Feet, middle and head
-               v3s16 p1 = floatToInt(pf + v3f(0, BS*0.1, 0), BS);
-               MapNode n1 = m_map->getNodeNoEx(p1);
-               v3s16 p2 = floatToInt(pf + v3f(0, BS*0.8, 0), BS);
-               MapNode n2 = m_map->getNodeNoEx(p2);
-               v3s16 p3 = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
-               MapNode n3 = m_map->getNodeNoEx(p3);
-
-               u32 damage_per_second = 0;
-               damage_per_second = MYMAX(damage_per_second,
-                       m_gamedef->ndef()->get(n1).damage_per_second);
-               damage_per_second = MYMAX(damage_per_second,
-                       m_gamedef->ndef()->get(n2).damage_per_second);
-               damage_per_second = MYMAX(damage_per_second,
-                       m_gamedef->ndef()->get(n3).damage_per_second);
-
-               if(damage_per_second != 0)
-               {
-                       damageLocalPlayer(damage_per_second, true);
-               }
+       if (m_client->moddingEnabled()) {
+               m_script->environment_step(dtime);
        }
 
        // Protocol v29 make this behaviour obsolete
-       if (((Client*) getGameDef())->getProtoVersion() < 29) {
+       if (getGameDef()->getProtoVersion() < 29) {
+               if (m_lava_hurt_interval.step(dtime, 1.0)) {
+                       v3f pf = lplayer->getPosition();
+
+                       // Feet, middle and head
+                       v3s16 p1 = floatToInt(pf + v3f(0, BS * 0.1, 0), BS);
+                       MapNode n1 = m_map->getNodeNoEx(p1);
+                       v3s16 p2 = floatToInt(pf + v3f(0, BS * 0.8, 0), BS);
+                       MapNode n2 = m_map->getNodeNoEx(p2);
+                       v3s16 p3 = floatToInt(pf + v3f(0, BS * 1.6, 0), BS);
+                       MapNode n3 = m_map->getNodeNoEx(p3);
+
+                       u32 damage_per_second = 0;
+                       damage_per_second = MYMAX(damage_per_second,
+                               m_client->ndef()->get(n1).damage_per_second);
+                       damage_per_second = MYMAX(damage_per_second,
+                               m_client->ndef()->get(n2).damage_per_second);
+                       damage_per_second = MYMAX(damage_per_second,
+                               m_client->ndef()->get(n3).damage_per_second);
+
+                       if (damage_per_second != 0)
+                               damageLocalPlayer(damage_per_second, true);
+               }
+
                /*
                        Drowning
                */
@@ -282,7 +286,7 @@ void ClientEnvironment::step(float dtime)
                        // head
                        v3s16 p = floatToInt(pf + v3f(0, BS * 1.6, 0), BS);
                        MapNode n = m_map->getNodeNoEx(p);
-                       ContentFeatures c = m_gamedef->ndef()->get(n);
+                       ContentFeatures c = m_client->ndef()->get(n);
                        u8 drowning_damage = c.drowning;
                        if (drowning_damage > 0 && lplayer->hp > 0) {
                                u16 breath = lplayer->getBreath();
@@ -306,7 +310,7 @@ void ClientEnvironment::step(float dtime)
                        // head
                        v3s16 p = floatToInt(pf + v3f(0, BS * 1.6, 0), BS);
                        MapNode n = m_map->getNodeNoEx(p);
-                       ContentFeatures c = m_gamedef->ndef()->get(n);
+                       ContentFeatures c = m_client->ndef()->get(n);
                        if (!lplayer->hp) {
                                lplayer->setBreath(11);
                        } else if (c.drowning == 0) {
@@ -332,10 +336,8 @@ void ClientEnvironment::step(float dtime)
                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);
+               u16 light = getInteriorLight(node_at_lplayer, 0, m_client->ndef());
+               final_color_blend(&lplayer->light_color, light, day_night_ratio);
        }
 
        /*
@@ -360,7 +362,7 @@ void ClientEnvironment::step(float dtime)
                        v3s16 p = obj->getLightPosition();
                        MapNode n = m_map->getNodeNoEx(p, &pos_ok);
                        if (pos_ok)
-                               light = n.getLightBlend(day_night_ratio, m_gamedef->ndef());
+                               light = n.getLightBlend(day_night_ratio, m_client->ndef());
                        else
                                light = blend_light(day_night_ratio, LIGHT_SUN, 0);
 
@@ -467,7 +469,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
                v3s16 p = object->getLightPosition();
                MapNode n = m_map->getNodeNoEx(p, &pos_ok);
                if (pos_ok)
-                       light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
+                       light = n.getLightBlend(getDayNightRatio(), m_client->ndef());
                else
                        light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
 
@@ -480,7 +482,7 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
        const std::string &init_data)
 {
        ClientActiveObject* obj =
-               ClientActiveObject::create((ActiveObjectType) type, m_gamedef, this);
+               ClientActiveObject::create((ActiveObjectType) type, m_client, this);
        if(obj == NULL)
        {
                infostream<<"ClientEnvironment::addActiveObject(): "
@@ -596,15 +598,13 @@ void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d,
        }
 }
 
-ClientEnvEvent ClientEnvironment::getClientEvent()
+ClientEnvEvent ClientEnvironment::getClientEnvEvent()
 {
-       ClientEnvEvent event;
-       if(m_client_event_queue.empty())
-               event.type = CEE_NONE;
-       else {
-               event = m_client_event_queue.front();
-               m_client_event_queue.pop();
-       }
+       FATAL_ERROR_IF(m_client_event_queue.empty(),
+                       "ClientEnvironment::getClientEnvEvent(): queue is empty");
+
+       ClientEnvEvent event = m_client_event_queue.front();
+       m_client_event_queue.pop();
        return event;
 }