diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp index 7174a8a4..f45853c4 100644 --- a/src/content_mapnode.cpp +++ b/src/content_mapnode.cpp @@ -26,6 +26,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #define WATER_ALPHA 160 +#define WATER_VISC 1 +#define LAVA_VISC 7 + // TODO: Get rid of these and set up some attributes like toughness, // fluffyness, and a funciton to calculate time and durability loss // (and sound? and whatever else) from them @@ -374,6 +377,7 @@ void content_mapnode_init() f->liquid_type = LIQUID_FLOWING; f->liquid_alternative_flowing = CONTENT_WATER; f->liquid_alternative_source = CONTENT_WATERSOURCE; + f->liquid_viscosity = WATER_VISC; f->vertex_alpha = WATER_ALPHA; if(f->special_material == NULL && g_texturesource) { @@ -421,6 +425,7 @@ void content_mapnode_init() f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; f->liquid_alternative_flowing = CONTENT_WATER; f->liquid_alternative_source = CONTENT_WATERSOURCE; + f->liquid_viscosity = WATER_VISC; f->vertex_alpha = WATER_ALPHA; if(f->special_material == NULL && g_texturesource) { @@ -451,6 +456,7 @@ void content_mapnode_init() f->liquid_type = LIQUID_FLOWING; f->liquid_alternative_flowing = CONTENT_LAVA; f->liquid_alternative_source = CONTENT_LAVASOURCE; + f->liquid_viscosity = LAVA_VISC; f->damage_per_second = 4*2; if(f->special_material == NULL && g_texturesource) { @@ -499,6 +505,7 @@ void content_mapnode_init() f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; f->liquid_alternative_flowing = CONTENT_LAVA; f->liquid_alternative_source = CONTENT_LAVASOURCE; + f->liquid_viscosity = LAVA_VISC; f->damage_per_second = 4*2; if(f->special_material == NULL && g_texturesource) { diff --git a/src/map.cpp b/src/map.cpp index 3aff00c9..6331055a 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1562,6 +1562,9 @@ void Map::transformLiquids(core::map & modified_blocks) /*if(initial_size != 0) dstream<<"transformLiquids(): initial_size="< must_reflow; + while(m_transforming_liquid.size() != 0) { // This should be done here so that it is done when continue is used @@ -1672,6 +1675,7 @@ void Map::transformLiquids(core::map & modified_blocks) */ content_t new_node_content; s8 new_node_level = -1; + s8 max_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 @@ -1680,34 +1684,51 @@ void Map::transformLiquids(core::map & modified_blocks) } 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 = LIQUID_LEVEL_MAX; + max_node_level = new_node_level = LIQUID_LEVEL_MAX; } 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 = LIQUID_LEVEL_MAX; + if (nb_liquid_level + WATER_DROP_BOOST > max_node_level) { + max_node_level = LIQUID_LEVEL_MAX; if (nb_liquid_level + WATER_DROP_BOOST < LIQUID_LEVEL_MAX) - new_node_level = nb_liquid_level + WATER_DROP_BOOST; + max_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; + nb_liquid_level > 0 && nb_liquid_level - 1 > max_node_level) { + max_node_level = nb_liquid_level - 1; } break; } } + if (max_node_level != liquid_level) { + // amount to gain, limited by viscosity + // must be at least 1 in absolute value + s8 level_inc = max_node_level - liquid_level; + u8 viscosity = content_features(liquid_kind).liquid_viscosity; + if (level_inc < -viscosity || level_inc > viscosity) + new_node_level = liquid_level + level_inc/viscosity; + else if (level_inc < 0) + new_node_level = liquid_level - 1; + else if (level_inc > 0) + new_node_level = liquid_level + 1; + if (new_node_level != max_node_level) + must_reflow.push_back(p0); + } else + new_node_level = max_node_level; + if (new_node_level >= 0) new_node_content = liquid_kind; else new_node_content = CONTENT_AIR; + } /* @@ -1760,6 +1781,8 @@ void Map::transformLiquids(core::map & modified_blocks) } } //dstream<<"Map::transformLiquids(): loopcount="< 0) + m_transforming_liquid.push_back(must_reflow.pop_front()); } NodeMetadata* Map::getNodeMetadata(v3s16 p) diff --git a/src/mapnode.h b/src/mapnode.h index 77f6b321..4c2b9285 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -153,6 +153,10 @@ struct ContentFeatures content_t liquid_alternative_flowing; // If the content is liquid, this is the source version of the liquid. content_t liquid_alternative_source; + // Viscosity for fluid flow, ranging from 1 to 7, with + // 1 giving almost instantaneous propagation and 7 being + // the slowest possible + u8 liquid_viscosity; // Used currently for flowing liquids u8 vertex_alpha; // Special irrlicht material, used sometimes @@ -189,6 +193,7 @@ struct ContentFeatures initial_metadata = NULL; liquid_alternative_flowing = CONTENT_IGNORE; liquid_alternative_source = CONTENT_IGNORE; + liquid_viscosity = 0; vertex_alpha = 255; special_material = NULL; special_atlas = NULL;