From 8a18d7f1ba7a5271751b7f33b012ee24eac10234 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Tue, 29 Mar 2016 11:31:52 -0400 Subject: [PATCH] Mapgen: Spread both night and day light banks in spreadLight --- src/mapgen.cpp | 55 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 13 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]; - - light--; - // should probably compare masked, but doesn't seem to make a difference - if (light <= nn.param1 || !ndef->get(nn).light_propagates) + if (!a.contains(vi)) return; - nn.param1 = light; + 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; + + 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; + + // 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; - u8 light_produced = ndef->get(n).light_source & 0x0F; - if (light_produced) - n.param1 = light_produced; + const ContentFeatures &cf = ndef->get(n); + if (!cf.light_propagates) + continue; - u8 light = n.param1 & 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 | (light_produced << 4); + + u8 light = n.param1; if (light) { lightSpread(a, v3s16(x, y, z + 1), light); lightSpread(a, v3s16(x, y + 1, z ), light);