]> git.lizzy.rs Git - minetest.git/blobdiff - src/map.cpp
Get rid of unused variables
[minetest.git] / src / map.cpp
index 83062706694022984f5ae077c86d29e9c6c1c11b..092ce97fdcf030cca3b60c8af40a9b09a0b6a0fe 100644 (file)
@@ -1540,6 +1540,17 @@ void Map::PrintInfo(std::ostream &out)
 
 #define WATER_DROP_BOOST 4
 
+enum NeighborType {
+       NEIGHBOR_UPPER,
+       NEIGHBOR_SAME_LEVEL,
+       NEIGHBOR_LOWER
+};
+struct NodeNeighbor {
+       MapNode n;
+       NeighborType t;
+       v3s16 p;
+};
+
 void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
 {
        DSTACK(__FUNCTION_NAME);
@@ -1559,240 +1570,220 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
                v3s16 p0 = m_transforming_liquid.pop_front();
 
                MapNode n0 = getNodeNoEx(p0);
-
-               // Don't deal with non-liquids
-               if(content_liquid(n0.getContent()) == false)
-                       continue;
-
-               bool is_source = !content_flowing_liquid(n0.getContent());
-
-               u8 liquid_level = 8;
-               if(is_source == false)
-                       liquid_level = n0.param2 & 0x0f;
-
-               // Turn possible source into non-source
-               u8 nonsource_c = make_liquid_flowing(n0.getContent());
-
+                               
                /*
-                       If not source, check that some node flows into this one
-                       and what is the level of liquid in this one
-               */
-               if(is_source == false)
-               {
-                       s8 new_liquid_level_max = -1;
-
-                       v3s16 dirs_from[5] = {
-                               v3s16(0,1,0), // top
-                               v3s16(0,0,1), // back
-                               v3s16(1,0,0), // right
-                               v3s16(0,0,-1), // front
-                               v3s16(-1,0,0), // left
-                       };
-                       for(u16 i=0; i<5; i++)
-                       {
-                               bool from_top = (i==0);
-
-                               v3s16 p2 = p0 + dirs_from[i];
-                               MapNode n2 = getNodeNoEx(p2);
-
-                               if(content_liquid(n2.getContent()))
-                               {
-                                       u8 n2_nonsource_c = make_liquid_flowing(n2.getContent());
-                                       // Check that the liquids are the same type
-                                       if(n2_nonsource_c != nonsource_c)
-                                       {
-                                               dstream<<"WARNING: Not handling: different liquids"
-                                                               " collide"<<std::endl;
-                                               continue;
+                       Collect information about current node
+                */
+               s8 liquid_level = -1;
+               u8 liquid_kind = CONTENT_IGNORE;
+               LiquidType liquid_type = content_features(n0.getContent()).liquid_type;
+               switch (liquid_type) {
+                       case LIQUID_SOURCE:
+                               liquid_level = 8;
+                               liquid_kind = content_features(n0.getContent()).liquid_alternative_flowing;
+                               break;
+                       case LIQUID_FLOWING:
+                               liquid_level = (n0.param2 & LIQUID_LEVEL_MASK);
+                               liquid_kind = n0.getContent();
+                               break;
+                       case LIQUID_NONE:
+                               // if this is an air node, it *could* be transformed into a liquid. otherwise,
+                               // continue with the next node.
+                               if (n0.getContent() != CONTENT_AIR)
+                                       continue;
+                               liquid_kind = CONTENT_AIR;
+                               break;
+               }
+               
+               /*
+                       Collect information about the environment
+                */
+               v3s16 dirs[6] = {
+                       v3s16( 0, 1, 0), // top
+                       v3s16( 0,-1, 0), // bottom
+                       v3s16( 1, 0, 0), // right
+                       v3s16(-1, 0, 0), // left
+                       v3s16( 0, 0, 1), // back
+                       v3s16( 0, 0,-1), // front
+               };
+               NodeNeighbor sources[6]; // surrounding sources
+               int num_sources = 0;
+               NodeNeighbor flows[6]; // surrounding flowing liquid nodes
+               int num_flows = 0;
+               NodeNeighbor airs[6]; // surrounding air
+               int num_airs = 0;
+               NodeNeighbor neutrals[6]; // nodes that are solid or another kind of liquid
+               int num_neutrals = 0;
+               bool flowing_down = false;
+               for (u16 i = 0; i < 6; i++) {
+                       NeighborType nt = NEIGHBOR_SAME_LEVEL;
+                       switch (i) {
+                               case 0:
+                                       nt = NEIGHBOR_UPPER;
+                                       break;
+                               case 1:
+                                       nt = NEIGHBOR_LOWER;
+                                       break;
+                       }
+                       v3s16 npos = p0 + dirs[i];
+                       NodeNeighbor nb = {getNodeNoEx(npos), nt, npos};
+                       switch (content_features(nb.n.getContent()).liquid_type) {
+                               case LIQUID_NONE:
+                                       if (nb.n.getContent() == CONTENT_AIR) {
+                                               airs[num_airs++] = nb;
+                                               // if the current node happens to be a flowing node, it will start to flow down here.
+                                               if (nb.t == NEIGHBOR_LOWER)
+                                                       flowing_down = true;
+                                       } else {
+                                               neutrals[num_neutrals++] = nb;
                                        }
-                                       bool n2_is_source = !content_flowing_liquid(n2.getContent());
-                                       s8 n2_liquid_level = 8;
-                                       if(n2_is_source == false)
-                                               n2_liquid_level = n2.param2 & 0x07;
-
-                                       s8 new_liquid_level = -1;
-                                       if(from_top)
-                                       {
-                                               //new_liquid_level = 7;
-                                               if(n2_liquid_level >= 7 - WATER_DROP_BOOST)
-                                                       new_liquid_level = 7;
-                                               else
-                                                       new_liquid_level = n2_liquid_level + WATER_DROP_BOOST;
+                                       break;
+                               case LIQUID_SOURCE:
+                                       // if this node is not (yet) of a liquid type, choose the first liquid type we encounter 
+                                       if (liquid_kind == CONTENT_AIR)
+                                               liquid_kind = content_features(nb.n.getContent()).liquid_alternative_flowing;
+                                       if (content_features(nb.n.getContent()).liquid_alternative_flowing !=liquid_kind) {
+                                               neutrals[num_neutrals++] = nb;
+                                       } else {
+                                               sources[num_sources++] = nb;
                                        }
-                                       else if(n2_liquid_level > 0)
-                                       {
-                                               new_liquid_level = n2_liquid_level - 1;
+                                       break;
+                               case LIQUID_FLOWING:
+                                       // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
+                                       if (liquid_kind == CONTENT_AIR)
+                                               liquid_kind = content_features(nb.n.getContent()).liquid_alternative_flowing;
+                                       if (content_features(nb.n.getContent()).liquid_alternative_flowing != liquid_kind) {
+                                               neutrals[num_neutrals++] = nb;
+                                       } else {
+                                               flows[num_flows++] = nb;
+                                               if (nb.t == NEIGHBOR_LOWER)
+                                                       flowing_down = true;
                                        }
-
-                                       if(new_liquid_level > new_liquid_level_max)
-                                               new_liquid_level_max = new_liquid_level;
-                               }
-                       } //for
-
-                       /*
-                               If liquid level should be something else, update it and
-                               add all the neighboring water nodes to the transform queue.
-                       */
-                       if(new_liquid_level_max != liquid_level)
-                       {
-                               if(new_liquid_level_max == -1)
-                               {
-                                       // Remove water alltoghether
-                                       n0.setContent(CONTENT_AIR);
-                                       n0.param2 = 0;
-                                       setNode(p0, n0);
-                               }
-                               else
-                               {
-                                       n0.param2 = new_liquid_level_max;
-                                       setNode(p0, n0);
-                               }
-
-                               // Block has been modified
-                               {
-                                       v3s16 blockpos = getNodeBlockPos(p0);
-                                       MapBlock *block = getBlockNoCreateNoEx(blockpos);
-                                       if(block != NULL)
-                                               modified_blocks.insert(blockpos, block);
+                                       break;
+                       }
+               }
+               
+               /*
+                       decide on the type (and possibly level) of the current node
+                */
+               u8 new_node_content;
+               s8 new_node_level = -1;
+               if (num_sources >= 2 || liquid_type == LIQUID_SOURCE) {
+                       // liquid_kind will be set to either the flowing alternative of the node (if it's a liquid)
+                       // or the flowing alternative of the first of the surrounding sources (if it's air), so
+                       // it's perfectly safe to use liquid_kind here to determine the new node content.
+                       new_node_content = content_features(liquid_kind).liquid_alternative_source;
+               } else if (num_sources == 1 && sources[0].t != NEIGHBOR_LOWER) {
+                       // liquid_kind is set properly, see above
+                       new_node_content = liquid_kind;
+                       new_node_level = 7;
+               } else {
+                       // no surrounding sources, so get the maximum level that can flow into this node
+                       for (u16 i = 0; i < num_flows; i++) {
+                               u8 nb_liquid_level = (flows[i].n.param2 & LIQUID_LEVEL_MASK);
+                               switch (flows[i].t) {
+                                       case NEIGHBOR_UPPER:
+                                               if (nb_liquid_level + WATER_DROP_BOOST > new_node_level) {
+                                                       new_node_level = 7;
+                                                       if (nb_liquid_level + WATER_DROP_BOOST < 7)
+                                                               new_node_level = nb_liquid_level + WATER_DROP_BOOST;
+                                               }
+                                               break;
+                                       case NEIGHBOR_LOWER:
+                                               break;
+                                       case NEIGHBOR_SAME_LEVEL:
+                                               if ((flows[i].n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK &&
+                                                       nb_liquid_level > 0 && nb_liquid_level - 1 > new_node_level) {
+                                                       new_node_level = nb_liquid_level - 1;
+                                               }
+                                               break;
                                }
-
-                               /*
-                                       Add neighboring non-source liquid nodes to transform queue.
-                               */
-                               v3s16 dirs[6] = {
-                                       v3s16(0,0,1), // back
-                                       v3s16(0,1,0), // top
-                                       v3s16(1,0,0), // right
-                                       v3s16(0,0,-1), // front
-                                       v3s16(0,-1,0), // bottom
-                                       v3s16(-1,0,0), // left
-                               };
-                               for(u16 i=0; i<6; i++)
-                               {
-                                       v3s16 p2 = p0 + dirs[i];
-
-                                       MapNode n2 = getNodeNoEx(p2);
-                                       if(content_flowing_liquid(n2.getContent()))
-                                       {
-                                               m_transforming_liquid.push_back(p2);
+                       }
+                       // don't flow as far in open terrain - if there isn't at least one adjacent solid block,
+                       // substract another unit from the resulting water level.
+                       if (!flowing_down && new_node_level >= 1) {
+                               bool at_wall = false;
+                               for (u16 i = 0; i < num_neutrals; i++) {
+                                       if (neutrals[i].t == NEIGHBOR_SAME_LEVEL) {
+                                               at_wall = true;
+                                               break;
                                        }
                                }
+                               if (!at_wall)
+                                       new_node_level -= 1;
                        }
+                       
+                       if (new_node_level >= 0)
+                               new_node_content = liquid_kind;
+                       else
+                               new_node_content = CONTENT_AIR;
                }
-
-               // Get a new one from queue if the node has turned into non-water
-               if(content_liquid(n0.getContent()) == false)
+               
+               /*
+                       check if anything has changed. if not, just continue with the next node.
+                */
+               if (new_node_content == n0.getContent() && (content_features(n0.getContent()).liquid_type != LIQUID_FLOWING ||
+                                                                                ((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level &&
+                                                                                ((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)
+                                                                                == flowing_down)))
                        continue;
-
+               
+               
                /*
-                       Flow water from this node
-               */
-               v3s16 dirs_to[5] = {
-                       v3s16(0,-1,0), // bottom
-                       v3s16(0,0,1), // back
-                       v3s16(1,0,0), // right
-                       v3s16(0,0,-1), // front
-                       v3s16(-1,0,0), // left
-               };
-               for(u16 i=0; i<5; i++)
-               {
-                       bool to_bottom = (i == 0);
-
-                       // If liquid is at lowest possible height, it's not going
-                       // anywhere except down
-                       if(liquid_level == 0 && to_bottom == false)
-                               continue;
-
-                       u8 liquid_next_level = 0;
-                       // If going to bottom
-                       if(to_bottom)
-                       {
-                               //liquid_next_level = 7;
-                               if(liquid_level >= 7 - WATER_DROP_BOOST)
-                                       liquid_next_level = 7;
-                               else
-                                       liquid_next_level = liquid_level + WATER_DROP_BOOST;
-                       }
-                       else
-                               liquid_next_level = liquid_level - 1;
-
-                       bool n2_changed = false;
-                       bool flowed = false;
-
-                       v3s16 p2 = p0 + dirs_to[i];
-
-                       MapNode n2 = getNodeNoEx(p2);
-                       //dstream<<"[1] n2.param="<<(int)n2.param<<std::endl;
-
-                       if(content_liquid(n2.getContent()))
-                       {
-                               u8 n2_nonsource_c = make_liquid_flowing(n2.getContent());
-                               // Check that the liquids are the same type
-                               if(n2_nonsource_c != nonsource_c)
-                               {
-                                       dstream<<"WARNING: Not handling: different liquids"
-                                                       " collide"<<std::endl;
-                                       continue;
-                               }
-                               bool n2_is_source = !content_flowing_liquid(n2.getContent());
-                               u8 n2_liquid_level = 8;
-                               if(n2_is_source == false)
-                                       n2_liquid_level = n2.param2 & 0x07;
-
-                               if(to_bottom)
-                               {
-                                       flowed = true;
-                               }
-
-                               if(n2_is_source)
-                               {
-                                       // Just flow into the source, nothing changes.
-                                       // n2_changed is not set because destination didn't change
-                                       flowed = true;
+                       update the current node
+                */
+               bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK));
+               n0.setContent(new_node_content);
+               if (content_features(n0.getContent()).liquid_type == LIQUID_FLOWING) {
+                       // set level to last 3 bits, flowing down bit to 4th bit
+                       n0.param2 = (flowing_down ? LIQUID_FLOW_DOWN_MASK : 0x00) | (new_node_level & LIQUID_LEVEL_MASK);
+               } else {
+                       n0.param2 = 0;
+               }
+               setNode(p0, n0);
+               v3s16 blockpos = getNodeBlockPos(p0);
+               MapBlock *block = getBlockNoCreateNoEx(blockpos);
+               if(block != NULL)
+                       modified_blocks.insert(blockpos, block);
+               
+               /*
+                       enqueue neighbors for update if neccessary
+                */
+               switch (content_features(n0.getContent()).liquid_type) {
+                       case LIQUID_SOURCE:
+                               // make sure source flows into all neighboring nodes
+                               for (u16 i = 0; i < num_flows; i++)
+                                       if (flows[i].t != NEIGHBOR_UPPER)
+                                               m_transforming_liquid.push_back(flows[i].p);
+                               for (u16 i = 0; i < num_airs; i++)
+                                       if (airs[i].t != NEIGHBOR_UPPER)
+                                               m_transforming_liquid.push_back(airs[i].p);
+                               break;
+                       case LIQUID_NONE:
+                               // this flow has turned to air; neighboring flows might need to do the same
+                               for (u16 i = 0; i < num_flows; i++)
+                                       m_transforming_liquid.push_back(flows[i].p);
+                               break;
+                       case LIQUID_FLOWING:
+                               for (u16 i = 0; i < num_flows; i++) {
+                                       u8 flow_level = (flows[i].n.param2 & LIQUID_LEVEL_MASK);
+                                       // liquid_level is still the ORIGINAL level of this node.
+                                       if (flows[i].t != NEIGHBOR_UPPER && ((flow_level < liquid_level || flow_level < new_node_level) ||
+                                               flow_down_enabled))
+                                               m_transforming_liquid.push_back(flows[i].p);
                                }
-                               else
-                               {
-                                       if(liquid_next_level > liquid_level)
-                                       {
-                                               n2.param2 = liquid_next_level;
-                                               setNode(p2, n2);
-
-                                               n2_changed = true;
-                                               flowed = true;
-                                       }
+                               for (u16 i = 0; i < num_airs; i++) {
+                                       if (airs[i].t != NEIGHBOR_UPPER && (airs[i].t == NEIGHBOR_LOWER || new_node_level > 0))
+                                               m_transforming_liquid.push_back(airs[i].p);
                                }
-                       }
-                       else if(n2.getContent() == CONTENT_AIR)
-                       {
-                               n2.setContent(nonsource_c);
-                               n2.param2 = liquid_next_level;
-                               setNode(p2, n2);
-
-                               n2_changed = true;
-                               flowed = true;
-                       }
-
-                       //dstream<<"[2] n2.param="<<(int)n2.param<<std::endl;
-
-                       if(n2_changed)
-                       {
-                               m_transforming_liquid.push_back(p2);
-
-                               v3s16 blockpos = getNodeBlockPos(p2);
-                               MapBlock *block = getBlockNoCreateNoEx(blockpos);
-                               if(block != NULL)
-                                       modified_blocks.insert(blockpos, block);
-                       }
-
-                       // If n2_changed to bottom, don't flow anywhere else
-                       if(to_bottom && flowed && !is_source)
                                break;
                }
-
+               
                loopcount++;
                //if(loopcount >= 100000)
-               if(loopcount >= initial_size * 1)
+               if(loopcount >= initial_size * 10) {
                        break;
+               }
        }
        //dstream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
 }