new adjustable finite liquid
authorproller <proller@github.com>
Sun, 24 Feb 2013 14:39:07 +0000 (18:39 +0400)
committerproller <proller@github.com>
Sun, 24 Feb 2013 14:39:07 +0000 (18:39 +0400)
games/minimal/mods/default/mapgen.lua
minetest.conf.example
src/content_abm.cpp
src/content_mapblock.cpp
src/defaultsettings.cpp
src/map.cpp
src/map.h
src/mapnode.h
src/server.cpp
src/server.h

index af94505a04f5856e8e26944b2d1155a8ec79a493..115bb145879e8d70004604d7edfeb9f3df30372f 100644 (file)
@@ -27,7 +27,7 @@ minetest.register_alias("mapgen_mese", "default:mese")
 -- Ore generation
 --
 
-local function generate_ore(name, wherein, minp, maxp, seed, chunks_per_volume, ore_per_chunk, height_min, height_max)
+local function generate_ore(name, wherein, minp, maxp, seed, chunks_per_volume, ore_per_chunk, height_min, height_max, param2)
        if maxp.y < height_min or minp.y > height_max then
                return
        end
@@ -57,7 +57,7 @@ local function generate_ore(name, wherein, minp, maxp, seed, chunks_per_volume,
                                        local z2 = z0+z1
                                        local p2 = {x=x2, y=y2, z=z2}
                                        if minetest.env:get_node(p2).name == wherein then
-                                               minetest.env:set_node(p2, {name=name})
+                                               minetest.env:set_node(p2, {name=name, param2=param2})
                                        end
                                end
                        end
@@ -110,5 +110,11 @@ minetest.register_on_generated(function(minp, maxp, seed)
                end
                end
        end
+       if minetest.setting_get("liquid_finite") then
+               generate_ore("default:water_source", "default:stone", minp, maxp, seed+42, 1/24/24/24, 4,  -100,   -10,  128)
+               generate_ore("default:water_source", "default:stone", minp, maxp, seed+42, 1/28/28/28, 3,  -10000, -101, 128)
+               generate_ore("default:lava_source",  "default:stone", minp, maxp, seed+43, 1/38/38/38, 2,  -500,   -100, 128)
+               generate_ore("default:lava_source",  "default:stone", minp, maxp, seed+43, 1/30/30/30, 4,  -31000, -501, 128)
+       end
 end)
 
index c36fe05ff92be7b3be573178c5dea92c7db233bc..8e95d7e6018049b1fe7805eec536df020677457b 100644 (file)
 #enable_fog = true
 # Enable a bit lower water surface; disable for speed (not quite optimized)
 #new_style_water = false
+# Constant volume liquids
+#liquid_finite = false
+# Update liquids every .. recommend for finite: 0.2
+#liquid_update = 1.0
+# When finite liquid: relax flowing blocks to source if level near max and N nearby source blocks, more realistic, but not true constant. values: 0,1,2,3,4 : 0 - disable, 1 - most aggresive
+#liquid_relax = 1
+# optimization: faster cave flood (and not true constant)
+#liquid_fast_flood = 1
 # Enable nice leaves; disable for speed
 #new_style_leaves = true
 # Enable smooth lighting with simple ambient occlusion;
index 0dcf862fc0d1c891fad909c1df5be008b7467cf5..971ac4f34462540d0915fede713cfca50ebd7182 100644 (file)
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "settings.h"
 #include "mapblock.h" // For getNodeBlockPos
 #include "treegen.h" // For treegen::make_tree
+#include "main.h" // for g_settings
 #include "map.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@@ -146,11 +147,42 @@ public:
        }
 };
 
+class LiquidFlowABM : public ActiveBlockModifier
+{
+private:
+       std::set<std::string> contents;
+
+public:
+       LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr) 
+       {
+               std::set<content_t> liquids;
+               nodemgr->getIds("group:liquid", liquids);
+               for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++)
+                       contents.insert(nodemgr->get(*k).liquid_alternative_flowing);
+               
+       }
+       virtual std::set<std::string> getTriggerContents()
+       {
+               return contents;
+       }
+       virtual float getTriggerInterval()
+       { return 10.0; }
+       virtual u32 getTriggerChance()
+       { return 10; }
+       virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
+       {
+               ServerMap *map = &env->getServerMap();
+               if (map->transforming_liquid_size() < 500)
+                       map->transforming_liquid_add(p);
+               //if ((*map).m_transforming_liquid.size() < 500) (*map).m_transforming_liquid.push_back(p);
+       }
+};
+
 void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
 {
        env->addActiveBlockModifier(new GrowGrassABM());
        env->addActiveBlockModifier(new RemoveGrassABM());
        env->addActiveBlockModifier(new MakeTreesFromSaplingsABM());
+       if (g_settings->getBool("liquid_finite"))
+               env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef));
 }
-
-
index 290890490ec77241cab5c805f8ce32417690079f..e224f0b0603e803d943e64a1f1c6ca121bf96eea 100644 (file)
@@ -261,7 +261,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                                level = (-0.5+node_liquid_level) * BS;
                                        else if(n2.getContent() == c_flowing)
                                                level = (-0.5 + ((float)(n2.param2&LIQUID_LEVEL_MASK)
-                                                               + 0.5) / 8.0 * node_liquid_level) * BS;
+                                                               + 0.5) / (float)LIQUID_LEVEL_SOURCE * node_liquid_level) * BS;
 
                                        // Check node above neighbor.
                                        // NOTE: This doesn't get executed if neighbor
@@ -324,7 +324,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                        }
                                }
                                if(air_count >= 2)
-                                       cornerlevel = -0.5*BS;
+                                       cornerlevel = -0.5*BS+0.1;
                                else if(valid_count > 0)
                                        cornerlevel /= valid_count;
                                corner_levels[i] = cornerlevel;
index 6cdaaa49615afb1d28bceaf86aa93d75a90851d5..f2c9886b45b1b20d8ebfc98e37283f1831511081 100644 (file)
@@ -201,6 +201,11 @@ void set_default_settings(Settings *settings)
        //mapgen related things
        settings->setDefault("mg_name", "v6");
        settings->setDefault("water_level", "1");
+       settings->setDefault("liquid_finite", "false");
+       settings->setDefault("liquid_update", "1.0");
+       settings->setDefault("liquid_relax", "1");
+       settings->setDefault("liquid_fast_flood", "1");
+       
        settings->setDefault("chunksize", "5");
        settings->setDefault("mg_flags", "trees, caves, v6_biome_blend");
        settings->setDefault("mgv6_freq_desert", "0.45");
index 717b0cf9bf9c2398ec83b8de3e7bff68060880b4..7272451a422fc3f8485257e7e74944fcd3a0e68b 100644 (file)
@@ -1613,10 +1613,322 @@ struct NodeNeighbor {
        MapNode n;
        NeighborType t;
        v3s16 p;
+       bool l; //can liquid
+       bool i; //infinity
 };
 
+void Map::transforming_liquid_add(v3s16 p) {
+        m_transforming_liquid.push_back(p);
+}
+
+s32 Map::transforming_liquid_size() {
+        return m_transforming_liquid.size();
+}
+
+const v3s16 g_7dirs[7] =
+{
+       // +right, +top, +back
+       v3s16( 0,-1, 0), // bottom
+       v3s16( 0, 0, 0), // self
+       v3s16( 0, 0, 1), // back
+       v3s16( 0, 0,-1), // front
+       v3s16( 1, 0, 0), // right
+       v3s16(-1, 0, 0), // left
+       v3s16( 0, 1, 0)  // top
+};
+
+#define D_BOTTOM 0
+#define D_TOP 6
+#define D_SELF 1
+
+void Map::transformLiquidsFinite(core::map<v3s16, MapBlock*> & modified_blocks)
+{
+       INodeDefManager *nodemgr = m_gamedef->ndef();
+
+       DSTACK(__FUNCTION_NAME);
+       //TimeTaker timer("transformLiquids()");
+
+       u32 loopcount = 0;
+       u32 initial_size = m_transforming_liquid.size();
+
+       u8 relax = g_settings->getS16("liquid_relax");
+       bool fast_flood = g_settings->getS16("liquid_fast_flood");
+       int water_level = g_settings->getS16("water_level");
+
+       /*if(initial_size != 0)
+               infostream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
+
+       // list of nodes that due to viscosity have not reached their max level height
+       UniqueQueue<v3s16> must_reflow, must_reflow_second;
+
+       // List of MapBlocks that will require a lighting update (due to lava)
+       core::map<v3s16, MapBlock*> lighting_modified_blocks;
+
+       while(m_transforming_liquid.size() > 0)
+       {
+               // This should be done here so that it is done when continue is used
+               if(loopcount >= initial_size || loopcount >= 1000)
+                       break;
+               loopcount++;
+               /*
+                       Get a queued transforming liquid node
+               */
+               v3s16 p0 = m_transforming_liquid.pop_front();
+               u16 total_level = 0;
+               NodeNeighbor neighbors[7]; // surrounding flowing liquid nodes
+               s8 liquid_levels[7]      = {-1, -1, -1, -1, -1, -1, -1}; // current level of every block
+               s8 liquid_levels_want[7] = {-1, -1, -1, -1, -1, -1, -1}; // target levels
+               s8 can_liquid_same_level = 0;
+               content_t liquid_kind = CONTENT_IGNORE;
+               content_t liquid_kind_flowing = CONTENT_IGNORE;
+               /*
+                       Collect information about the environment
+                */
+               const v3s16 *dirs = g_7dirs;
+               for (u16 i = 0; i < 7; i++) {
+                       NeighborType nt = NEIGHBOR_SAME_LEVEL;
+                       switch (i) {
+                               case D_TOP:
+                                       nt = NEIGHBOR_UPPER;
+                                       break;
+                               case D_BOTTOM:
+                                       nt = NEIGHBOR_LOWER;
+                                       break;
+                       }
+                       v3s16 npos = p0 + dirs[i];
+
+                       neighbors[i].n = getNodeNoEx(npos);
+                       neighbors[i].t = nt;
+                       neighbors[i].p = npos;
+                       neighbors[i].l = 0;
+                       neighbors[i].i = 0;
+                       NodeNeighbor & nb = neighbors[i];
+
+                       switch (nodemgr->get(nb.n.getContent()).liquid_type) {
+                               case LIQUID_NONE:
+                                       if (nb.n.getContent() == CONTENT_AIR) {
+                                               liquid_levels[i] = 0;
+                                               nb.l = 1;
+                                       }
+                                       break;
+                               case LIQUID_SOURCE:
+                                       // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
+                                       if (liquid_kind_flowing == CONTENT_IGNORE)
+                                               liquid_kind_flowing = nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing);
+                                       if (liquid_kind == CONTENT_IGNORE)
+                                               liquid_kind = nb.n.getContent();
+                                       if (nb.n.getContent() == liquid_kind) {
+                                               liquid_levels[i] = LIQUID_LEVEL_SOURCE;
+                                               nb.l = 1;
+                                               nb.i = (nb.n.param2 & LIQUID_INFINITY_MASK);
+                                       }
+                                       break;
+                               case LIQUID_FLOWING:
+                                       // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
+                                       if (liquid_kind_flowing == CONTENT_IGNORE)
+                                               liquid_kind_flowing = nb.n.getContent();
+                                       if (liquid_kind == CONTENT_IGNORE)
+                                               liquid_kind = nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_source);
+                                       if (nb.n.getContent() == liquid_kind_flowing) {
+                                               liquid_levels[i] = (nb.n.param2 & LIQUID_LEVEL_MASK);
+                                               nb.l = 1;
+                                       }
+                                       break;
+                       }
+                       if (nb.l && nb.t == NEIGHBOR_SAME_LEVEL) ++can_liquid_same_level;
+                       if (liquid_levels[i] > 0) total_level += liquid_levels[i];
+
+                       /*
+                       infostream << "get node i=" <<(int)i<<" " << PP(npos) << " c="<<nb.n.getContent() <<" p0="<< (int)nb.n.param0 <<" p1="<< (int)nb.n.param1 <<" p2="<< (int)nb.n.param2 << " lt="<<nodemgr->get(nb.n.getContent()).liquid_type
+                       //<< " lk=" << liquid_kind << " lkf=" << liquid_kind_flowing
+                       << " l="<< nb.l << " inf="<< nb.i << " nlevel=" <<  (int)liquid_levels[i] << " tlevel=" << (int)total_level << " cansame="<<(int)can_liquid_same_level<<std::endl;
+                       */
+               }
+
+               if (liquid_kind == CONTENT_IGNORE || !neighbors[D_SELF].l || total_level <= 0)
+                       continue;
+
+               // fill bottom block
+               if (neighbors[D_BOTTOM].l) {
+                       liquid_levels_want[D_BOTTOM] = total_level > LIQUID_LEVEL_SOURCE ? LIQUID_LEVEL_SOURCE : total_level;
+                       total_level -= liquid_levels_want[D_BOTTOM];
+               }
+
+               if (relax && p0.Y <= water_level && liquid_levels[D_TOP] == 0 && total_level >= LIQUID_LEVEL_SOURCE * can_liquid_same_level - can_liquid_same_level + 2 && can_liquid_same_level >= relax + 1) { //relax up
+                       total_level = LIQUID_LEVEL_SOURCE * can_liquid_same_level; 
+               }
+
+               // calculate self level 5 blocks
+               u8 want_level = 
+                         total_level >= LIQUID_LEVEL_SOURCE * can_liquid_same_level
+                       ? LIQUID_LEVEL_SOURCE 
+                       : total_level / can_liquid_same_level;
+               total_level -= want_level * can_liquid_same_level;
+
+               if (relax && p0.Y > water_level && liquid_levels[D_TOP] == 0 && liquid_levels[D_BOTTOM] == LIQUID_LEVEL_SOURCE && want_level == 0 && total_level <= can_liquid_same_level - 2 && can_liquid_same_level >= relax + 1) { //relax down
+                       total_level = 0;
+               }
+
+               for (u16 ii = D_SELF; ii < D_TOP; ++ii) { // fill only same level
+                       if (!neighbors[ii].l)
+                               continue;
+                       liquid_levels_want[ii] = want_level;
+                       if (liquid_levels_want[ii] < LIQUID_LEVEL_SOURCE && total_level > 0
+                               && liquid_levels[ii] > liquid_levels_want[ii]
+                               ) {
+                               ++liquid_levels_want[ii];
+                               --total_level;
+                       }
+               }
+
+               for (u16 ii = 0; ii < 7; ++ii) {
+                       if (total_level < 1) break;
+                       if (liquid_levels_want[ii] >= 0 && liquid_levels_want[ii] < LIQUID_LEVEL_SOURCE) {
+                               ++liquid_levels_want[ii];
+                               --total_level;
+                       }
+               }
+
+               // fill top block if can
+               if (neighbors[D_TOP].l) {
+                       liquid_levels_want[D_TOP] = total_level > LIQUID_LEVEL_SOURCE ? LIQUID_LEVEL_SOURCE : total_level ;
+                       total_level -= liquid_levels_want[D_TOP];
+               }
+
+               for (u16 ii = 0; ii < 7; ii++) // infinity and cave flood optimization
+                       if (liquid_levels_want[ii] >= 0 &&
+                               (neighbors[ii].i ||
+                                (fast_flood && p0.Y < water_level &&
+                                 (initial_size >= 1000
+                                  && ii != D_TOP
+                                  && want_level >= LIQUID_LEVEL_SOURCE/4
+                                  && can_liquid_same_level >= 5
+                                  && liquid_levels[D_TOP] >= LIQUID_LEVEL_SOURCE))))
+                               liquid_levels_want[ii] = LIQUID_LEVEL_SOURCE;
+
+               //if (total_level > 0 /*|| flowed != volume*/) infostream <<" AFTER level=" << (int)total_level /*<< " flowed="<<flowed<< " volume=" <<volume*/<< " wantsame="<<(int)want_level<< " top="<< (int)liquid_levels_want[D_TOP]<< " topwas="<< (int)liquid_levels[D_TOP]<< " bot="<< (int)liquid_levels_want[D_BOTTOM]<<std::endl;
+
+               u8 changed = 0;
+               for (u16 i = 0; i < 7; i++) {
+                       if (liquid_levels_want[i] < 0 || !neighbors[i].l) 
+                               continue;
+                       MapNode & n0 = neighbors[i].n;
+                       p0 = neighbors[i].p;
+                       /*
+                               decide on the type (and possibly level) of the current node
+                       */
+                       content_t new_node_content;
+                       s8 new_node_level = -1;
+                       u8 viscosity = nodemgr->get(liquid_kind).liquid_viscosity;
+                       if (viscosity > 1 && liquid_levels_want[i] != liquid_levels[i]) {
+                               // amount to gain, limited by viscosity
+                               // must be at least 1 in absolute value
+                               s8 level_inc = liquid_levels_want[i] - liquid_levels[i];
+                               if (level_inc < -viscosity || level_inc > viscosity)
+                                       new_node_level = liquid_levels[i] + level_inc/viscosity;
+                               else if (level_inc < 0)
+                                       new_node_level = liquid_levels[i] - 1;
+                               else if (level_inc > 0)
+                                       new_node_level = liquid_levels[i] + 1;
+                       } else
+                               new_node_level = liquid_levels_want[i];
+                       if (new_node_level >= LIQUID_LEVEL_SOURCE)
+                               new_node_content = liquid_kind;
+                       else if (new_node_level > 0)
+                               new_node_content = liquid_kind_flowing;
+                       else
+                               new_node_content = CONTENT_AIR;
+
+                       // last level must flow down on stairs
+                       if (liquid_levels_want[i] != liquid_levels[i] && liquid_levels[D_TOP] <= 0 && !neighbors[D_BOTTOM].l && new_node_level >= 1 && new_node_level <= 2) //maybe == 1 // 
+                               for (u16 ii = D_SELF + 1; ii < D_TOP; ++ii) { // only same level
+                               if (!neighbors[ii].l)
+                                       continue;
+                               must_reflow_second.push_back(p0 + dirs[ii]);
+                       }
+
+                       /*
+                               check if anything has changed. if not, just continue with the next node.
+                        */
+                       if (
+                                new_node_content == n0.getContent() 
+                               && (nodemgr->get(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
+                                ))
+                               &&
+                                (nodemgr->get(n0.getContent()).liquid_type != LIQUID_SOURCE ||
+                                (((n0.param2 & LIQUID_INFINITY_MASK) == LIQUID_INFINITY_MASK) == neighbors[i].i
+                                ))
+                          ) {
+                               continue;
+                       }
+                       ++changed;
+
+                       /*
+                               update the current node
+                        */
+                       if (nodemgr->get(new_node_content).liquid_type == LIQUID_FLOWING) {
+                               // set level to last 3 bits, flowing down bit to 4th bit
+                               n0.param2 = (new_node_level & LIQUID_LEVEL_MASK);
+                       } else if (nodemgr->get(new_node_content).liquid_type == LIQUID_SOURCE) {
+                               //n0.param2 = ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK);
+                               n0.param2 = (neighbors[i].i ? LIQUID_INFINITY_MASK : 0x00);
+                       }
+                       //infostream << "set node i=" <<(int)i<<" "<< PP(p0)<< " nc="<<new_node_content<< " p2="<<(int)n0.param2<< " nl="<<(int)new_node_level<<std::endl;
+                       n0.setContent(new_node_content);
+                       // Find out whether there is a suspect for this action
+                       std::string suspect;
+                       if(m_gamedef->rollback()){
+                               suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
+                       }
+
+                       if(!suspect.empty()){
+                               // Blame suspect
+                               RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
+                               // Get old node for rollback
+                               RollbackNode rollback_oldnode(this, p0, m_gamedef);
+                               // Set node
+                               setNode(p0, n0);
+                               // Report
+                               RollbackNode rollback_newnode(this, p0, m_gamedef);
+                               RollbackAction action;
+                               action.setSetNode(p0, rollback_oldnode, rollback_newnode);
+                               m_gamedef->rollback()->reportAction(action);
+                       } else {
+                               // Set node
+                               setNode(p0, n0);
+                       }
+
+                       v3s16 blockpos = getNodeBlockPos(p0);
+                       MapBlock *block = getBlockNoCreateNoEx(blockpos);
+                       if(block != NULL) {
+                               modified_blocks.insert(blockpos, block);
+                               // If node emits light, MapBlock requires lighting update
+                               if(nodemgr->get(n0).light_source != 0)
+                                       lighting_modified_blocks[block->getPos()] = block;
+                       }
+                       must_reflow.push_back(neighbors[i].p);
+               }
+               /* //for better relax
+               if (changed)  for (u16 ii = D_SELF + 1; ii < D_TOP; ++ii) { // only same level
+                       if (!neighbors[ii].l) continue;
+                       must_reflow.push_back(p0 + dirs[ii]);
+               }*/
+       }
+       //if (loopcount) infostream<<"Map::transformLiquids(): loopcount="<<loopcount<<" reflow="<<must_reflow.size()<<" queue="<< m_transforming_liquid.size()<<std::endl;
+       while (must_reflow.size() > 0)
+               m_transforming_liquid.push_back(must_reflow.pop_front());
+       while (must_reflow_second.size() > 0)
+               m_transforming_liquid.push_back(must_reflow_second.pop_front());
+       updateLighting(lighting_modified_blocks, modified_blocks);
+}
+
 void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
 {
+
+       if (g_settings->getBool("liquid_finite")) return Map::transformLiquidsFinite(modified_blocks);
+       
        INodeDefManager *nodemgr = m_gamedef->ndef();
 
        DSTACK(__FUNCTION_NAME);
index 420fc29ca9a1036a32ac4a6676b274ae055dc0bc..a0305b790e7f6c58b78ba5f1a21d9bc9443f2321 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -300,6 +300,7 @@ public:
        virtual void PrintInfo(std::ostream &out);
 
        void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
+       void transformLiquidsFinite(core::map<v3s16, MapBlock*> & modified_blocks);
 
        /*
                Node metadata
@@ -328,6 +329,9 @@ public:
                Variables
        */
 
+       void transforming_liquid_add(v3s16 p);
+       s32 transforming_liquid_size();
+
 protected:
 
        std::ostream &m_dout; // A bit deprecated, could be removed
index de2529e4d12279823752d64756753bf546913670..56dfa6310b3bb6ba6931a2edf59a68f604a69907 100644 (file)
@@ -67,10 +67,15 @@ enum LightBank
 #define LIQUID_LEVEL_MASK 0x07
 #define LIQUID_FLOW_DOWN_MASK 0x08
 
+//#define LIQUID_LEVEL_MASK 0x3f // better finite water
+//#define LIQUID_FLOW_DOWN_MASK 0x40 // not used when finite water
+
 /* maximum amount of liquid in a block */
 #define LIQUID_LEVEL_MAX LIQUID_LEVEL_MASK
 #define LIQUID_LEVEL_SOURCE (LIQUID_LEVEL_MAX+1)
 
+#define LIQUID_INFINITY_MASK 0x80 //0b10000000
+
 /*
        This is the stuff what the whole world consists of.
 */
index 94a4787f88f27892831bc5639dfb43c2ffa4860f..138f288c6c8dc8308536f92c75d0259398d8c6fa 100644 (file)
@@ -961,6 +961,7 @@ Server::Server(
        m_ignore_map_edit_events_peer_id(0)
 {
        m_liquid_transform_timer = 0.0;
+       m_liquid_transform_every = 1.0;
        m_print_info_timer = 0.0;
        m_masterserver_timer = 0.0;
        m_objectdata_timer = 0.0;
@@ -1136,6 +1137,8 @@ Server::Server(
                Add some test ActiveBlockModifiers to environment
        */
        add_legacy_abms(m_env, m_nodedef);
+
+       m_liquid_transform_every = g_settings->getFloat("liquid_update");
 }
 
 Server::~Server()
@@ -1452,9 +1455,9 @@ void Server::AsyncRunStep()
 
        /* Transform liquids */
        m_liquid_transform_timer += dtime;
-       if(m_liquid_transform_timer >= 1.00)
+       if(m_liquid_transform_timer >= m_liquid_transform_every)
        {
-               m_liquid_transform_timer -= 1.00;
+               m_liquid_transform_timer -= m_liquid_transform_every;
 
                JMutexAutoLock lock(m_env_mutex);
 
index 22c7cf2bbf45615ac4a534d5b071cd51e61f7986..16bda43722bb66f80b249da0e76d163cfa308b83 100644 (file)
@@ -719,6 +719,7 @@ private:
 
        // Some timers
        float m_liquid_transform_timer;
+       float m_liquid_transform_every;
        float m_print_info_timer;
        float m_masterserver_timer;
        float m_objectdata_timer;