Noise: Prevent unittest crash caused by division by zero
[oweals/minetest.git] / src / mapblock.cpp
index 910e91316b294558c03ad2d74921c6e95f989d56..ca589479419438ab7df7ac56ad4822d0058730cc 100644 (file)
@@ -366,12 +366,19 @@ void MapBlock::actuallyUpdateDayNightDiff()
        /*
                Check if any lighting value differs
        */
+
+       MapNode previous_n(CONTENT_IGNORE);
        for (u32 i = 0; i < nodecount; i++) {
-               MapNode &n = data[i];
+               MapNode n = data[i];
+
+               // If node is identical to previous node, don't verify if it differs
+               if (n == previous_n)
+                       continue;
 
                differs = !n.isLightDayNightEq(nodemgr);
                if (differs)
                        break;
+               previous_n = n;
        }
 
        /*
@@ -494,22 +501,44 @@ static void correctBlockNodeIds(const NameIdMapping *nimap, MapNode *nodes,
        // correct ids.
        std::unordered_set<content_t> unnamed_contents;
        std::unordered_set<std::string> unallocatable_contents;
+
+       bool previous_exists = false;
+       content_t previous_local_id = CONTENT_IGNORE;
+       content_t previous_global_id = CONTENT_IGNORE;
+
        for (u32 i = 0; i < MapBlock::nodecount; i++) {
                content_t local_id = nodes[i].getContent();
+               // If previous node local_id was found and same than before, don't lookup maps
+               // apply directly previous resolved id
+               // This permits to massively improve loading performance when nodes are similar
+               // example: default:air, default:stone are massively present
+               if (previous_exists && local_id == previous_local_id) {
+                       nodes[i].setContent(previous_global_id);
+                       continue;
+               }
+
                std::string name;
                if (!nimap->getName(local_id, name)) {
                        unnamed_contents.insert(local_id);
+                       previous_exists = false;
                        continue;
                }
+
                content_t global_id;
                if (!nodedef->getId(name, global_id)) {
                        global_id = gamedef->allocateUnknownNodeId(name);
-                       if(global_id == CONTENT_IGNORE){
+                       if (global_id == CONTENT_IGNORE) {
                                unallocatable_contents.insert(name);
+                               previous_exists = false;
                                continue;
                        }
                }
                nodes[i].setContent(global_id);
+
+               // Save previous node local_id & global_id result
+               previous_local_id = local_id;
+               previous_global_id = global_id;
+               previous_exists = true;
        }
 
        for (const content_t c: unnamed_contents) {