continued.
[oweals/minetest.git] / src / mapblock.cpp
index af08cadaa45b3c870b040069690ec713dd46ed76..90ff05bd1468434066d23e51baa06dfe69b73ed6 100644 (file)
@@ -40,11 +40,14 @@ MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
        data = NULL;
        if(dummy == false)
                reallocate();
+       
+       m_spawn_timer = -10000;
 
 #ifndef SERVER
        m_mesh_expired = false;
        mesh_mutex.Init();
        mesh = NULL;
+       m_temp_mods_mutex.Init();
 #endif
 }
 
@@ -237,8 +240,8 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p,
 
        v3f zerovector = v3f(0,0,0);
        
-       u8 li = decode_light(light);
-       //u8 li = 150;
+       //u8 li = decode_light(light);
+       u8 li = light;
 
        u8 alpha = 255;
 
@@ -300,6 +303,8 @@ TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir)
                }
                if(mod.type == NODEMOD_CRACK)
                {
+                       spec.feature = TILEFEAT_CRACK;
+                       spec.param.crack.progression = mod.param;
                }
        }
        
@@ -433,14 +438,14 @@ void MapBlock::updateFastFaceRow(
                                // If node at sp (tile0) is more solid
                                if(mf == 1)
                                {
-                                       makeFastFace(tile0, light,
+                                       makeFastFace(tile0, decode_light(light),
                                                        sp, face_dir, scale,
                                                        posRelative_f, dest);
                                }
                                // If node at sp is less solid (mf == 2)
                                else
                                {
-                                       makeFastFace(tile1, light,
+                                       makeFastFace(tile1, decode_light(light),
                                                        sp+face_dir_f, -face_dir, scale,
                                                        posRelative_f, dest);
                                }
@@ -580,47 +585,52 @@ void MapBlock::updateMesh(u32 daynight_ratio)
 
                NOTE: This is the slowest part of this method.
        */
+       
+       {
+               // Lock this, as m_temp_mods will be used directly
+               JMutexAutoLock lock(m_temp_mods_mutex);
 
-       /*
-               Go through every y,z and get top faces in rows of x+
-       */
-       for(s16 y=0; y<MAP_BLOCKSIZE; y++){
-               for(s16 z=0; z<MAP_BLOCKSIZE; z++){
-                       updateFastFaceRow(daynight_ratio, posRelative_f,
-                                       v3s16(0,y,z), MAP_BLOCKSIZE,
-                                       v3s16(1,0,0), //dir
-                                       v3f  (1,0,0),
-                                       v3s16(0,1,0), //face dir
-                                       v3f  (0,1,0),
-                                       fastfaces_new);
-               }
-       }
-       /*
-               Go through every x,y and get right faces in rows of z+
-       */
-       for(s16 x=0; x<MAP_BLOCKSIZE; x++){
+               /*
+                       Go through every y,z and get top faces in rows of x+
+               */
                for(s16 y=0; y<MAP_BLOCKSIZE; y++){
-                       updateFastFaceRow(daynight_ratio, posRelative_f,
-                                       v3s16(x,y,0), MAP_BLOCKSIZE,
-                                       v3s16(0,0,1),
-                                       v3f  (0,0,1),
-                                       v3s16(1,0,0),
-                                       v3f  (1,0,0),
-                                       fastfaces_new);
+                       for(s16 z=0; z<MAP_BLOCKSIZE; z++){
+                               updateFastFaceRow(daynight_ratio, posRelative_f,
+                                               v3s16(0,y,z), MAP_BLOCKSIZE,
+                                               v3s16(1,0,0), //dir
+                                               v3f  (1,0,0),
+                                               v3s16(0,1,0), //face dir
+                                               v3f  (0,1,0),
+                                               fastfaces_new);
+                       }
                }
-       }
-       /*
-               Go through every y,z and get back faces in rows of x+
-       */
-       for(s16 z=0; z<MAP_BLOCKSIZE; z++){
-               for(s16 y=0; y<MAP_BLOCKSIZE; y++){
-                       updateFastFaceRow(daynight_ratio, posRelative_f,
-                                       v3s16(0,y,z), MAP_BLOCKSIZE,
-                                       v3s16(1,0,0),
-                                       v3f  (1,0,0),
-                                       v3s16(0,0,1),
-                                       v3f  (0,0,1),
-                                       fastfaces_new);
+               /*
+                       Go through every x,y and get right faces in rows of z+
+               */
+               for(s16 x=0; x<MAP_BLOCKSIZE; x++){
+                       for(s16 y=0; y<MAP_BLOCKSIZE; y++){
+                               updateFastFaceRow(daynight_ratio, posRelative_f,
+                                               v3s16(x,y,0), MAP_BLOCKSIZE,
+                                               v3s16(0,0,1),
+                                               v3f  (0,0,1),
+                                               v3s16(1,0,0),
+                                               v3f  (1,0,0),
+                                               fastfaces_new);
+                       }
+               }
+               /*
+                       Go through every y,z and get back faces in rows of x+
+               */
+               for(s16 z=0; z<MAP_BLOCKSIZE; z++){
+                       for(s16 y=0; y<MAP_BLOCKSIZE; y++){
+                               updateFastFaceRow(daynight_ratio, posRelative_f,
+                                               v3s16(0,y,z), MAP_BLOCKSIZE,
+                                               v3s16(1,0,0),
+                                               v3f  (1,0,0),
+                                               v3s16(0,0,1),
+                                               v3f  (0,0,1),
+                                               fastfaces_new);
+                       }
                }
        }
 
@@ -646,14 +656,31 @@ void MapBlock::updateMesh(u32 daynight_ratio)
                        
                        if(f.tile.feature == TILEFEAT_NONE)
                        {
-                               /*collector.append(g_tile_materials[f.tile.id], f.vertices, 4,
-                                               indices, 6);*/
                                collector.append(tile_material_get(f.tile.id), f.vertices, 4,
                                                indices, 6);
                        }
+                       else if(f.tile.feature == TILEFEAT_CRACK)
+                       {
+                               const char *path = tile_texture_path_get(f.tile.id);
+
+                               u16 progression = f.tile.param.crack.progression;
+
+                               std::string name = (std::string)path + "_cracked_"
+                                               + (char)('0' + progression);
+
+                               TextureMod *mod = new CrackTextureMod(progression);
+
+                               video::ITexture *texture = g_irrlicht->getTexture(
+                                               TextureSpec(name, path, mod));
+
+                               video::SMaterial material = tile_material_get(f.tile.id);
+                               material.setTexture(0, texture);
+
+                               collector.append(material, f.vertices, 4, indices, 6);
+                       }
                        else
                        {
-                               // Not implemented
+                               // No such feature
                                assert(0);
                        }
                }
@@ -661,6 +688,7 @@ void MapBlock::updateMesh(u32 daynight_ratio)
                collector.fillMesh(mesh_new);
 
                // Use VBO for mesh (this just would set this for ever buffer)
+               // This will lead to infinite memory usage because or irrlicht.
                //mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
                
                /*std::cout<<"MapBlock has "<<fastfaces_new->getSize()<<" faces "
@@ -668,19 +696,6 @@ void MapBlock::updateMesh(u32 daynight_ratio)
                                <<" materials (meshbuffers)"<<std::endl;*/
        }
 
-       /*
-               Clear temporary FastFaces
-       */
-
-       /*core::list<FastFace*>::Iterator i;
-       i = fastfaces_new->begin();
-       for(; i != fastfaces_new->end(); i++)
-       {
-               delete *i;
-       }
-       fastfaces_new->clear();
-       delete fastfaces_new;*/
-
        /*
                Add special graphics:
                - torches
@@ -688,14 +703,6 @@ void MapBlock::updateMesh(u32 daynight_ratio)
                TODO: Optimize by using same meshbuffer for same textures
        */
 
-       /*scene::ISceneManager *smgr = NULL;
-       video::IVideoDriver* driver = NULL;
-       if(g_device)
-       {
-               smgr = g_device->getSceneManager();
-               driver = smgr->getVideoDriver();
-       }*/
-                       
        for(s16 z=0; z<MAP_BLOCKSIZE; z++)
        for(s16 y=0; y<MAP_BLOCKSIZE; y++)
        for(s16 x=0; x<MAP_BLOCKSIZE; x++)
@@ -750,21 +757,17 @@ void MapBlock::updateMesh(u32 daynight_ratio)
                                        = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
                        if(dir == v3s16(0,-1,0))
                                buf->getMaterial().setTexture(0,
-                                               g_irrlicht->getTexture("../data/torch_on_floor.png"));
-                                               //g_texturecache.get("torch_on_floor"));
+                                               g_irrlicht->getTexture(porting::getDataPath("torch_on_floor.png").c_str()));
                        else if(dir == v3s16(0,1,0))
                                buf->getMaterial().setTexture(0,
-                                               g_irrlicht->getTexture("../data/torch_on_ceiling.png"));
-                                               //g_texturecache.get("torch_on_ceiling"));
+                                               g_irrlicht->getTexture(porting::getDataPath("torch_on_ceiling.png").c_str()));
                        // For backwards compatibility
                        else if(dir == v3s16(0,0,0))
                                buf->getMaterial().setTexture(0,
-                                               g_irrlicht->getTexture("../data/torch_on_floor.png"));
-                                               //g_texturecache.get("torch_on_floor"));
+                                               g_irrlicht->getTexture(porting::getDataPath("torch_on_floor.png").c_str()));
                        else
                                buf->getMaterial().setTexture(0, 
-                                               g_irrlicht->getTexture("../data/torch.png"));
-                               //buf->getMaterial().setTexture(0, g_texturecache.get("torch"));
+                                               g_irrlicht->getTexture(porting::getDataPath("torch.png").c_str()));
 
                        // Add to mesh
                        mesh_new->addMeshBuffer(buf);
@@ -858,7 +861,9 @@ void MapBlock::updateMesh(u32 daynight_ratio)
        is_underground is set.
 
        At the moment, all sunlighted nodes are added to light_sources.
-       TODO: This could be optimized.
+       - SUGG: This could be optimized
+
+       Turns sunglighted mud into grass.
 */
 bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources)
 {
@@ -878,10 +883,6 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources)
                                MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z));
                                if(n.getLight(LIGHTBANK_DAY) != LIGHT_SUN)
                                {
-                                       /*if(is_underground)
-                                       {
-                                               no_sunlight = true;
-                                       }*/
                                        no_sunlight = true;
                                }
                        }
@@ -889,15 +890,14 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources)
                        {
                                no_top_block = true;
                                
-                               // TODO: This makes over-ground roofed places sunlighted
+                               // NOTE: This makes over-ground roofed places sunlighted
                                // Assume sunlight, unless is_underground==true
                                if(is_underground)
                                {
                                        no_sunlight = true;
                                }
                                
-                               // TODO: There has to be some way to allow this behaviour
-                               // As of now, it just makes everything dark.
+                               // NOTE: As of now, it just would make everything dark.
                                // No sunlight here
                                //no_sunlight = true;
                        }
@@ -926,7 +926,15 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources)
 
                                                light_sources.insert(pos_relative + pos, true);
                                        }
-                                       else{
+                                       else
+                                       {
+                                               // Turn mud into grass
+                                               if(n.d == CONTENT_MUD)
+                                               {
+                                                       n.d = CONTENT_GRASS;
+                                               }
+
+                                               // Sunlight goes no further
                                                break;
                                        }
                                }
@@ -998,6 +1006,52 @@ void MapBlock::copyTo(VoxelManipulator &dst)
                core::array<DistanceSortedObject> &dest)
 {
 }*/
+void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio)
+{
+       /*
+               Step objects
+       */
+       m_objects.step(dtime, server, daynight_ratio);
+       
+       /*
+               Spawn some objects at random.
+
+               Use dayNightDiffed() to approximate being near ground level
+       */
+       if(m_spawn_timer < -999)
+       {
+               m_spawn_timer = 60;
+       }
+       if(dayNightDiffed() == true && getObjectCount() == 0)
+       {
+               m_spawn_timer -= dtime;
+               if(m_spawn_timer <= 0.0)
+               {
+                       m_spawn_timer += myrand() % 300;
+                       
+                       v2s16 p2d(
+                               (myrand()%(MAP_BLOCKSIZE-1))+0,
+                               (myrand()%(MAP_BLOCKSIZE-1))+0
+                       );
+
+                       s16 y = getGroundLevel(p2d);
+                       
+                       if(y >= 0)
+                       {
+                               v3s16 p(p2d.X, y+1, p2d.Y);
+
+                               if(getNode(p).d == CONTENT_AIR
+                                               && getNode(p).getLightBlend(daynight_ratio) <= 11)
+                               {
+                                       RatObject *obj = new RatObject(NULL, -1, intToFloat(p));
+                                       addObject(obj);
+                               }
+                       }
+               }
+       }
+
+       setChangedFlag();
+}
 
 
 void MapBlock::updateDayNightDiff()
@@ -1047,6 +1101,31 @@ void MapBlock::updateDayNightDiff()
        m_day_night_differs = differs;
 }
 
+s16 MapBlock::getGroundLevel(v2s16 p2d)
+{
+       if(isDummy())
+               return -3;
+       try
+       {
+               s16 y = MAP_BLOCKSIZE-1;
+               for(; y>=0; y--)
+               {
+                       if(is_ground_content(getNodeRef(p2d.X, y, p2d.Y).d))
+                       {
+                               if(y == MAP_BLOCKSIZE-1)
+                                       return -2;
+                               else
+                                       return y;
+                       }
+               }
+               return -1;
+       }
+       catch(InvalidPositionException &e)
+       {
+               return -3;
+       }
+}
+
 /*
        Serialization
 */