]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/voxelalgorithms.cpp
Use node lighting for liquid spreading
[dragonfireclient.git] / src / voxelalgorithms.cpp
index 019ec1bc6ffcef2159bb2b6630047001d2c20723..83c1dd4ca570b6c2493fd5e0e396391f078feaaf 100644 (file)
@@ -583,144 +583,153 @@ bool isSunlightAbove(Map *map, v3s16 pos, INodeDefManager *ndef)
 
 static const LightBank banks[] = { LIGHTBANK_DAY, LIGHTBANK_NIGHT };
 
-void update_lighting_node(Map *map, INodeDefManager *ndef, v3s16 p,
-       MapNode oldnode, std::map<v3s16, MapBlock*> & modified_blocks)
+void update_lighting_nodes(Map *map, INodeDefManager *ndef,
+       std::vector<std::pair<v3s16, MapNode> > &oldnodes,
+       std::map<v3s16, MapBlock*> & modified_blocks)
 {
        // For node getter functions
        bool is_valid_position;
 
-       // Get position and block of the changed node
-       relative_v3 rel_pos;
-       mapblock_v3 block_pos;
-       getNodeBlockPosWithOffset(p, block_pos, rel_pos);
-       MapBlock *block = map->getBlockNoCreateNoEx(block_pos);
-       if (block == NULL || block->isDummy()) {
-               return;
-       }
-
        // Process each light bank separately
        for (s32 i = 0; i < 2; i++) {
-               // Get the new node
-               MapNode n = block->getNodeNoCheck(rel_pos, &is_valid_position);
-               if (!is_valid_position) {
-                       break;
-               }
                LightBank bank = banks[i];
+               UnlightQueue disappearing_lights(256);
+               ReLightQueue light_sources(256);
+               // For each changed node process sunlight and initialize
+               for (std::vector<std::pair<v3s16, MapNode> >::iterator it =
+                               oldnodes.begin(); it < oldnodes.end(); it++) {
+                       // Get position and block of the changed node
+                       v3s16 p = it->first;
+                       relative_v3 rel_pos;
+                       mapblock_v3 block_pos;
+                       getNodeBlockPosWithOffset(p, block_pos, rel_pos);
+                       MapBlock *block = map->getBlockNoCreateNoEx(block_pos);
+                       if (block == NULL || block->isDummy()) {
+                               continue;
+                       }
+                       // Get the new node
+                       MapNode n = block->getNodeNoCheck(rel_pos, &is_valid_position);
+                       if (!is_valid_position) {
+                               break;
+                       }
 
-               // Light of the old node
-               u8 old_light = oldnode.getLight(bank, ndef);
+                       // Light of the old node
+                       u8 old_light = it->second.getLight(bank, ndef);
 
-               // Add the block of the added node to modified_blocks
-               modified_blocks[block_pos] = block;
+                       // Add the block of the added node to modified_blocks
+                       modified_blocks[block_pos] = block;
 
-               // Get new light level of the node
-               u8 new_light = 0;
-               if (ndef->get(n).light_propagates) {
-                       if (bank == LIGHTBANK_DAY && ndef->get(n).sunlight_propagates
+                       // Get new light level of the node
+                       u8 new_light = 0;
+                       if (ndef->get(n).light_propagates) {
+                               if (bank == LIGHTBANK_DAY && ndef->get(n).sunlight_propagates
                                        && isSunlightAbove(map, p, ndef)) {
-                               new_light = LIGHT_SUN;
-                       } else {
-                               new_light = ndef->get(n).light_source;
-                               for (int i = 0; i < 6; i++) {
-                                       v3s16 p2 = p + neighbor_dirs[i];
-                                       bool is_valid;
-                                       MapNode n2 = map->getNodeNoEx(p2, &is_valid);
-                                       if (is_valid) {
-                                               u8 spread = n2.getLight(bank, ndef);
-                                               // If the neighbor is at least as bright as
-                                               // this node then its light is not from
-                                               // this node.
-                                               // Its light can spread to this node.
-                                               if (spread > new_light && spread >= old_light) {
-                                                       new_light = spread - 1;
+                                       new_light = LIGHT_SUN;
+                               } else {
+                                       new_light = ndef->get(n).light_source;
+                                       for (int i = 0; i < 6; i++) {
+                                               v3s16 p2 = p + neighbor_dirs[i];
+                                               bool is_valid;
+                                               MapNode n2 = map->getNodeNoEx(p2, &is_valid);
+                                               if (is_valid) {
+                                                       u8 spread = n2.getLight(bank, ndef);
+                                                       // If the neighbor is at least as bright as
+                                                       // this node then its light is not from
+                                                       // this node.
+                                                       // Its light can spread to this node.
+                                                       if (spread > new_light && spread >= old_light) {
+                                                               new_light = spread - 1;
+                                                       }
                                                }
                                        }
                                }
+                       } else {
+                               // If this is an opaque node, it still can emit light.
+                               new_light = ndef->get(n).light_source;
                        }
-               } else {
-                       // If this is an opaque node, it still can emit light.
-                       new_light = ndef->get(n).light_source;
-               }
-
-               ReLightQueue light_sources(256);
 
-               if (new_light > 0) {
-                       light_sources.push(new_light, rel_pos, block_pos, block, 6);
-               }
+                       if (new_light > 0) {
+                               light_sources.push(new_light, rel_pos, block_pos, block, 6);
+                       }
 
-               if (new_light < old_light) {
-                       // The node became opaque or doesn't provide as much
-                       // light as the previous one, so it must be unlighted.
-                       LightQueue disappearing_lights(256);
+                       if (new_light < old_light) {
+                               // The node became opaque or doesn't provide as much
+                               // light as the previous one, so it must be unlighted.
 
-                       // Add to unlight queue
-                       n.setLight(bank, 0, ndef);
-                       block->setNodeNoCheck(rel_pos, n);
-                       disappearing_lights.push(old_light, rel_pos, block_pos, block, 6);
+                               // Add to unlight queue
+                               n.setLight(bank, 0, ndef);
+                               block->setNodeNoCheck(rel_pos, n);
+                               disappearing_lights.push(old_light, rel_pos, block_pos, block,
+                                       6);
 
-                       // Remove sunlight, if there was any
-                       if (bank == LIGHTBANK_DAY && old_light == LIGHT_SUN) {
-                               for (s16 y = p.Y - 1;; y--) {
-                                       v3s16 n2pos(p.X, y, p.Z);
+                               // Remove sunlight, if there was any
+                               if (bank == LIGHTBANK_DAY && old_light == LIGHT_SUN) {
+                                       for (s16 y = p.Y - 1;; y--) {
+                                               v3s16 n2pos(p.X, y, p.Z);
 
-                                       MapNode n2;
+                                               MapNode n2;
 
-                                       n2 = map->getNodeNoEx(n2pos, &is_valid_position);
-                                       if (!is_valid_position)
-                                               break;
+                                               n2 = map->getNodeNoEx(n2pos, &is_valid_position);
+                                               if (!is_valid_position)
+                                                       break;
 
-                                       // If this node doesn't have sunlight, the nodes below
-                                       // it don't have too.
-                                       if (n2.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) {
-                                               break;
+                                               // If this node doesn't have sunlight, the nodes below
+                                               // it don't have too.
+                                               if (n2.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) {
+                                                       break;
+                                               }
+                                               // Remove sunlight and add to unlight queue.
+                                               n2.setLight(LIGHTBANK_DAY, 0, ndef);
+                                               map->setNode(n2pos, n2);
+                                               relative_v3 rel_pos2;
+                                               mapblock_v3 block_pos2;
+                                               getNodeBlockPosWithOffset(n2pos, block_pos2, rel_pos2);
+                                               MapBlock *block2 = map->getBlockNoCreateNoEx(
+                                                       block_pos2);
+                                               disappearing_lights.push(LIGHT_SUN, rel_pos2,
+                                                       block_pos2, block2,
+                                                       4 /* The node above caused the change */);
                                        }
-                                       // Remove sunlight and add to unlight queue.
-                                       n2.setLight(LIGHTBANK_DAY, 0, ndef);
-                                       map->setNode(n2pos, n2);
-                                       relative_v3 rel_pos2;
-                                       mapblock_v3 block_pos2;
-                                       getNodeBlockPosWithOffset(n2pos, block_pos2, rel_pos2);
-                                       MapBlock *block2 = map->getBlockNoCreateNoEx(block_pos2);
-                                       disappearing_lights.push(LIGHT_SUN, rel_pos2, block_pos2,
-                                               block2, 4 /* The node above caused the change */);
                                }
-                       }
-                       // Remove lights
-                       unspreadLight(map, ndef, bank, disappearing_lights, light_sources,
-                               modified_blocks);
-               } else if (new_light > old_light) {
-                       // It is sure that the node provides more light than the previous
-                       // one, unlighting is not necessary.
-                       // Propagate sunlight
-                       if (bank == LIGHTBANK_DAY && new_light == LIGHT_SUN) {
-                               for (s16 y = p.Y - 1;; y--) {
-                                       v3s16 n2pos(p.X, y, p.Z);
-
-                                       MapNode n2;
-
-                                       n2 = map->getNodeNoEx(n2pos, &is_valid_position);
-                                       if (!is_valid_position)
-                                               break;
-
-                                       // This should not happen, but if the node has sunlight
-                                       // then the iteration should stop.
-                                       if (n2.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN) {
-                                               break;
-                                       }
-                                       // If the node terminates sunlight, stop.
-                                       if (!ndef->get(n2).sunlight_propagates) {
-                                               break;
+                       } else if (new_light > old_light) {
+                               // It is sure that the node provides more light than the previous
+                               // one, unlighting is not necessary.
+                               // Propagate sunlight
+                               if (bank == LIGHTBANK_DAY && new_light == LIGHT_SUN) {
+                                       for (s16 y = p.Y - 1;; y--) {
+                                               v3s16 n2pos(p.X, y, p.Z);
+
+                                               MapNode n2;
+
+                                               n2 = map->getNodeNoEx(n2pos, &is_valid_position);
+                                               if (!is_valid_position)
+                                                       break;
+
+                                               // This should not happen, but if the node has sunlight
+                                               // then the iteration should stop.
+                                               if (n2.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN) {
+                                                       break;
+                                               }
+                                               // If the node terminates sunlight, stop.
+                                               if (!ndef->get(n2).sunlight_propagates) {
+                                                       break;
+                                               }
+                                               relative_v3 rel_pos2;
+                                               mapblock_v3 block_pos2;
+                                               getNodeBlockPosWithOffset(n2pos, block_pos2, rel_pos2);
+                                               MapBlock *block2 = map->getBlockNoCreateNoEx(
+                                                       block_pos2);
+                                               // Mark node for lighting.
+                                               light_sources.push(LIGHT_SUN, rel_pos2, block_pos2,
+                                                       block2, 4);
                                        }
-                                       relative_v3 rel_pos2;
-                                       mapblock_v3 block_pos2;
-                                       getNodeBlockPosWithOffset(n2pos, block_pos2, rel_pos2);
-                                       MapBlock *block2 = map->getBlockNoCreateNoEx(block_pos2);
-                                       // Mark node for lighting.
-                                       light_sources.push(LIGHT_SUN, rel_pos2, block_pos2, block2,
-                                               4);
                                }
                        }
+
                }
+               // Remove lights
+               unspreadLight(map, ndef, bank, disappearing_lights, light_sources,
+                       modified_blocks);
                // Initialize light values for light spreading.
                for (u8 i = 0; i <= LIGHT_SUN; i++) {
                        const std::vector<ChangingLight> &lights = light_sources.lights[i];