Faster lighting at map generation time
authorPerttu Ahola <celeron55@gmail.com>
Mon, 24 Jan 2011 14:36:58 +0000 (16:36 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Mon, 24 Jan 2011 14:36:58 +0000 (16:36 +0200)
src/defaultsettings.cpp
src/main.cpp
src/map.cpp
src/map.h
src/player.cpp
src/server.cpp
src/voxel.cpp
src/voxel.h

index 6cd242f01ae659e1802253be7d0bbd1e29aa7e3c..4046b81b96b6b61acb55b918970e1fe906da6b9a 100644 (file)
@@ -47,6 +47,7 @@ void set_default_settings()
        g_settings.setDefault("objectdata_interval", "0.2");
        g_settings.setDefault("active_object_range", "2");
        g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
+       //g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
        g_settings.setDefault("max_simultaneous_block_sends_server_total", "4");
        g_settings.setDefault("max_block_send_distance", "6");
        g_settings.setDefault("max_block_generate_distance", "6");
index 092d62988bb05a31ebadd33eb7c59306bba790fa..d2f8a6b9d559a25dbd9780a31ec55b12acf8624e 100644 (file)
@@ -259,7 +259,8 @@ TODO: Remove HMParams
 \r
 TODO: Flowing water to actually contain flow direction information\r
 \r
-TODO: Faster lighting using VoxelManipulator\r
+TODO: Remove duplicate lighting implementation from Map (leave\r
+      VoxelManipulator)\r
 \r
 Doing now:\r
 ----------\r
index 09fb154aadff189512e35360b93b8ff1b7bb9a33..bbcc0f36f0e33cb440bd25934d89ea617fe3c7de 100644 (file)
@@ -622,10 +622,13 @@ void Map::updateLighting(enum LightBank bank,
                core::map<v3s16, MapBlock*> & modified_blocks)
 {
        /*m_dout<<DTIME<<"Map::updateLighting(): "
-                       <<a_blocks.getSize()<<" blocks... ";*/
+                       <<a_blocks.size()<<" blocks."<<std::endl;*/
+       
+       //TimeTaker timer("updateLighting");
        
        // For debugging
-       bool debug=false;
+       bool debug=true;
+
        u32 count_was = modified_blocks.size();
 
        core::map<v3s16, bool> light_sources;
@@ -720,9 +723,10 @@ void Map::updateLighting(enum LightBank bank,
                        
                }
        }
-       
+
+#if 0
        {
-               //TimeTaker timer("unspreadLight");
+               TimeTaker timer("unspreadLight");
                unspreadLight(bank, unlight_from, light_sources, modified_blocks);
        }
        
@@ -741,7 +745,7 @@ void Map::updateLighting(enum LightBank bank,
        //       - Find out why it works
 
        {
-               //TimeTaker timer("spreadLight");
+               TimeTaker timer("spreadLight");
                spreadLight(bank, light_sources, modified_blocks);
        }
        
@@ -751,6 +755,36 @@ void Map::updateLighting(enum LightBank bank,
                count_was = modified_blocks.size();
                dstream<<"spreadLight modified "<<diff<<std::endl;
        }
+#endif
+       
+       {
+               //MapVoxelManipulator vmanip(this);
+
+               ManualMapVoxelManipulator vmanip(this);
+               
+               core::map<v3s16, MapBlock*>::Iterator i;
+               i = a_blocks.getIterator();
+               for(; i.atEnd() == false; i++)
+               {
+                       MapBlock *block = i.getNode()->getValue();
+                       v3s16 p = block->getPos();
+                       vmanip.initialEmerge(p - v3s16(1,1,1), p + v3s16(1,1,1));
+               }
+               {
+                       //TimeTaker timer("unSpreadLight");
+                       vmanip.unspreadLight(bank, unlight_from, light_sources);
+               }
+               {
+                       //TimeTaker timer("spreadLight");
+                       vmanip.spreadLight(bank, light_sources);
+               }
+               {
+                       //TimeTaker timer("blitBack");
+                       vmanip.blitBack(modified_blocks);
+               }
+               /*dstream<<"emerge_time="<<emerge_time<<std::endl;
+               emerge_time = 0;*/
+       }
 
        //m_dout<<"Done ("<<getTimestamp()<<")"<<std::endl;
 }
@@ -2220,7 +2254,8 @@ MapBlock * ServerMap::emergeBlock(
        }
 
        //dstream<<"Not found on disk, generating."<<std::endl;
-       //TimeTaker("emergeBlock()", g_irrlicht);
+       // 0ms
+       //TimeTaker("emergeBlock() generate");
 
        /*
                Do not generate over-limit
@@ -4138,7 +4173,10 @@ void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
 #endif
 
 #if 0
-void MapVoxelManipulator::emerge(VoxelArea a)
+/*
+       NOTE: This is slow
+*/
+void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
 {
        TimeTaker timer1("emerge", &emerge_time);
        
@@ -4185,6 +4223,9 @@ void MapVoxelManipulator::blitBack
                return;
        
        //TimeTaker timer1("blitBack");
+
+       /*dstream<<"blitBack(): m_loaded_blocks.size()="
+                       <<m_loaded_blocks.size()<<std::endl;*/
        
        /*
                Initialize block cache
@@ -4241,4 +4282,90 @@ void MapVoxelManipulator::blitBack
        }
 }
 
+ManualMapVoxelManipulator::ManualMapVoxelManipulator(Map *map):
+               MapVoxelManipulator(map)
+{
+}
+
+ManualMapVoxelManipulator::~ManualMapVoxelManipulator()
+{
+}
+
+void ManualMapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
+{
+       // Just create the area to avoid segfaults
+       VoxelManipulator::emerge(a, caller_id);
+
+       /*
+               Just create the area to avoid segfaults
+       */
+       /*addArea(a);
+       for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++)
+       for(s32 y=a.MinEdge.Y; y<=a.MaxEdge.Y; y++)
+       for(s32 x=a.MinEdge.X; x<=a.MaxEdge.X; x++)
+       {
+               s32 i = m_area.index(x,y,z);
+               // Don't touch nodes that have already been loaded
+               if(!(m_flags[i] & VOXELFLAG_NOT_LOADED))
+                       continue;
+               m_flags[i] = VOXELFLAG_INEXISTENT;
+       }*/
+}
+
+void ManualMapVoxelManipulator::initialEmerge(
+               v3s16 blockpos_min, v3s16 blockpos_max)
+{
+       TimeTaker timer1("emerge", &emerge_time);
+
+       // Units of these are MapBlocks
+       v3s16 p_min = blockpos_min;
+       v3s16 p_max = blockpos_max;
+
+       VoxelArea block_area_nodes
+                       (p_min*MAP_BLOCKSIZE, (p_max+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
+
+       addArea(block_area_nodes);
+
+       for(s32 z=p_min.Z; z<=p_max.Z; z++)
+       for(s32 y=p_min.Y; y<=p_max.Y; y++)
+       for(s32 x=p_min.X; x<=p_max.X; x++)
+       {
+               v3s16 p(x,y,z);
+               core::map<v3s16, bool>::Node *n;
+               n = m_loaded_blocks.find(p);
+               if(n != NULL)
+                       continue;
+               
+               bool block_data_inexistent = false;
+               try
+               {
+                       TimeTaker timer1("emerge load", &emerge_load_time);
+
+                       MapBlock *block = m_map->getBlockNoCreate(p);
+                       if(block->isDummy())
+                               block_data_inexistent = true;
+                       else
+                               block->copyTo(*this);
+               }
+               catch(InvalidPositionException &e)
+               {
+                       block_data_inexistent = true;
+               }
+
+               if(block_data_inexistent)
+               {
+                       VoxelArea a(p*MAP_BLOCKSIZE, (p+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
+                       // Fill with VOXELFLAG_INEXISTENT
+                       for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++)
+                       for(s32 y=a.MinEdge.Y; y<=a.MaxEdge.Y; y++)
+                       {
+                               s32 i = m_area.index(a.MinEdge.X,y,z);
+                               memset(&m_flags[i], VOXELFLAG_INEXISTENT, MAP_BLOCKSIZE);
+                       }
+               }
+
+               m_loaded_blocks.insert(p, true);
+       }
+}
+
 //END
index 3b6b169e5d2b56cdc16a6b4def42ced5565522c9..787e1240fd6d821ede30b2988c509aed32cc8152 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -523,7 +523,7 @@ public:
 
        void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
 
-private:
+protected:
        Map *m_map;
        /*
                NOTE: This might be used or not
@@ -534,5 +534,18 @@ private:
        core::map<v3s16, bool> m_loaded_blocks;
 };
 
+class ManualMapVoxelManipulator : public MapVoxelManipulator
+{
+public:
+       ManualMapVoxelManipulator(Map *map);
+       virtual ~ManualMapVoxelManipulator();
+       
+       virtual void emerge(VoxelArea a, s32 caller_id=-1);
+
+       void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
+
+protected:
+};
+
 #endif
 
index bb25015b5f4562868a65331f7b31ae4cea6e7175..8aabb030c24f84f46fd7822b813beff0bc1376f4 100644 (file)
@@ -412,8 +412,9 @@ void LocalPlayer::applyControl(float dtime)
                }
                else
                {
-                       speed += move_direction;
-                       superspeed = true;
+                       // "Turbo button"
+                       /*speed += move_direction;
+                       superspeed = true;*/
                }
        }
 
index 65e3903459903593b6371f1b9dc15bf403c2dc41..716ff77c6bfa6f1311e78d10c23003599f235683 100644 (file)
@@ -168,7 +168,7 @@ void * EmergeThread::Thread()
                                                changed_blocks,
                                                lighting_invalidated_blocks);
 
-#if 0
+#if 1
                                /*
                                        EXPERIMENTAL: Create a few other blocks too
                                */
@@ -184,6 +184,19 @@ void * EmergeThread::Thread()
                                                only_from_disk,
                                                changed_blocks,
                                                lighting_invalidated_blocks);
+#if 0
+                               map.emergeBlock(
+                                               p + v3s16(0,2,0),
+                                               only_from_disk,
+                                               changed_blocks,
+                                               lighting_invalidated_blocks);
+
+                               map.emergeBlock(
+                                               p + v3s16(0,-2,0),
+                                               only_from_disk,
+                                               changed_blocks,
+                                               lighting_invalidated_blocks);
+#endif
 #endif
                        }
 
@@ -216,23 +229,6 @@ void * EmergeThread::Thread()
                                dout_server<<std::endl;
                        }
 
-#if 0
-                       /*
-                               Update water pressure
-                       */
-
-                       m_server->UpdateBlockWaterPressure(block, modified_blocks);
-
-                       for(core::map<v3s16, MapBlock*>::Iterator i = changed_blocks.getIterator();
-                                       i.atEnd() == false; i++)
-                       {
-                               MapBlock *block = i.getNode()->getValue();
-                               m_server->UpdateBlockWaterPressure(block, modified_blocks);
-                               //v3s16 p = i.getNode()->getKey();
-                               //m_server->UpdateBlockWaterPressure(p, modified_blocks);
-                       }
-#endif
-
                        /*
                                Collect a list of blocks that have been modified in
                                addition to the fetched one.
@@ -249,7 +245,7 @@ void * EmergeThread::Thread()
                        /*dstream<<"lighting "<<lighting_invalidated_blocks.size()
                                        <<" blocks"<<std::endl;*/
                        
-                       //TimeTaker timer("** updateLighting", g_device);
+                       //TimeTaker timer("** updateLighting");
                        
                        // Update lighting without locking the environment mutex,
                        // add modified blocks to changed blocks
@@ -497,7 +493,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                        || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
                        || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
                                continue;
-
+               
+                       // If this is true, inexistent block will be made from scratch
                        bool generate = d <= d_max_gen;
                        
                        if(haxmode)
@@ -513,6 +510,35 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                                        generate = false;
                        }
 
+                       /*
+                               If block is far away, don't generate it unless it is
+                               near ground level
+                       */
+                       if(d > 4)
+                       {
+                               v2s16 p2d(p.X, p.Z);
+                               MapSector *sector = NULL;
+                               try
+                               {
+                                       sector = server->m_env.getMap().getSectorNoGenerate(p2d);
+                               }
+                               catch(InvalidPositionException &e)
+                               {
+                               }
+
+                               if(sector != NULL)
+                               {
+                                       // Get center ground height in nodes
+                                       f32 gh = sector->getGroundHeight(
+                                                       v2s16(MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2));
+                                       // Block center y in nodes
+                                       f32 y = (f32)(p.Y * MAP_BLOCKSIZE + MAP_BLOCKSIZE/2);
+                                       // If differs a lot, don't generate
+                                       if(fabs(gh - y) > MAP_BLOCKSIZE*2)
+                                               generate = false;
+                               }
+                       }
+
                        /*
                                Don't draw if not in sight
                        */
index c045c949ccfeebf95ab397f063916697152c4612..a0cc44d715967397c260c79bf04f732d68dd490d 100644 (file)
@@ -264,6 +264,395 @@ void VoxelManipulator::clearFlag(u8 flags)
                        <<volume<<" nodes"<<std::endl;*/
 }
 
+void VoxelManipulator::unspreadLight(enum LightBank bank, v3s16 p, u8 oldlight,
+               core::map<v3s16, bool> & light_sources)
+{
+       v3s16 dirs[6] = {
+               v3s16(0,0,1), // back
+               v3s16(0,1,0), // top
+               v3s16(1,0,0), // right
+               v3s16(0,0,-1), // front
+               v3s16(0,-1,0), // bottom
+               v3s16(-1,0,0), // left
+       };
+       
+       emerge(VoxelArea(p - v3s16(1,1,1), p + v3s16(1,1,1)));
+
+       // Loop through 6 neighbors
+       for(u16 i=0; i<6; i++)
+       {
+               // Get the position of the neighbor node
+               v3s16 n2pos = p + dirs[i];
+               
+               u32 n2i = m_area.index(n2pos);
+
+               if(m_flags[n2i] & VOXELFLAG_INEXISTENT)
+                       continue;
+
+               MapNode &n2 = m_data[n2i];
+               
+               /*
+                       If the neighbor is dimmer than what was specified
+                       as oldlight (the light of the previous node)
+               */
+               if(n2.getLight(bank) < oldlight)
+               {
+                       /*
+                               And the neighbor is transparent and it has some light
+                       */
+                       if(n2.light_propagates() && n2.getLight(bank) != 0)
+                       {
+                               /*
+                                       Set light to 0 and add to queue
+                               */
+
+                               u8 current_light = n2.getLight(bank);
+                               n2.setLight(bank, 0);
+                               
+                               unspreadLight(bank, n2pos, current_light, light_sources);
+                               
+                               /*
+                                       Remove from light_sources if it is there
+                                       NOTE: This doesn't happen nearly at all
+                               */
+                               /*if(light_sources.find(n2pos))
+                               {
+                                       std::cout<<"Removed from light_sources"<<std::endl;
+                                       light_sources.remove(n2pos);
+                               }*/
+                       }
+               }
+               else{
+                       light_sources.insert(n2pos, true);
+               }
+       }
+}
+
+#if 1
+/*
+       Goes recursively through the neighbours of the node.
+
+       Alters only transparent nodes.
+
+       If the lighting of the neighbour is lower than the lighting of
+       the node was (before changing it to 0 at the step before), the
+       lighting of the neighbour is set to 0 and then the same stuff
+       repeats for the neighbour.
+
+       The ending nodes of the routine are stored in light_sources.
+       This is useful when a light is removed. In such case, this
+       routine can be called for the light node and then again for
+       light_sources to re-light the area without the removed light.
+
+       values of from_nodes are lighting values.
+*/
+void VoxelManipulator::unspreadLight(enum LightBank bank,
+               core::map<v3s16, u8> & from_nodes,
+               core::map<v3s16, bool> & light_sources)
+{
+       if(from_nodes.size() == 0)
+               return;
+       
+       core::map<v3s16, u8>::Iterator j;
+       j = from_nodes.getIterator();
+
+       for(; j.atEnd() == false; j++)
+       {
+               v3s16 pos = j.getNode()->getKey();
+               
+               //MapNode &n = m_data[m_area.index(pos)];
+               
+               u8 oldlight = j.getNode()->getValue();
+
+               unspreadLight(bank, pos, oldlight, light_sources);
+       }
+}
+#endif
+
+#if 0
+/*
+       Goes recursively through the neighbours of the node.
+
+       Alters only transparent nodes.
+
+       If the lighting of the neighbour is lower than the lighting of
+       the node was (before changing it to 0 at the step before), the
+       lighting of the neighbour is set to 0 and then the same stuff
+       repeats for the neighbour.
+
+       The ending nodes of the routine are stored in light_sources.
+       This is useful when a light is removed. In such case, this
+       routine can be called for the light node and then again for
+       light_sources to re-light the area without the removed light.
+
+       values of from_nodes are lighting values.
+*/
+void VoxelManipulator::unspreadLight(enum LightBank bank,
+               core::map<v3s16, u8> & from_nodes,
+               core::map<v3s16, bool> & light_sources)
+{
+       v3s16 dirs[6] = {
+               v3s16(0,0,1), // back
+               v3s16(0,1,0), // top
+               v3s16(1,0,0), // right
+               v3s16(0,0,-1), // front
+               v3s16(0,-1,0), // bottom
+               v3s16(-1,0,0), // left
+       };
+       
+       if(from_nodes.size() == 0)
+               return;
+       
+       core::map<v3s16, u8> unlighted_nodes;
+       core::map<v3s16, u8>::Iterator j;
+       j = from_nodes.getIterator();
+
+       for(; j.atEnd() == false; j++)
+       {
+               v3s16 pos = j.getNode()->getKey();
+               
+               emerge(VoxelArea(pos - v3s16(1,1,1), pos + v3s16(1,1,1)));
+
+               //MapNode &n = m_data[m_area.index(pos)];
+               
+               u8 oldlight = j.getNode()->getValue();
+               
+               // Loop through 6 neighbors
+               for(u16 i=0; i<6; i++)
+               {
+                       // Get the position of the neighbor node
+                       v3s16 n2pos = pos + dirs[i];
+                       
+                       u32 n2i = m_area.index(n2pos);
+
+                       if(m_flags[n2i] & VOXELFLAG_INEXISTENT)
+                               continue;
+
+                       MapNode &n2 = m_data[n2i];
+                       
+                       /*
+                               If the neighbor is dimmer than what was specified
+                               as oldlight (the light of the previous node)
+                       */
+                       if(n2.getLight(bank) < oldlight)
+                       {
+                               /*
+                                       And the neighbor is transparent and it has some light
+                               */
+                               if(n2.light_propagates() && n2.getLight(bank) != 0)
+                               {
+                                       /*
+                                               Set light to 0 and add to queue
+                                       */
+
+                                       u8 current_light = n2.getLight(bank);
+                                       n2.setLight(bank, 0);
+
+                                       unlighted_nodes.insert(n2pos, current_light);
+                                       
+                                       /*
+                                               Remove from light_sources if it is there
+                                               NOTE: This doesn't happen nearly at all
+                                       */
+                                       /*if(light_sources.find(n2pos))
+                                       {
+                                               std::cout<<"Removed from light_sources"<<std::endl;
+                                               light_sources.remove(n2pos);
+                                       }*/
+                               }
+                       }
+                       else{
+                               light_sources.insert(n2pos, true);
+                       }
+               }
+       }
+
+       /*dstream<<"unspreadLight(): Changed block "
+                       <<blockchangecount<<" times"
+                       <<" for "<<from_nodes.size()<<" nodes"
+                       <<std::endl;*/
+       
+       if(unlighted_nodes.size() > 0)
+               unspreadLight(bank, unlighted_nodes, light_sources);
+}
+#endif
+
+void VoxelManipulator::spreadLight(enum LightBank bank, v3s16 p)
+{
+       const v3s16 dirs[6] = {
+               v3s16(0,0,1), // back
+               v3s16(0,1,0), // top
+               v3s16(1,0,0), // right
+               v3s16(0,0,-1), // front
+               v3s16(0,-1,0), // bottom
+               v3s16(-1,0,0), // left
+       };
+
+       emerge(VoxelArea(p - v3s16(1,1,1), p + v3s16(1,1,1)));
+
+       u32 i = m_area.index(p);
+       
+       if(m_flags[i] & VOXELFLAG_INEXISTENT)
+               return;
+
+       MapNode &n = m_data[i];
+
+       u8 oldlight = n.getLight(bank);
+       u8 newlight = diminish_light(oldlight);
+
+       // Loop through 6 neighbors
+       for(u16 i=0; i<6; i++)
+       {
+               // Get the position of the neighbor node
+               v3s16 n2pos = p + dirs[i];
+               
+               u32 n2i = m_area.index(n2pos);
+
+               if(m_flags[n2i] & VOXELFLAG_INEXISTENT)
+                       continue;
+
+               MapNode &n2 = m_data[n2i];
+               
+               /*
+                       If the neighbor is brighter than the current node,
+                       add to list (it will light up this node on its turn)
+               */
+               if(n2.getLight(bank) > undiminish_light(oldlight))
+               {
+                       spreadLight(bank, n2pos);
+               }
+               /*
+                       If the neighbor is dimmer than how much light this node
+                       would spread on it, add to list
+               */
+               if(n2.getLight(bank) < newlight)
+               {
+                       if(n2.light_propagates())
+                       {
+                               n2.setLight(bank, newlight);
+                               spreadLight(bank, n2pos);
+                       }
+               }
+       }
+}
+
+#if 1
+/*
+       Lights neighbors of from_nodes, collects all them and then
+       goes on recursively.
+*/
+void VoxelManipulator::spreadLight(enum LightBank bank,
+               core::map<v3s16, bool> & from_nodes)
+{
+       if(from_nodes.size() == 0)
+               return;
+       
+       core::map<v3s16, bool> lighted_nodes;
+       core::map<v3s16, bool>::Iterator j;
+       j = from_nodes.getIterator();
+
+       for(; j.atEnd() == false; j++)
+       {
+               v3s16 pos = j.getNode()->getKey();
+
+               spreadLight(bank, pos);
+       }
+}
+#endif
+
+#if 0
+/*
+       Lights neighbors of from_nodes, collects all them and then
+       goes on recursively.
+*/
+void VoxelManipulator::spreadLight(enum LightBank bank,
+               core::map<v3s16, bool> & from_nodes)
+{
+       const v3s16 dirs[6] = {
+               v3s16(0,0,1), // back
+               v3s16(0,1,0), // top
+               v3s16(1,0,0), // right
+               v3s16(0,0,-1), // front
+               v3s16(0,-1,0), // bottom
+               v3s16(-1,0,0), // left
+       };
+
+       if(from_nodes.size() == 0)
+               return;
+       
+       core::map<v3s16, bool> lighted_nodes;
+       core::map<v3s16, bool>::Iterator j;
+       j = from_nodes.getIterator();
+
+       for(; j.atEnd() == false; j++)
+       {
+               v3s16 pos = j.getNode()->getKey();
+
+               emerge(VoxelArea(pos - v3s16(1,1,1), pos + v3s16(1,1,1)));
+
+               u32 i = m_area.index(pos);
+               
+               if(m_flags[i] & VOXELFLAG_INEXISTENT)
+                       continue;
+
+               MapNode &n = m_data[i];
+
+               u8 oldlight = n.getLight(bank);
+               u8 newlight = diminish_light(oldlight);
+
+               // Loop through 6 neighbors
+               for(u16 i=0; i<6; i++)
+               {
+                       // Get the position of the neighbor node
+                       v3s16 n2pos = pos + dirs[i];
+                       
+                       try
+                       {
+                               u32 n2i = m_area.index(n2pos);
+
+                               if(m_flags[n2i] & VOXELFLAG_INEXISTENT)
+                                       continue;
+
+                               MapNode &n2 = m_data[n2i];
+                               
+                               /*
+                                       If the neighbor is brighter than the current node,
+                                       add to list (it will light up this node on its turn)
+                               */
+                               if(n2.getLight(bank) > undiminish_light(oldlight))
+                               {
+                                       lighted_nodes.insert(n2pos, true);
+                               }
+                               /*
+                                       If the neighbor is dimmer than how much light this node
+                                       would spread on it, add to list
+                               */
+                               if(n2.getLight(bank) < newlight)
+                               {
+                                       if(n2.light_propagates())
+                                       {
+                                               n2.setLight(bank, newlight);
+                                               lighted_nodes.insert(n2pos, true);
+                                       }
+                               }
+                       }
+                       catch(InvalidPositionException &e)
+                       {
+                               continue;
+                       }
+               }
+       }
+
+       /*dstream<<"spreadLight(): Changed block "
+                       <<blockchangecount<<" times"
+                       <<" for "<<from_nodes.size()<<" nodes"
+                       <<std::endl;*/
+       
+       if(lighted_nodes.size() > 0)
+               spreadLight(bank, lighted_nodes);
+}
+#endif
+
 #if 0
 int VoxelManipulator::getWaterPressure(v3s16 p, s16 &highest_y, int recur_count)
 {
index c377dfe7a54cc57e6ff8787f10b0138432f05ece..80d292891d61eac2e515f899eda2294644576352 100644 (file)
@@ -323,7 +323,11 @@ public:
                emerge(p);
                return !(m_flags[m_area.index(p)] & VOXELFLAG_INEXISTENT);
        }*/
-       // These are a bit slow and shouldn't be used internally
+
+       /*
+               These are a bit slow and shouldn't be used internally.
+               Use m_data[m_area.index(p)] instead.
+       */
        MapNode getNode(v3s16 p)
        {
                emerge(p);
@@ -396,7 +400,17 @@ public:
        */
 
        void clearFlag(u8 flag);
-
+       
+       void unspreadLight(enum LightBank bank, v3s16 p, u8 oldlight,
+                       core::map<v3s16, bool> & light_sources);
+       void unspreadLight(enum LightBank bank,
+                       core::map<v3s16, u8> & from_nodes,
+                       core::map<v3s16, bool> & light_sources);
+       
+       void spreadLight(enum LightBank bank, v3s16 p);
+       void spreadLight(enum LightBank bank,
+                       core::map<v3s16, bool> & from_nodes);
+       
 #if 0
        // VOXELFLAG_CHECKED2s must usually be cleared before calling
        // -1: dead end, 0-255: pressure