@@ -242,18 +242,38 @@ void Mapgen::setLighting(u8 light, v3s16 nmin, v3s16 nmax)
242
242
243
243
void Mapgen::lightSpread (VoxelArea &a, v3s16 p, u8 light)
244
244
{
245
- if (light <= 1 || !a. contains (p) )
245
+ if (light <= 1 )
246
246
return ;
247
247
248
248
u32 vi = vm->m_area .index (p);
249
- MapNode &nn = vm->m_data [vi];
249
+ if (!a.contains (vi))
250
+ return ;
251
+
252
+ MapNode &n = vm->m_data [vi];
253
+
254
+ // Decay light in each of the banks separately
255
+ u8 light_day = light & 0x0F ;
256
+ if (light_day > 0 )
257
+ light_day -= 0x01 ;
250
258
251
- light--;
252
- // should probably compare masked, but doesn't seem to make a difference
253
- if (light <= nn.param1 || !ndef->get (nn).light_propagates )
259
+ u8 light_night = light & 0xF0 ;
260
+ if (light_night > 0 )
261
+ light_night -= 0x10 ;
262
+
263
+ // Bail out only if we have no more light from either bank to propogate, or
264
+ // we hit a solid block that light cannot pass through.
265
+ if ((light_day <= (n.param1 & 0x0F ) &&
266
+ light_night <= (n.param1 & 0xF0 )) ||
267
+ !ndef->get (n).light_propagates )
254
268
return ;
255
269
256
- nn.param1 = light;
270
+ // Since this recursive function only terminates when there is no light from
271
+ // either bank left, we need to take the max of both banks into account for
272
+ // the case where spreading has stopped for one light bank but not the other.
273
+ light = MYMAX (light_day, n.param1 & 0x0F ) |
274
+ MYMAX (light_night, n.param1 & 0xF0 );
275
+
276
+ n.param1 = light;
257
277
258
278
lightSpread (a, p + v3s16 (0 , 0 , 1 ), light);
259
279
lightSpread (a, p + v3s16 (0 , 1 , 0 ), light);
@@ -284,6 +304,9 @@ void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax, bool propagate_shadow)
284
304
bool block_is_underground = (water_level >= nmax.Y );
285
305
v3s16 em = vm->m_area .getExtent ();
286
306
307
+ // NOTE: Direct access to the low 4 bits of param1 is okay here because,
308
+ // by definition, sunlight will never be in the night lightbank.
309
+
287
310
for (int z = a.MinEdge .Z ; z <= a.MaxEdge .Z ; z++) {
288
311
for (int x = a.MinEdge .X ; x <= a.MaxEdge .X ; x++) {
289
312
// see if we can get a light value from the overtop
@@ -320,15 +343,21 @@ void Mapgen::spreadLight(v3s16 nmin, v3s16 nmax)
320
343
u32 i = vm->m_area .index (a.MinEdge .X , y, z);
321
344
for (int x = a.MinEdge .X ; x <= a.MaxEdge .X ; x++, i++) {
322
345
MapNode &n = vm->m_data [i];
323
- if (n.getContent () == CONTENT_IGNORE ||
324
- !ndef->get (n).light_propagates )
346
+ if (n.getContent () == CONTENT_IGNORE)
347
+ continue ;
348
+
349
+ const ContentFeatures &cf = ndef->get (n);
350
+ if (!cf.light_propagates )
325
351
continue ;
326
352
327
- u8 light_produced = ndef->get (n).light_source & 0x0F ;
353
+ // TODO(hmmmmm): Abstract away direct param1 accesses with a
354
+ // wrapper, but something lighter than MapNode::get/setLight
355
+
356
+ u8 light_produced = cf.light_source ;
328
357
if (light_produced)
329
- n.param1 = light_produced;
358
+ n.param1 = light_produced | (light_produced << 4 ) ;
330
359
331
- u8 light = n.param1 & 0x0F ;
360
+ u8 light = n.param1 ;
332
361
if (light) {
333
362
lightSpread (a, v3s16 (x, y, z + 1 ), light);
334
363
lightSpread (a, v3s16 (x, y + 1 , z ), light);
0 commit comments