aboutsummaryrefslogtreecommitdiff
path: root/src/mapgen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mapgen.cpp')
-rw-r--r--src/mapgen.cpp51
1 files changed, 40 insertions, 11 deletions
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index 36d19bfa7..29af83517 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -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);