From e40be619f2a30c7a4d5042d922f0fe57539411d5 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 10 Jun 2019 13:00:35 +0200 Subject: [PATCH] Add disable_jump to liquids and ladders (#7688) 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 | 43 ++++++++++++++++++--------------- src/client/localplayer.h | 1 + src/collision.cpp | 49 +++++++++++++++++++------------------- src/collision.h | 11 ++++++++- 4 files changed, 60 insertions(+), 44 deletions(-) diff --git a/src/client/localplayer.cpp b/src/client/localplayer.cpp index dabeee6fe..0e273a16a 100644 --- a/src/client/localplayer.cpp +++ b/src/client/localplayer.cpp @@ -170,8 +170,8 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, std::vector *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) { diff --git a/src/client/localplayer.h b/src/client/localplayer.h index b1fc1fbc8..84cfa583a 100644 --- a/src/client/localplayer.h +++ b/src/client/localplayer.h @@ -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; diff --git a/src/collision.cpp b/src/collision.cpp index a07899e65..b36cc89b0 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -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); } } diff --git a/src/collision.h b/src/collision.h index 4c5594528..85df02c96 100644 --- a/src/collision.h +++ b/src/collision.h @@ -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);