Falling sand and gravel
[oweals/minetest.git] / src / environment.cpp
index d3e8fa12cbbb2dab21ae226686fa3d22eca7694c..2c5c2d2b8a572f56f7f1de8b2e36ec749d7043f8 100644 (file)
@@ -30,6 +30,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "log.h"
 #include "profiler.h"
 #include "scriptapi.h"
+#include "nodedef.h"
+#include "nodemetadata.h"
+#include "main.h" // For g_settings, g_profiler
+#include "gamedef.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
@@ -268,9 +272,11 @@ void ActiveBlockList::update(core::list<v3s16> &active_positions,
        ServerEnvironment
 */
 
-ServerEnvironment::ServerEnvironment(ServerMap *map, lua_State *L):
+ServerEnvironment::ServerEnvironment(ServerMap *map, lua_State *L,
+               IGameDef *gamedef):
        m_map(map),
        m_lua(L),
+       m_gamedef(gamedef),
        m_random_spawn_timer(3),
        m_send_recommended_timer(0),
        m_game_time(0),
@@ -310,7 +316,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
                //infostream<<"Checking player file "<<path<<std::endl;
 
                // Load player to see what is its name
-               ServerRemotePlayer testplayer;
+               ServerRemotePlayer testplayer(this);
                {
                        // Open file and deserialize
                        std::ifstream is(path.c_str(), std::ios_base::binary);
@@ -424,7 +430,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
                infostream<<"Checking player file "<<path<<std::endl;
 
                // Load player to see what is its name
-               ServerRemotePlayer testplayer;
+               ServerRemotePlayer testplayer(this);
                {
                        // Open file and deserialize
                        std::ifstream is(path.c_str(), std::ios_base::binary);
@@ -452,7 +458,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
                if(player == NULL)
                {
                        infostream<<"Is a new player"<<std::endl;
-                       player = new ServerRemotePlayer();
+                       player = new ServerRemotePlayer(this);
                        newplayer = true;
                }
 
@@ -552,9 +558,9 @@ void spawnRandomObjects(MapBlock *block)
                        MapNode n = block->getNodeNoEx(p);
                        if(n.getContent() == CONTENT_IGNORE)
                                continue;
-                       if(content_features(n).liquid_type != LIQUID_NONE)
+                       if(m_gamedef->ndef()->get(n).liquid_type != LIQUID_NONE)
                                continue;
-                       if(content_features(n).walkable)
+                       if(m_gamedef->ndef()->get(n).walkable)
                        {
                                last_node_walkable = true;
                                continue;
@@ -562,7 +568,7 @@ void spawnRandomObjects(MapBlock *block)
                        if(last_node_walkable)
                        {
                                // If block contains light information
-                               if(content_features(n).param_type == CPT_LIGHT)
+                               if(m_gamedef->ndef()->get(n).param_type == CPT_LIGHT)
                                {
                                        if(n.getLight(LIGHTBANK_DAY) <= 5)
                                        {
@@ -606,7 +612,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
        activateObjects(block);
 
        // Run node metadata
-       bool changed = block->m_node_metadata.step((float)dtime_s);
+       bool changed = block->m_node_metadata->step((float)dtime_s);
        if(changed)
        {
                MapEditEvent event;
@@ -631,15 +637,15 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
 #if 1
                // Test something:
                // Convert all mud under proper day lighting to grass
-               if(n.getContent() == CONTENT_MUD)
+               if(n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_MUD"))
                {
                        if(dtime_s > 300)
                        {
                                MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
-                               if(content_features(n_top).air_equivalent &&
-                                               n_top.getLight(LIGHTBANK_DAY) >= 13)
+                               if(m_gamedef->ndef()->get(n_top).air_equivalent &&
+                                               n_top.getLight(LIGHTBANK_DAY, m_gamedef->ndef()) >= 13)
                                {
-                                       n.setContent(CONTENT_GRASS);
+                                       n.setContent(LEGN(m_gamedef->ndef(), "CONTENT_GRASS"));
                                        m_map->addNodeWithEvent(p, n);
                                }
                        }
@@ -797,9 +803,9 @@ void ServerEnvironment::step(float dtime)
                                v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
                                try{
                                        MapNode n = m_map->getNode(bottompos);
-                                       if(n.getContent() == CONTENT_GRASS)
+                                       if(n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_GRASS"))
                                        {
-                                               n.setContent(CONTENT_GRASS_FOOTSTEPS);
+                                               n.setContent(LEGN(m_gamedef->ndef(), "CONTENT_GRASS_FOOTSTEPS"));
                                                m_map->setNode(bottompos, n);
                                        }
                                }
@@ -916,7 +922,7 @@ void ServerEnvironment::step(float dtime)
                        block->setTimestampNoChangedFlag(m_game_time);
 
                        // Run node metadata
-                       bool changed = block->m_node_metadata.step(dtime);
+                       bool changed = block->m_node_metadata->step(dtime);
                        if(changed)
                        {
                                MapEditEvent event;
@@ -1002,15 +1008,16 @@ void ServerEnvironment::step(float dtime)
                                        Test something:
                                        Convert mud under proper lighting to grass
                                */
-                               if(n.getContent() == CONTENT_MUD)
+                               if(n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_MUD"))
                                {
                                        if(myrand()%20 == 0)
                                        {
                                                MapNode n_top = m_map->getNodeNoEx(p+v3s16(0,1,0));
-                                               if(content_features(n_top).air_equivalent &&
-                                                               n_top.getLightBlend(getDayNightRatio()) >= 13)
+                                               if(m_gamedef->ndef()->get(n_top).air_equivalent &&
+                                                               n_top.getLightBlend(getDayNightRatio(),
+                                                                               m_gamedef->ndef()) >= 13)
                                                {
-                                                       n.setContent(CONTENT_GRASS);
+                                                       n.setContent(LEGN(m_gamedef->ndef(), "CONTENT_GRASS"));
                                                        m_map->addNodeWithEvent(p, n);
                                                }
                                        }
@@ -1018,14 +1025,14 @@ void ServerEnvironment::step(float dtime)
                                /*
                                        Convert grass into mud if under something else than air
                                */
-                               if(n.getContent() == CONTENT_GRASS)
+                               if(n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_GRASS"))
                                {
                                        //if(myrand()%20 == 0)
                                        {
                                                MapNode n_top = m_map->getNodeNoEx(p+v3s16(0,1,0));
-                                               if(content_features(n_top).air_equivalent == false)
+                                               if(m_gamedef->ndef()->get(n_top).air_equivalent == false)
                                                {
-                                                       n.setContent(CONTENT_MUD);
+                                                       n.setContent(LEGN(m_gamedef->ndef(), "CONTENT_MUD"));
                                                        m_map->addNodeWithEvent(p, n);
                                                }
                                        }
@@ -1033,8 +1040,8 @@ void ServerEnvironment::step(float dtime)
                                /*
                                        Rats spawn around regular trees
                                */
-                               if(n.getContent() == CONTENT_TREE ||
-                                               n.getContent() == CONTENT_JUNGLETREE)
+                               if(n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_TREE") ||
+                                               n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_JUNGLETREE"))
                                {
                                        if(myrand()%200 == 0 && active_object_count_wider == 0)
                                        {
@@ -1042,7 +1049,7 @@ void ServerEnvironment::step(float dtime)
                                                                0, myrand_range(-2, 2));
                                                MapNode n1 = m_map->getNodeNoEx(p1);
                                                MapNode n1b = m_map->getNodeNoEx(p1+v3s16(0,-1,0));
-                                               if(n1b.getContent() == CONTENT_GRASS &&
+                                               if(n1b.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_GRASS") &&
                                                                n1.getContent() == CONTENT_AIR)
                                                {
                                                        v3f pos = intToFloat(p1, BS);
@@ -1054,14 +1061,15 @@ void ServerEnvironment::step(float dtime)
                                /*
                                        Fun things spawn in caves and dungeons
                                */
-                               if(n.getContent() == CONTENT_STONE ||
-                                               n.getContent() == CONTENT_MOSSYCOBBLE)
+                               if(n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_STONE") ||
+                                               n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_MOSSYCOBBLE"))
                                {
                                        if(myrand()%200 == 0 && active_object_count_wider == 0)
                                        {
                                                v3s16 p1 = p + v3s16(0,1,0);
                                                MapNode n1a = m_map->getNodeNoEx(p1+v3s16(0,0,0));
-                                               if(n1a.getLightBlend(getDayNightRatio()) <= 3){
+                                               if(n1a.getLightBlend(getDayNightRatio(),
+                                                               m_gamedef->ndef()) <= 3){
                                                        MapNode n1b = m_map->getNodeNoEx(p1+v3s16(0,1,0));
                                                        if(n1a.getContent() == CONTENT_AIR &&
                                                                        n1b.getContent() == CONTENT_AIR)
@@ -1098,7 +1106,7 @@ void ServerEnvironment::step(float dtime)
                                /*
                                        Make trees from saplings!
                                */
-                               if(n.getContent() == CONTENT_SAPLING)
+                               if(n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_SAPLING"))
                                {
                                        if(myrand()%50 == 0)
                                        {
@@ -1111,7 +1119,8 @@ void ServerEnvironment::step(float dtime)
                                                v3s16 tree_blockp = getNodeBlockPos(tree_p);
                                                vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
                                                bool is_apple_tree = myrand()%4 == 0;
-                                               mapgen::make_tree(vmanip, tree_p, is_apple_tree);
+                                               mapgen::make_tree(vmanip, tree_p, is_apple_tree,
+                                                               m_gamedef->ndef());
                                                vmanip.blitBackAll(&modified_blocks);
 
                                                // update lighting
@@ -1141,6 +1150,11 @@ void ServerEnvironment::step(float dtime)
                }
        }
        
+       /*
+               Step script environment (run global on_step())
+       */
+       scriptapi_environment_step(m_lua, dtime);
+
        /*
                Step active objects
        */
@@ -1500,7 +1514,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
        // Register reference in scripting api (must be done before post-init)
        scriptapi_add_object_reference(m_lua, object);
        // Post-initialize object
-       object->addedToEnvironment(object->getId());
+       object->addedToEnvironment();
 
        return object->getId();
 }
@@ -1855,9 +1869,12 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
        ClientEnvironment
 */
 
-ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr):
+ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
+               ITextureSource *texturesource, IGameDef *gamedef):
        m_map(map),
-       m_smgr(smgr)
+       m_smgr(smgr),
+       m_texturesource(texturesource),
+       m_gamedef(gamedef)
 {
        assert(m_map);
        assert(m_smgr);
@@ -2056,11 +2073,11 @@ void ClientEnvironment::step(float dtime)
 
                u32 damage_per_second = 0;
                damage_per_second = MYMAX(damage_per_second,
-                               content_features(n1).damage_per_second);
+                               m_gamedef->ndef()->get(n1).damage_per_second);
                damage_per_second = MYMAX(damage_per_second,
-                               content_features(n2).damage_per_second);
+                               m_gamedef->ndef()->get(n2).damage_per_second);
                damage_per_second = MYMAX(damage_per_second,
-                               content_features(n3).damage_per_second);
+                               m_gamedef->ndef()->get(n3).damage_per_second);
                
                if(damage_per_second != 0)
                {
@@ -2096,7 +2113,7 @@ void ClientEnvironment::step(float dtime)
                        // Get node at head
                        v3s16 p = player->getLightPosition();
                        MapNode n = m_map->getNode(p);
-                       light = n.getLightBlend(getDayNightRatio());
+                       light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
                }
                catch(InvalidPositionException &e) {}
                player->updateLight(light);
@@ -2110,9 +2127,9 @@ void ClientEnvironment::step(float dtime)
                        v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
                        try{
                                MapNode n = m_map->getNode(bottompos);
-                               if(n.getContent() == CONTENT_GRASS)
+                               if(n.getContent() == LEGN(m_gamedef->ndef(), "CONTENT_GRASS"))
                                {
-                                       n.setContent(CONTENT_GRASS_FOOTSTEPS);
+                                       n.setContent(LEGN(m_gamedef->ndef(), "CONTENT_GRASS_FOOTSTEPS"));
                                        m_map->setNode(bottompos, n);
                                        // Update mesh on client
                                        if(m_map->mapType() == MAPTYPE_CLIENT)
@@ -2151,7 +2168,7 @@ void ClientEnvironment::step(float dtime)
                                // Get node at head
                                v3s16 p = obj->getLightPosition();
                                MapNode n = m_map->getNode(p);
-                               light = n.getLightBlend(getDayNightRatio());
+                               light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
                        }
                        catch(InvalidPositionException &e) {}
                        obj->updateLight(light);
@@ -2235,14 +2252,15 @@ 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);
+       // TODO: Make g_texturesource non-global
+       object->addToScene(m_smgr, m_texturesource);
        return object->getId();
 }
 
 void ClientEnvironment::addActiveObject(u16 id, u8 type,
                const std::string &init_data)
 {
-       ClientActiveObject* obj = ClientActiveObject::create(type);
+       ClientActiveObject* obj = ClientActiveObject::create(type, m_gamedef);
        if(obj == NULL)
        {
                infostream<<"ClientEnvironment::addActiveObject(): "