]> git.lizzy.rs Git - dragonfireclient.git/commitdiff
Mapgen: Spread both night and day light banks in spreadLight
authorkwolekr <kwolekr@minetest.net>
Tue, 29 Mar 2016 15:31:52 +0000 (11:31 -0400)
committerkwolekr <kwolekr@minetest.net>
Tue, 29 Mar 2016 20:32:30 +0000 (16:32 -0400)
src/mapgen.cpp

index 36d19bfa74f96f6f09fc0960ac7f9028d973ea10..29af835178a5016813f6d0e694e9e7b449b269aa 100644 (file)
@@ -242,18 +242,38 @@ void Mapgen::setLighting(u8 light, v3s16 nmin, v3s16 nmax)
 
 void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light)
 {
-       if (light <= 1 || !a.contains(p))
+       if (light <= 1)
                return;
 
        u32 vi = vm->m_area.index(p);
-       MapNode &nn = vm->m_data[vi];
+       if (!a.contains(vi))
+               return;
+
+       MapNode &n = vm->m_data[vi];
+
+       // Decay light in each of the banks separately
+       u8 light_day = light & 0x0F;
+       if (light_day > 0)
+               light_day -= 0x01;
 
-       light--;
-       // should probably compare masked, but doesn't seem to make a difference
-       if (light <= nn.param1 || !ndef->get(nn).light_propagates)
+       u8 light_night = light & 0xF0;
+       if (light_night > 0)
+               light_night -= 0x10;
+
+       // Bail out only if we have no more light from either bank to propogate, or
+       // we hit a solid block that light cannot pass through.
+       if ((light_day  <= (n.param1 & 0x0F) &&
+               light_night <= (n.param1 & 0xF0)) ||
+               !ndef->get(n).light_propagates)
                return;
 
-       nn.param1 = light;
+       // Since this recursive function only terminates when there is no light from
+       // either bank left, we need to take the max of both banks into account for
+       // the case where spreading has stopped for one light bank but not the other.
+       light = MYMAX(light_day, n.param1 & 0x0F) |
+                       MYMAX(light_night, n.param1 & 0xF0);
+
+       n.param1 = light;
 
        lightSpread(a, p + v3s16(0, 0, 1), light);
        lightSpread(a, p + v3s16(0, 1, 0), light);
@@ -284,6 +304,9 @@ void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax, bool propagate_shadow)
        bool block_is_underground = (water_level >= nmax.Y);
        v3s16 em = vm->m_area.getExtent();
 
+       // NOTE: Direct access to the low 4 bits of param1 is okay here because,
+       // by definition, sunlight will never be in the night lightbank.
+
        for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) {
                for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++) {
                        // see if we can get a light value from the overtop
@@ -320,15 +343,21 @@ void Mapgen::spreadLight(v3s16 nmin, v3s16 nmax)
                        u32 i = vm->m_area.index(a.MinEdge.X, y, z);
                        for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++, i++) {
                                MapNode &n = vm->m_data[i];
-                               if (n.getContent() == CONTENT_IGNORE ||
-                                       !ndef->get(n).light_propagates)
+                               if (n.getContent() == CONTENT_IGNORE)
+                                       continue;
+
+                               const ContentFeatures &cf = ndef->get(n);
+                               if (!cf.light_propagates)
                                        continue;
 
-                               u8 light_produced = ndef->get(n).light_source & 0x0F;
+                               // TODO(hmmmmm): Abstract away direct param1 accesses with a
+                               // wrapper, but something lighter than MapNode::get/setLight
+
+                               u8 light_produced = cf.light_source;
                                if (light_produced)
-                                       n.param1 = light_produced;
+                                       n.param1 = light_produced | (light_produced << 4);
 
-                               u8 light = n.param1 & 0x0F;
+                               u8 light = n.param1;
                                if (light) {
                                        lightSpread(a, v3s16(x,     y,     z + 1), light);
                                        lightSpread(a, v3s16(x,     y + 1, z    ), light);