Add disable_jump to liquids and ladders (#7688)
authorSmallJoker <SmallJoker@users.noreply.github.com>
Mon, 10 Jun 2019 11:00:35 +0000 (13:00 +0200)
committerGitHub <noreply@github.com>
Mon, 10 Jun 2019 11:00:35 +0000 (13:00 +0200)
Remove second nodedef check by improving the colliding node detection
Also remove the 2nd check in old_move, correct standing node a bit

src/client/localplayer.cpp
src/client/localplayer.h
src/collision.cpp
src/collision.h

index dabeee6fedf2a326a55c833acef411096be1f924..0e273a16a4c7fd39cb966e72244771d8960a00a6 100644 (file)
@@ -170,8 +170,8 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
                std::vector<CollisionInfo> *collision_info)
 {
        if (!collision_info || collision_info->empty()) {
-               // Node below the feet, update each ClientEnvironment::step()
-               m_standing_node = floatToInt(m_position, BS) - v3s16(0, 1, 0);
+               // Node at feet position, update each ClientEnvironment::step()
+               m_standing_node = floatToInt(m_position, BS);
        }
 
        // Temporary option for old move code
@@ -309,7 +309,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
                        collision_info->push_back(colinfo);
 
                        if (colinfo.type != COLLISION_NODE ||
-                                       colinfo.new_speed.Y != 0 ||
+                                       colinfo.axis != COLLISION_AXIS_Y ||
                                        (could_sneak && m_sneak_node_exists))
                                continue;
 
@@ -320,6 +320,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
                        if (is_first || len < distance) {
                                m_standing_node = colinfo.node_p;
                                distance = len;
+                               is_first = false;
                        }
                }
        }
@@ -435,11 +436,11 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
                Check properties of the node on which the player is standing
        */
        const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(m_standing_node));
+
        // Determine if jumping is possible
-       m_can_jump = (touching_ground && !in_liquid && !is_climbing)
-                       || sneak_can_jump;
-       if (itemgroup_get(f.groups, "disable_jump"))
-               m_can_jump = false;
+       m_disable_jump = itemgroup_get(f.groups, "disable_jump");
+       m_can_jump = ((touching_ground && !is_climbing)
+                       || sneak_can_jump) && !m_disable_jump;
 
        // Jump key pressed while jumping off from a bouncy block
        if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") &&
@@ -636,18 +637,14 @@ void LocalPlayer::applyControl(float dtime, Environment *env)
                                setSpeed(speedJ);
                                m_client->getEventManager()->put(new SimpleTriggerEvent(MtEvent::PLAYER_JUMP));
                        }
-               }
-               else if(in_liquid)
-               {
-                       if(fast_climb)
+               } else if (in_liquid && !m_disable_jump) {
+                       if (fast_climb)
                                speedV.Y = movement_speed_fast;
                        else
                                speedV.Y = movement_speed_walk;
                        swimming_vertical = true;
-               }
-               else if(is_climbing)
-               {
-                       if(fast_climb)
+               } else if (is_climbing && !m_disable_jump) {
+                       if (fast_climb)
                                speedV.Y = movement_speed_fast;
                        else
                                speedV.Y = movement_speed_climb;
@@ -908,6 +905,12 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
                pos_max_d, m_collisionbox, player_stepheight, dtime,
                &position, &m_speed, accel_f);
 
+       // Positition was slightly changed; update standing node pos
+       if (touching_ground)
+               m_standing_node = floatToInt(m_position - v3f(0, 0.1f * BS, 0), BS);
+       else
+               m_standing_node = floatToInt(m_position, BS);
+
        /*
                If the player's feet touch the topside of any node, this is
                set to true.
@@ -1048,11 +1051,13 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
        /*
                Check properties of the node on which the player is standing
        */
-       const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(getStandingNodePos()));
+       const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(
+               getStandingNodePos()));
+
        // Determine if jumping is possible
-       m_can_jump = touching_ground && !in_liquid;
-       if (itemgroup_get(f.groups, "disable_jump"))
-               m_can_jump = false;
+       m_disable_jump = itemgroup_get(f.groups, "disable_jump");
+       m_can_jump = touching_ground && !m_disable_jump;
+
        // Jump key pressed while jumping off from a bouncy block
        if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") &&
                        m_speed.Y >= -0.5 * BS) {
index b1fc1fbc8be72be21b91c175c0154f745a6fca9b..84cfa583a31accecd3e65c071ce432641de3c030 100644 (file)
@@ -183,6 +183,7 @@ private:
        // ***** End of variables for temporary option *****
 
        bool m_can_jump = false;
+       bool m_disable_jump = false;
        u16 m_breath = PLAYER_MAX_BREATH_DEFAULT;
        f32 m_yaw = 0.0f;
        f32 m_pitch = 0.0f;
index a07899e652c7ec0d976ca79c30ab3923976a9f4e..b36cc89b093d0050a018bc10d6b420e158068b88 100644 (file)
@@ -59,7 +59,7 @@ struct NearbyCollisionInfo {
 // Checks for collision of a moving aabbox with a static aabbox
 // Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision
 // The time after which the collision occurs is stored in dtime.
-int axisAlignedCollision(
+CollisionAxis axisAlignedCollision(
                const aabb3f &staticbox, const aabb3f &movingbox,
                const v3f &speed, f32 d, f32 *dtime)
 {
@@ -86,11 +86,11 @@ int axisAlignedCollision(
                                        (relbox.MaxEdge.Y + speed.Y * (*dtime) > COLL_ZERO) &&
                                        (relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) &&
                                        (relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO))
-                               return 0;
+                               return COLLISION_AXIS_X;
                }
                else if(relbox.MinEdge.X > xsize)
                {
-                       return -1;
+                       return COLLISION_AXIS_NONE;
                }
        }
        else if(speed.X < 0) // Check for collision with X+ plane
@@ -101,11 +101,11 @@ int axisAlignedCollision(
                                        (relbox.MaxEdge.Y + speed.Y * (*dtime) > COLL_ZERO) &&
                                        (relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) &&
                                        (relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO))
-                               return 0;
+                               return COLLISION_AXIS_X;
                }
                else if(relbox.MaxEdge.X < 0)
                {
-                       return -1;
+                       return COLLISION_AXIS_NONE;
                }
        }
 
@@ -119,11 +119,11 @@ int axisAlignedCollision(
                                        (relbox.MaxEdge.X + speed.X * (*dtime) > COLL_ZERO) &&
                                        (relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) &&
                                        (relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO))
-                               return 1;
+                               return COLLISION_AXIS_Y;
                }
                else if(relbox.MinEdge.Y > ysize)
                {
-                       return -1;
+                       return COLLISION_AXIS_NONE;
                }
        }
        else if(speed.Y < 0) // Check for collision with Y+ plane
@@ -134,11 +134,11 @@ int axisAlignedCollision(
                                        (relbox.MaxEdge.X + speed.X * (*dtime) > COLL_ZERO) &&
                                        (relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) &&
                                        (relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO))
-                               return 1;
+                               return COLLISION_AXIS_Y;
                }
                else if(relbox.MaxEdge.Y < 0)
                {
-                       return -1;
+                       return COLLISION_AXIS_NONE;
                }
        }
 
@@ -152,11 +152,11 @@ int axisAlignedCollision(
                                        (relbox.MaxEdge.X + speed.X * (*dtime) > COLL_ZERO) &&
                                        (relbox.MinEdge.Y + speed.Y * (*dtime) < ysize) &&
                                        (relbox.MaxEdge.Y + speed.Y * (*dtime) > COLL_ZERO))
-                               return 2;
+                               return COLLISION_AXIS_Z;
                }
                //else if(relbox.MinEdge.Z > zsize)
                //{
-               //      return -1;
+               //      return COLLISION_AXIS_NONE;
                //}
        }
        else if(speed.Z < 0) // Check for collision with Z+ plane
@@ -167,15 +167,15 @@ int axisAlignedCollision(
                                        (relbox.MaxEdge.X + speed.X * (*dtime) > COLL_ZERO) &&
                                        (relbox.MinEdge.Y + speed.Y * (*dtime) < ysize) &&
                                        (relbox.MaxEdge.Y + speed.Y * (*dtime) > COLL_ZERO))
-                               return 2;
+                               return COLLISION_AXIS_Z;
                }
                //else if(relbox.MaxEdge.Z < 0)
                //{
-               //      return -1;
+               //      return COLLISION_AXIS_NONE;
                //}
        }
 
-       return -1;
+       return COLLISION_AXIS_NONE;
 }
 
 // Helper function:
@@ -442,7 +442,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
                movingbox.MinEdge += *pos_f;
                movingbox.MaxEdge += *pos_f;
 
-               int nearest_collided = -1;
+               CollisionAxis nearest_collided = COLLISION_AXIS_NONE;
                f32 nearest_dtime = dtime;
                int nearest_boxindex = -1;
 
@@ -457,7 +457,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
 
                        // Find nearest collision of the two boxes (raytracing-like)
                        f32 dtime_tmp;
-                       int collided = axisAlignedCollision(box_info.box,
+                       CollisionAxis collided = axisAlignedCollision(box_info.box,
                                        movingbox, *speed_f, d, &dtime_tmp);
 
                        if (collided == -1 || dtime_tmp >= nearest_dtime)
@@ -468,7 +468,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
                        nearest_boxindex = boxindex;
                }
 
-               if (nearest_collided == -1) {
+               if (nearest_collided == COLLISION_AXIS_NONE) {
                        // No collision with any collision box.
                        *pos_f += *speed_f * dtime;
                        dtime = 0;  // Set to 0 to avoid "infinite" loop due to small FP numbers
@@ -477,7 +477,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
                        NearbyCollisionInfo &nearest_info = cinfo[nearest_boxindex];
                        const aabb3f& cbox = nearest_info.box;
                        // Check for stairs.
-                       bool step_up = (nearest_collided != 1) && // must not be Y direction
+                       bool step_up = (nearest_collided != COLLISION_AXIS_Y) && // must not be Y direction
                                        (movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
                                        (movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
                                        (!wouldCollideWithCeiling(cinfo, movingbox,
@@ -491,11 +491,11 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
                        if (nearest_dtime < 0) {
                                // Handle negative nearest_dtime (can be caused by the d allowance)
                                if (!step_up) {
-                                       if (nearest_collided == 0)
+                                       if (nearest_collided == COLLISION_AXIS_X)
                                                pos_f->X += speed_f->X * nearest_dtime;
-                                       if (nearest_collided == 1)
+                                       if (nearest_collided == COLLISION_AXIS_Y)
                                                pos_f->Y += speed_f->Y * nearest_dtime;
-                                       if (nearest_collided == 2)
+                                       if (nearest_collided == COLLISION_AXIS_Z)
                                                pos_f->Z += speed_f->Z * nearest_dtime;
                                }
                        } else {
@@ -522,19 +522,19 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
                                // Special case: Handle stairs
                                nearest_info.is_step_up = true;
                                is_collision = false;
-                       } else if (nearest_collided == 0) { // X
+                       } else if (nearest_collided == COLLISION_AXIS_X) {
                                if (fabs(speed_f->X) > BS * 3)
                                        speed_f->X *= bounce;
                                else
                                        speed_f->X = 0;
                                result.collides = true;
-                       } else if (nearest_collided == 1) { // Y
+                       } else if (nearest_collided == COLLISION_AXIS_Y) {
                                if(fabs(speed_f->Y) > BS * 3)
                                        speed_f->Y *= bounce;
                                else
                                        speed_f->Y = 0;
                                result.collides = true;
-                       } else if (nearest_collided == 2) { // Z
+                       } else if (nearest_collided == COLLISION_AXIS_Z) {
                                if (fabs(speed_f->Z) > BS * 3)
                                        speed_f->Z *= bounce;
                                else
@@ -547,6 +547,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
                                is_collision = false;
 
                        if (is_collision) {
+                               info.axis = nearest_collided;
                                result.collisions.push_back(info);
                        }
                }
index 4c5594528d101dd136924647a3b5578e671c9c56..85df02c965cc1118a699b06fb7ac59caceb0421e 100644 (file)
@@ -33,11 +33,20 @@ enum CollisionType
        COLLISION_OBJECT,
 };
 
+enum CollisionAxis
+{
+       COLLISION_AXIS_NONE = -1,
+       COLLISION_AXIS_X,
+       COLLISION_AXIS_Y,
+       COLLISION_AXIS_Z,
+};
+
 struct CollisionInfo
 {
        CollisionInfo() = default;
 
        CollisionType type = COLLISION_NODE;
+       CollisionAxis axis = COLLISION_AXIS_NONE;
        v3s16 node_p = v3s16(-32768,-32768,-32768); // COLLISION_NODE
        v3f old_speed;
        v3f new_speed;
@@ -66,7 +75,7 @@ collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
 // Checks for collision of a moving aabbox with a static aabbox
 // Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision
 // dtime receives time until first collision, invalid if -1 is returned
-int axisAlignedCollision(
+CollisionAxis axisAlignedCollision(
                const aabb3f &staticbox, const aabb3f &movingbox,
                const v3f &speed, f32 d, f32 *dtime);