]> git.lizzy.rs Git - minetest.git/commitdiff
Split liquid_viscosity to liquid_viscosity and move_resistance (#10810)
authorWuzzy <wuzzy2@mail.ru>
Fri, 1 Oct 2021 14:21:24 +0000 (14:21 +0000)
committerGitHub <noreply@github.com>
Fri, 1 Oct 2021 14:21:24 +0000 (16:21 +0200)
15 files changed:
doc/client_lua_api.txt
doc/lua_api.txt
games/devtest/mods/testnodes/liquids.lua
games/devtest/mods/testnodes/properties.lua
games/devtest/mods/testnodes/textures/testnodes_climbable_resistance_side.png [new file with mode: 0644]
games/devtest/mods/testnodes/textures/testnodes_move_resistance.png [new file with mode: 0644]
src/client/clientenvironment.cpp
src/client/localplayer.cpp
src/client/localplayer.h
src/nodedef.cpp
src/nodedef.h
src/script/common/c_content.cpp
src/script/cpp_api/s_node.h
src/script/lua_api/l_localplayer.cpp
src/script/lua_api/l_localplayer.h

index 24d23b0b5f6dfeb05e59196169945c1202eb9ed9..32be8c849f82df4d18f930c77eb07b8d4643bacf 100644 (file)
@@ -1030,8 +1030,8 @@ Methods:
     * returns true if player is in a liquid (This oscillates so that the player jumps a bit above the surface)
 * `is_in_liquid_stable()`
     * returns true if player is in a stable liquid (This is more stable and defines the maximum speed of the player)
-* `get_liquid_viscosity()`
-    * returns liquid viscosity (Gets the viscosity of liquid to calculate friction)
+* `get_move_resistance()`
+    * returns move resistance of current node, the higher the slower the player moves
 * `is_climbing()`
     * returns true if player is climbing
 * `swimming_vertical()`
@@ -1233,7 +1233,7 @@ It can be created via `Raycast(pos1, pos2, objects, liquids)` or
                liquid_type = <string>,         -- A string containing "none", "flowing", or "source" *May not exist*
                liquid_alternative_flowing = <string>, -- Alternative node for liquid *May not exist*
                liquid_alternative_source = <string>, -- Alternative node for liquid *May not exist*
-               liquid_viscosity = <number>,    -- How fast the liquid flows *May not exist*
+               liquid_viscosity = <number>,    -- How slow the liquid flows *May not exist*
                liquid_renewable = <boolean>,   -- Whether the liquid makes an infinite source *May not exist*
                liquid_range = <number>,        -- How far the liquid flows *May not exist*
                drowning = bool,                -- Whether the player will drown in the node
@@ -1248,6 +1248,7 @@ It can be created via `Raycast(pos1, pos2, objects, liquids)` or
                },
                legacy_facedir_simple = bool,   -- Whether to use old facedir
                legacy_wallmounted = bool       -- Whether to use old wallmounted
+               move_resistance = <number>,     -- How slow players can move through the node *May not exist*
        }
 ```
 
index 4fab78841bbc3e1dc7d3dcc084fefa900041402e..9efe1afe7e22372c328e553802e8a533d01996f2 100644 (file)
@@ -1804,7 +1804,7 @@ to games.
       - (14)                                           -- constant tolerance
   Negative damage values are discarded as no damage.
 * `falling_node`: if there is no walkable block under the node it will fall
-* `float`: the node will not fall through liquids
+* `float`: the node will not fall through liquids (`liquidtype ~= "none"`)
 * `level`: Can be used to give an additional sense of progression in the game.
      * A larger level will cause e.g. a weapon of a lower level make much less
        damage, and get worn out much faster, or not be able to get drops
@@ -4147,7 +4147,7 @@ differences:
 
 ### Other API functions operating on a VoxelManip
 
-If any VoxelManip contents were set to a liquid node,
+If any VoxelManip contents were set to a liquid node (`liquidtype ~= "none"`),
 `VoxelManip:update_liquids()` must be called for these liquid nodes to begin
 flowing. It is recommended to call this function only after having written all
 buffered data back to the VoxelManip object, save for special situations where
@@ -4958,8 +4958,8 @@ Call these functions only at load time!
     * You should have joined some channels to receive events.
     * If message comes from a server mod, `sender` field is an empty string.
 * `minetest.register_on_liquid_transformed(function(pos_list, node_list))`
-    * Called after liquid nodes are modified by the engine's liquid transformation
-      process.
+    * Called after liquid nodes (`liquidtype ~= "none"`) are modified by the
+      engine's liquid transformation process.
     * `pos_list` is an array of all modified positions.
     * `node_list` is an array of the old node that was previously at the position
       with the corresponding index in pos_list.
@@ -5301,7 +5301,8 @@ Environment access
     * `pos1`: start of the ray
     * `pos2`: end of the ray
     * `objects`: if false, only nodes will be returned. Default is `true`.
-    * `liquids`: if false, liquid nodes won't be returned. Default is `false`.
+    * `liquids`: if false, liquid nodes (`liquidtype ~= "none"`) won't be
+                 returned. Default is `false`.
 * `minetest.find_path(pos1,pos2,searchdistance,max_jump,max_drop,algorithm)`
     * returns table containing path that can be walked on
     * returns a table of 3D points representing a path from `pos1` to `pos2` or
@@ -5325,7 +5326,7 @@ Environment access
 * `minetest.spawn_tree (pos, {treedef})`
     * spawns L-system tree at given `pos` with definition in `treedef` table
 * `minetest.transforming_liquid_add(pos)`
-    * add node to liquid update queue
+    * add node to liquid flow update queue
 * `minetest.get_node_max_level(pos)`
     * get max available level for leveled node
 * `minetest.get_node_level(pos)`
@@ -6978,7 +6979,8 @@ It can be created via `Raycast(pos1, pos2, objects, liquids)` or
 * `pos1`: start of the ray
 * `pos2`: end of the ray
 * `objects`: if false, only nodes will be returned. Default is true.
-* `liquids`: if false, liquid nodes won't be returned. Default is false.
+* `liquids`: if false, liquid nodes (`liquidtype ~= "none"`) won't be
+             returned. Default is false.
 
 ### Methods
 
@@ -7462,6 +7464,8 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and
         range = 4.0,
 
         liquids_pointable = false,
+        -- If true, item points to all liquid nodes (`liquidtype ~= "none"`),
+        -- even those for which `pointable = false`
 
         light_source = 0,
         -- When used for nodes: Defines amount of light emitted by node.
@@ -7647,14 +7651,21 @@ Used by `minetest.register_node`.
 
         climbable = false,  -- If true, can be climbed on (ladder)
 
+        move_resistance = 0,
+        -- Slows down movement of players through this node (max. 7).
+        -- If this is nil, it will be equal to liquid_viscosity.
+        -- Note: If liquid movement physics apply to the node
+        -- (see `liquid_move_physics`), the movement speed will also be
+        -- affected by the `movement_liquid_*` settings.
+
         buildable_to = false,  -- If true, placed nodes can replace this node
 
         floodable = false,
         -- If true, liquids flow into and replace this node.
         -- Warning: making a liquid node 'floodable' will cause problems.
 
-        liquidtype = "none",  -- specifies liquid physics
-        -- * "none":    no liquid physics
+        liquidtype = "none",  -- specifies liquid flowing physics
+        -- * "none":    no liquid flowing physics
         -- * "source":  spawns flowing liquid nodes at all 4 sides and below;
         --              recommended drawtype: "liquid".
         -- * "flowing": spawned from source, spawns more flowing liquid nodes
@@ -7668,12 +7679,26 @@ Used by `minetest.register_node`.
 
         liquid_alternative_source = "",  -- Source version of flowing liquid
 
-        liquid_viscosity = 0,  -- Higher viscosity = slower flow (max. 7)
+        liquid_viscosity = 0,
+        -- Controls speed at which the liquid spreads/flows (max. 7).
+        -- 0 is fastest, 7 is slowest.
+        -- By default, this also slows down movement of players inside the node
+        -- (can be overridden using `move_resistance`)
 
         liquid_renewable = true,
         -- If true, a new liquid source can be created by placing two or more
         -- sources nearby
 
+        liquid_move_physics = nil, -- specifies movement physics if inside node
+        -- * false: No liquid movement physics apply.
+        -- * true: Enables liquid movement physics. Enables things like
+        --   ability to "swim" up/down, sinking slowly if not moving,
+        --   smoother speed change when falling into, etc. The `movement_liquid_*`
+        --   settings apply.
+        -- * nil: Will be treated as true if `liquidype ~= "none"`
+        --   and as false otherwise.
+        -- Default: nil
+
         leveled = 0,
         -- Only valid for "nodebox" drawtype with 'type = "leveled"'.
         -- Allows defining the nodebox height without using param2.
index 3d2ea17f5e65c50f7d18fadded605c574ce8a49b..be33814af81b4f6d95e3d1d78d330e5af1c2f9fc 100644 (file)
@@ -40,9 +40,11 @@ for d=0, 8 do
                liquid_range = d,
        })
 
+       if d <= 7 then
+
        local mod = "^[colorize:#000000:127"
        minetest.register_node("testnodes:vliquid_"..d, {
-               description = "Test Liquid Source, Viscosity "..d,
+               description = "Test Liquid Source, Viscosity/Resistance "..d,
                drawtype = "liquid",
                tiles = {"testnodes_liquidsource_r"..d..".png"..mod},
                special_tiles = {
@@ -61,7 +63,7 @@ for d=0, 8 do
        })
 
        minetest.register_node("testnodes:vliquid_flowing_"..d, {
-               description = "Flowing Test Liquid, Viscosity "..d,
+               description = "Flowing Test Liquid, Viscosity/Resistance "..d,
                drawtype = "flowingliquid",
                tiles = {"testnodes_liquidflowing_r"..d..".png"..mod},
                special_tiles = {
@@ -80,4 +82,53 @@ for d=0, 8 do
                liquid_viscosity = d,
        })
 
+       mod = "^[colorize:#000000:192"
+       local v = 4
+       minetest.register_node("testnodes:vrliquid_"..d, {
+               description = "Test Liquid Source, Viscosity "..v..", Resistance "..d,
+               drawtype = "liquid",
+               tiles = {"testnodes_liquidsource_r"..d..".png"..mod},
+               special_tiles = {
+                       {name = "testnodes_liquidsource_r"..d..".png"..mod, backface_culling = false},
+                       {name = "testnodes_liquidsource_r"..d..".png"..mod, backface_culling = true},
+               },
+               use_texture_alpha = "blend",
+               paramtype = "light",
+               walkable = false,
+               pointable = false,
+               diggable = false,
+               buildable_to = true,
+               is_ground_content = false,
+               liquidtype = "source",
+               liquid_alternative_flowing = "testnodes:vrliquid_flowing_"..d,
+               liquid_alternative_source = "testnodes:vrliquid_"..d,
+               liquid_viscosity = v,
+               move_resistance = d,
+       })
+
+       minetest.register_node("testnodes:vrliquid_flowing_"..d, {
+               description = "Flowing Test Liquid, Viscosity "..v..", Resistance "..d,
+               drawtype = "flowingliquid",
+               tiles = {"testnodes_liquidflowing_r"..d..".png"..mod},
+               special_tiles = {
+                       {name = "testnodes_liquidflowing_r"..d..".png"..mod, backface_culling = false},
+                       {name = "testnodes_liquidflowing_r"..d..".png"..mod, backface_culling = false},
+               },
+               use_texture_alpha = "blend",
+               paramtype = "light",
+               paramtype2 = "flowingliquid",
+               walkable = false,
+               pointable = false,
+               diggable = false,
+               buildable_to = true,
+               is_ground_content = false,
+               liquidtype = "flowing",
+               liquid_alternative_flowing = "testnodes:vrliquid_flowing_"..d,
+               liquid_alternative_source = "testnodes:vrliquid_"..d,
+               liquid_viscosity = v,
+               move_resistance = d,
+       })
+
+       end
+
 end
index a52cd1d6fa8e2778f8733cd0514b56e8b1ee28dd..51f703d7c22afe513d3393b9c22abc0198e82497 100644 (file)
@@ -152,6 +152,66 @@ minetest.register_node("testnodes:liquidflowing_nojump", {
        post_effect_color = {a = 70, r = 255, g = 0, b = 200},
 })
 
+-- A liquid which doesn't have liquid movement physics (source variant)
+minetest.register_node("testnodes:liquid_noswim", {
+       description = S("No-swim Liquid Source Node"),
+       liquidtype = "source",
+       liquid_range = 1,
+       liquid_viscosity = 0,
+       liquid_alternative_flowing = "testnodes:liquidflowing_noswim",
+       liquid_alternative_source = "testnodes:liquid_noswim",
+       liquid_renewable = false,
+       liquid_move_physics = false,
+       groups = {dig_immediate=3},
+       walkable = false,
+
+       drawtype = "liquid",
+       tiles = {"testnodes_liquidsource.png^[colorize:#FF00FF:127"},
+       special_tiles = {
+               {name = "testnodes_liquidsource.png^[colorize:#FF00FF:127", backface_culling = false},
+               {name = "testnodes_liquidsource.png^[colorize:#FF00FF:127", backface_culling = true},
+       },
+       use_texture_alpha = "blend",
+       paramtype = "light",
+       pointable = false,
+       liquids_pointable = true,
+       buildable_to = true,
+       is_ground_content = false,
+       post_effect_color = {a = 70, r = 255, g = 200, b = 200},
+})
+
+-- A liquid which doen't have liquid movement physics (flowing variant)
+minetest.register_node("testnodes:liquidflowing_noswim", {
+       description = S("No-swim Flowing Liquid Node"),
+       liquidtype = "flowing",
+       liquid_range = 1,
+       liquid_viscosity = 0,
+       liquid_alternative_flowing = "testnodes:liquidflowing_noswim",
+       liquid_alternative_source = "testnodes:liquid_noswim",
+       liquid_renewable = false,
+       liquid_move_physics = false,
+       groups = {dig_immediate=3},
+       walkable = false,
+
+
+       drawtype = "flowingliquid",
+       tiles = {"testnodes_liquidflowing.png^[colorize:#FF00FF:127"},
+       special_tiles = {
+               {name = "testnodes_liquidflowing.png^[colorize:#FF00FF:127", backface_culling = false},
+               {name = "testnodes_liquidflowing.png^[colorize:#FF00FF:127", backface_culling = false},
+       },
+       use_texture_alpha = "blend",
+       paramtype = "light",
+       paramtype2 = "flowingliquid",
+       pointable = false,
+       liquids_pointable = true,
+       buildable_to = true,
+       is_ground_content = false,
+       post_effect_color = {a = 70, r = 255, g = 200, b = 200},
+})
+
+
+
 -- Nodes that modify fall damage (various damage modifiers)
 for i=-100, 100, 25 do
        if i ~= 0 then
@@ -216,6 +276,54 @@ for i=1, 5 do
        })
 end
 
+-- Move resistance nodes (various resistance levels)
+for r=0, 7 do
+       if r > 0 then
+               minetest.register_node("testnodes:move_resistance"..r, {
+                       description = S("Move-resistant Node (@1)", r),
+                       walkable = false,
+                       move_resistance = r,
+
+                       drawtype = "glasslike",
+                       paramtype = "light",
+                       sunlight_propagates = true,
+                       tiles = { "testnodes_move_resistance.png" },
+                       is_ground_content = false,
+                       groups = { dig_immediate = 3 },
+                       color = { b = 0, g = 255, r = math.floor((r/7)*255), a = 255 },
+               })
+       end
+
+       minetest.register_node("testnodes:move_resistance_liquidlike"..r, {
+               description = S("Move-resistant Node, liquidlike (@1)", r),
+               walkable = false,
+               move_resistance = r,
+               liquid_move_physics = true,
+
+               drawtype = "glasslike",
+               paramtype = "light",
+               sunlight_propagates = true,
+               tiles = { "testnodes_move_resistance.png" },
+               is_ground_content = false,
+               groups = { dig_immediate = 3 },
+               color = { b = 255, g = 0, r = math.floor((r/7)*255), a = 255 },
+       })
+end
+
+minetest.register_node("testnodes:climbable_move_resistance_4", {
+       description = S("Climbable Move-resistant Node (4)"),
+       walkable = false,
+       climbable = true,
+       move_resistance = 4,
+
+       drawtype = "glasslike",
+       paramtype = "light",
+       sunlight_propagates = true,
+       tiles = {"testnodes_climbable_resistance_side.png"},
+       is_ground_content = false,
+       groups = { dig_immediate = 3 },
+})
+
 -- By placing something on the node, the node itself will be replaced
 minetest.register_node("testnodes:buildable_to", {
        description = S("Replacable Node"),
diff --git a/games/devtest/mods/testnodes/textures/testnodes_climbable_resistance_side.png b/games/devtest/mods/testnodes/textures/testnodes_climbable_resistance_side.png
new file mode 100644 (file)
index 0000000..be01583
Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_climbable_resistance_side.png differ
diff --git a/games/devtest/mods/testnodes/textures/testnodes_move_resistance.png b/games/devtest/mods/testnodes/textures/testnodes_move_resistance.png
new file mode 100644 (file)
index 0000000..cac3944
Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_move_resistance.png differ
index 7e3867537001ed30529aa8c7f60c55c703c484bc..448af36c6596e982a144d16958db7eed0ed41a65 100644 (file)
@@ -194,32 +194,41 @@ void ClientEnvironment::step(float dtime)
                lplayer->applyControl(dtime_part, this);
 
                // Apply physics
-               if (!free_move && !is_climbing) {
+               if (!free_move) {
                        // Gravity
                        v3f speed = lplayer->getSpeed();
-                       if (!lplayer->in_liquid)
+                       if (!is_climbing && !lplayer->in_liquid)
                                speed.Y -= lplayer->movement_gravity *
                                        lplayer->physics_override_gravity * dtime_part * 2.0f;
 
                        // Liquid floating / sinking
-                       if (lplayer->in_liquid && !lplayer->swimming_vertical &&
+                       if (!is_climbing && lplayer->in_liquid &&
+                                       !lplayer->swimming_vertical &&
                                        !lplayer->swimming_pitch)
                                speed.Y -= lplayer->movement_liquid_sink * dtime_part * 2.0f;
 
-                       // Liquid resistance
-                       if (lplayer->in_liquid_stable || lplayer->in_liquid) {
-                               // How much the node's viscosity blocks movement, ranges
-                               // between 0 and 1. Should match the scale at which viscosity
+                       // Movement resistance
+                       if (lplayer->move_resistance > 0) {
+                               // How much the node's move_resistance blocks movement, ranges
+                               // between 0 and 1. Should match the scale at which liquid_viscosity
                                // increase affects other liquid attributes.
-                               static const f32 viscosity_factor = 0.3f;
-
-                               v3f d_wanted = -speed / lplayer->movement_liquid_fluidity;
+                               static const f32 resistance_factor = 0.3f;
+
+                               v3f d_wanted;
+                               bool in_liquid_stable = lplayer->in_liquid_stable || lplayer->in_liquid;
+                               if (in_liquid_stable) {
+                                       d_wanted = -speed / lplayer->movement_liquid_fluidity;
+                               } else {
+                                       d_wanted = -speed / BS;
+                               }
                                f32 dl = d_wanted.getLength();
-                               if (dl > lplayer->movement_liquid_fluidity_smooth)
-                                       dl = lplayer->movement_liquid_fluidity_smooth;
+                               if (in_liquid_stable) {
+                                       if (dl > lplayer->movement_liquid_fluidity_smooth)
+                                               dl = lplayer->movement_liquid_fluidity_smooth;
+                               }
 
-                               dl *= (lplayer->liquid_viscosity * viscosity_factor) +
-                                       (1 - viscosity_factor);
+                               dl *= (lplayer->move_resistance * resistance_factor) +
+                                       (1 - resistance_factor);
                                v3f d = d_wanted.normalize() * (dl * dtime_part * 100.0f);
                                speed += d;
                        }
index 2d4f7305a6d4b7fdd5974d2ff606db07768c8806..3f78d201d366e3e81804983f061786facfe700fd 100644 (file)
@@ -227,8 +227,9 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
                pp = floatToInt(position + v3f(0.0f, BS * 0.1f, 0.0f), BS);
                node = map->getNode(pp, &is_valid_position);
                if (is_valid_position) {
-                       in_liquid = nodemgr->get(node.getContent()).isLiquid();
-                       liquid_viscosity = nodemgr->get(node.getContent()).liquid_viscosity;
+                       const ContentFeatures &cf = nodemgr->get(node.getContent());
+                       in_liquid = cf.liquid_move_physics;
+                       move_resistance = cf.move_resistance;
                } else {
                        in_liquid = false;
                }
@@ -238,8 +239,9 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
                pp = floatToInt(position + v3f(0.0f, BS * 0.5f, 0.0f), BS);
                node = map->getNode(pp, &is_valid_position);
                if (is_valid_position) {
-                       in_liquid = nodemgr->get(node.getContent()).isLiquid();
-                       liquid_viscosity = nodemgr->get(node.getContent()).liquid_viscosity;
+                       const ContentFeatures &cf = nodemgr->get(node.getContent());
+                       in_liquid = cf.liquid_move_physics;
+                       move_resistance = cf.move_resistance;
                } else {
                        in_liquid = false;
                }
@@ -252,7 +254,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
        pp = floatToInt(position + v3f(0.0f), BS);
        node = map->getNode(pp, &is_valid_position);
        if (is_valid_position) {
-               in_liquid_stable = nodemgr->get(node.getContent()).isLiquid();
+               in_liquid_stable = nodemgr->get(node.getContent()).liquid_move_physics;
        } else {
                in_liquid_stable = false;
        }
@@ -800,8 +802,9 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
                pp = floatToInt(position + v3f(0.0f, BS * 0.1f, 0.0f), BS);
                node = map->getNode(pp, &is_valid_position);
                if (is_valid_position) {
-                       in_liquid = nodemgr->get(node.getContent()).isLiquid();
-                       liquid_viscosity = nodemgr->get(node.getContent()).liquid_viscosity;
+                       const ContentFeatures &cf = nodemgr->get(node.getContent());
+                       in_liquid = cf.liquid_move_physics;
+                       move_resistance = cf.move_resistance;
                } else {
                        in_liquid = false;
                }
@@ -810,8 +813,9 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
                pp = floatToInt(position + v3f(0.0f, BS * 0.5f, 0.0f), BS);
                node = map->getNode(pp, &is_valid_position);
                if (is_valid_position) {
-                       in_liquid = nodemgr->get(node.getContent()).isLiquid();
-                       liquid_viscosity = nodemgr->get(node.getContent()).liquid_viscosity;
+                       const ContentFeatures &cf = nodemgr->get(node.getContent());
+                       in_liquid = cf.liquid_move_physics;
+                       move_resistance = cf.move_resistance;
                } else {
                        in_liquid = false;
                }
@@ -823,7 +827,7 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
        pp = floatToInt(position + v3f(0.0f), BS);
        node = map->getNode(pp, &is_valid_position);
        if (is_valid_position)
-               in_liquid_stable = nodemgr->get(node.getContent()).isLiquid();
+               in_liquid_stable = nodemgr->get(node.getContent()).liquid_move_physics;
        else
                in_liquid_stable = false;
 
index 345aec9d99e10321a3634a57899cedc50f792a79..13b35ae4e1f1ac611ff8ac38a48fae232190b30c 100644 (file)
@@ -55,8 +55,8 @@ class LocalPlayer : public Player
        bool in_liquid = false;
        // This is more stable and defines the maximum speed of the player
        bool in_liquid_stable = false;
-       // Gets the viscosity of water to calculate friction
-       u8 liquid_viscosity = 0;
+       // Slows down the player when moving through
+       u8 move_resistance = 0;
        bool is_climbing = false;
        bool swimming_vertical = false;
        bool swimming_pitch = false;
index db4043aa159c390b235d92ca25f646d4ba55c154..703df4dee0da8c8bee0d93a57bee5766c2a9cbef 100644 (file)
@@ -403,6 +403,8 @@ void ContentFeatures::reset()
        palette_name = "";
        palette = NULL;
        node_dig_prediction = "air";
+       move_resistance = 0;
+       liquid_move_physics = false;
 }
 
 void ContentFeatures::setAlphaFromLegacy(u8 legacy_alpha)
@@ -512,9 +514,12 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
        writeU8(os, legacy_facedir_simple);
        writeU8(os, legacy_wallmounted);
 
+       // new attributes
        os << serializeString16(node_dig_prediction);
        writeU8(os, leveled_max);
        writeU8(os, alpha);
+       writeU8(os, move_resistance);
+       writeU8(os, liquid_move_physics);
 }
 
 void ContentFeatures::deSerialize(std::istream &is)
@@ -584,9 +589,11 @@ void ContentFeatures::deSerialize(std::istream &is)
 
        // liquid
        liquid_type = (enum LiquidType) readU8(is);
+       liquid_move_physics = liquid_type != LIQUID_NONE;
        liquid_alternative_flowing = deSerializeString16(is);
        liquid_alternative_source = deSerializeString16(is);
        liquid_viscosity = readU8(is);
+       move_resistance = liquid_viscosity; // set default move_resistance
        liquid_renewable = readU8(is);
        liquid_range = readU8(is);
        drowning = readU8(is);
@@ -618,6 +625,16 @@ void ContentFeatures::deSerialize(std::istream &is)
                if (is.eof())
                        throw SerializationError("");
                alpha = static_cast<enum AlphaMode>(tmp);
+
+               tmp = readU8(is);
+               if (is.eof())
+                       throw SerializationError("");
+               move_resistance = tmp;
+
+               tmp = readU8(is);
+               if (is.eof())
+                       throw SerializationError("");
+               liquid_move_physics = tmp;
        } catch(SerializationError &e) {};
 }
 
index 8a6d88071f1fe31935c46a1929b41509f6704326..ea50d428137e14034d799fe5ca52191a057f7504 100644 (file)
@@ -376,11 +376,15 @@ struct ContentFeatures
        u32 damage_per_second;
        // client dig prediction
        std::string node_dig_prediction;
+       // how slow players move through
+       u8 move_resistance = 0;
 
        // --- LIQUID PROPERTIES ---
 
        // Whether the node is non-liquid, source liquid or flowing liquid
        enum LiquidType liquid_type;
+       // If true, movement (e.g. of players) inside this node is liquid-like.
+       bool liquid_move_physics;
        // If the content is liquid, this is the flowing version of the liquid.
        std::string liquid_alternative_flowing;
        content_t liquid_alternative_flowing_id;
index 5a095fd8f1fb57f0f1247f6e26bc3bec8ea770ff..8a5a3fe711fe157e05bca4e598daa9ace0088a96 100644 (file)
@@ -719,6 +719,9 @@ void read_content_features(lua_State *L, ContentFeatures &f, int index)
        // the slowest possible
        f.liquid_viscosity = getintfield_default(L, index,
                        "liquid_viscosity", f.liquid_viscosity);
+       // If move_resistance is not set explicitly,
+       // move_resistance is equal to liquid_viscosity
+       f.move_resistance = f.liquid_viscosity;
        f.liquid_range = getintfield_default(L, index,
                        "liquid_range", f.liquid_range);
        f.leveled = getintfield_default(L, index, "leveled", f.leveled);
@@ -822,6 +825,21 @@ void read_content_features(lua_State *L, ContentFeatures &f, int index)
        getstringfield(L, index, "node_dig_prediction",
                f.node_dig_prediction);
 
+       // How much the node slows down players, ranging from 1 to 7,
+       // the higher, the slower.
+       f.move_resistance = getintfield_default(L, index,
+                       "move_resistance", f.move_resistance);
+
+       // Whether e.g. players in this node will have liquid movement physics
+       lua_getfield(L, index, "liquid_move_physics");
+       if(lua_isboolean(L, -1)) {
+               f.liquid_move_physics = lua_toboolean(L, -1);
+       } else if(lua_isnil(L, -1)) {
+               f.liquid_move_physics = f.liquid_type != LIQUID_NONE;
+       } else {
+               errorstream << "Field \"liquid_move_physics\": Invalid type!" << std::endl;
+       }
+       lua_pop(L, 1);
 }
 
 void push_content_features(lua_State *L, const ContentFeatures &c)
@@ -949,6 +967,10 @@ void push_content_features(lua_State *L, const ContentFeatures &c)
        lua_setfield(L, -2, "legacy_wallmounted");
        lua_pushstring(L, c.node_dig_prediction.c_str());
        lua_setfield(L, -2, "node_dig_prediction");
+       lua_pushnumber(L, c.move_resistance);
+       lua_setfield(L, -2, "move_resistance");
+       lua_pushboolean(L, c.liquid_move_physics);
+       lua_setfield(L, -2, "liquid_move_physics");
 }
 
 /******************************************************************************/
index 3f771c838c335afa78adabf931a7a975d5bdc74d..3c6a8445b2da0957c664d4611ccaa0a5ecb0e455 100644 (file)
@@ -53,6 +53,7 @@ class ScriptApiNode
        static struct EnumString es_ContentParamType[];
        static struct EnumString es_ContentParamType2[];
        static struct EnumString es_LiquidType[];
+       static struct EnumString es_LiquidMoveType[];
        static struct EnumString es_NodeBoxType[];
        static struct EnumString es_TextureAlphaMode[];
 };
index 9f3569eccbe26d32530feefe6e9b6c493087abfb..bdbe98cb0422fa7705cb6279d95781a5ba1a5617 100644 (file)
@@ -128,11 +128,11 @@ int LuaLocalPlayer::l_is_in_liquid_stable(lua_State *L)
        return 1;
 }
 
-int LuaLocalPlayer::l_get_liquid_viscosity(lua_State *L)
+int LuaLocalPlayer::l_get_move_resistance(lua_State *L)
 {
        LocalPlayer *player = getobject(L, 1);
 
-       lua_pushinteger(L, player->liquid_viscosity);
+       lua_pushinteger(L, player->move_resistance);
        return 1;
 }
 
@@ -466,7 +466,6 @@ const luaL_Reg LuaLocalPlayer::methods[] = {
                luamethod(LuaLocalPlayer, is_touching_ground),
                luamethod(LuaLocalPlayer, is_in_liquid),
                luamethod(LuaLocalPlayer, is_in_liquid_stable),
-               luamethod(LuaLocalPlayer, get_liquid_viscosity),
                luamethod(LuaLocalPlayer, is_climbing),
                luamethod(LuaLocalPlayer, swimming_vertical),
                luamethod(LuaLocalPlayer, get_physics_override),
@@ -488,5 +487,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = {
                luamethod(LuaLocalPlayer, hud_change),
                luamethod(LuaLocalPlayer, hud_get),
 
+               luamethod(LuaLocalPlayer, get_move_resistance),
+
                {0, 0}
 };
index 4413f2bdb8facb02f861996c6cb8037888905e76..041545a49e7921cd51b680573a0f0416c4f50436 100644 (file)
@@ -51,7 +51,6 @@ class LuaLocalPlayer : public ModApiBase
        static int l_is_touching_ground(lua_State *L);
        static int l_is_in_liquid(lua_State *L);
        static int l_is_in_liquid_stable(lua_State *L);
-       static int l_get_liquid_viscosity(lua_State *L);
        static int l_is_climbing(lua_State *L);
        static int l_swimming_vertical(lua_State *L);
 
@@ -96,6 +95,8 @@ class LuaLocalPlayer : public ModApiBase
        // hud_get(self, id)
        static int l_hud_get(lua_State *L);
 
+       static int l_get_move_resistance(lua_State *L);
+
        LocalPlayer *m_localplayer = nullptr;
 
 public: