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
This commit is contained in:
SmallJoker 2019-06-10 13:00:35 +02:00 committed by GitHub
parent bd6f1cca9d
commit e40be619f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 44 deletions

@ -170,8 +170,8 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
std::vector<CollisionInfo> *collision_info) std::vector<CollisionInfo> *collision_info)
{ {
if (!collision_info || collision_info->empty()) { if (!collision_info || collision_info->empty()) {
// Node below the feet, update each ClientEnvironment::step() // Node at feet position, update each ClientEnvironment::step()
m_standing_node = floatToInt(m_position, BS) - v3s16(0, 1, 0); m_standing_node = floatToInt(m_position, BS);
} }
// Temporary option for old move code // 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); collision_info->push_back(colinfo);
if (colinfo.type != COLLISION_NODE || if (colinfo.type != COLLISION_NODE ||
colinfo.new_speed.Y != 0 || colinfo.axis != COLLISION_AXIS_Y ||
(could_sneak && m_sneak_node_exists)) (could_sneak && m_sneak_node_exists))
continue; continue;
@ -320,6 +320,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
if (is_first || len < distance) { if (is_first || len < distance) {
m_standing_node = colinfo.node_p; m_standing_node = colinfo.node_p;
distance = len; 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 Check properties of the node on which the player is standing
*/ */
const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(m_standing_node)); const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(m_standing_node));
// Determine if jumping is possible // Determine if jumping is possible
m_can_jump = (touching_ground && !in_liquid && !is_climbing) m_disable_jump = itemgroup_get(f.groups, "disable_jump");
|| sneak_can_jump; m_can_jump = ((touching_ground && !is_climbing)
if (itemgroup_get(f.groups, "disable_jump")) || sneak_can_jump) && !m_disable_jump;
m_can_jump = false;
// Jump key pressed while jumping off from a bouncy block // Jump key pressed while jumping off from a bouncy block
if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") && if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") &&
@ -636,18 +637,14 @@ void LocalPlayer::applyControl(float dtime, Environment *env)
setSpeed(speedJ); setSpeed(speedJ);
m_client->getEventManager()->put(new SimpleTriggerEvent(MtEvent::PLAYER_JUMP)); m_client->getEventManager()->put(new SimpleTriggerEvent(MtEvent::PLAYER_JUMP));
} }
} } else if (in_liquid && !m_disable_jump) {
else if(in_liquid) if (fast_climb)
{
if(fast_climb)
speedV.Y = movement_speed_fast; speedV.Y = movement_speed_fast;
else else
speedV.Y = movement_speed_walk; speedV.Y = movement_speed_walk;
swimming_vertical = true; swimming_vertical = true;
} } else if (is_climbing && !m_disable_jump) {
else if(is_climbing) if (fast_climb)
{
if(fast_climb)
speedV.Y = movement_speed_fast; speedV.Y = movement_speed_fast;
else else
speedV.Y = movement_speed_climb; 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, pos_max_d, m_collisionbox, player_stepheight, dtime,
&position, &m_speed, accel_f); &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 If the player's feet touch the topside of any node, this is
set to true. 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 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 // Determine if jumping is possible
m_can_jump = touching_ground && !in_liquid; m_disable_jump = itemgroup_get(f.groups, "disable_jump");
if (itemgroup_get(f.groups, "disable_jump")) m_can_jump = touching_ground && !m_disable_jump;
m_can_jump = false;
// Jump key pressed while jumping off from a bouncy block // Jump key pressed while jumping off from a bouncy block
if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") && if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") &&
m_speed.Y >= -0.5 * BS) { m_speed.Y >= -0.5 * BS) {

@ -183,6 +183,7 @@ private:
// ***** End of variables for temporary option ***** // ***** End of variables for temporary option *****
bool m_can_jump = false; bool m_can_jump = false;
bool m_disable_jump = false;
u16 m_breath = PLAYER_MAX_BREATH_DEFAULT; u16 m_breath = PLAYER_MAX_BREATH_DEFAULT;
f32 m_yaw = 0.0f; f32 m_yaw = 0.0f;
f32 m_pitch = 0.0f; f32 m_pitch = 0.0f;

@ -59,7 +59,7 @@ struct NearbyCollisionInfo {
// Checks for collision of a moving aabbox with a static aabbox // 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 // 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. // The time after which the collision occurs is stored in dtime.
int axisAlignedCollision( CollisionAxis axisAlignedCollision(
const aabb3f &staticbox, const aabb3f &movingbox, const aabb3f &staticbox, const aabb3f &movingbox,
const v3f &speed, f32 d, f32 *dtime) const v3f &speed, f32 d, f32 *dtime)
{ {
@ -86,11 +86,11 @@ int axisAlignedCollision(
(relbox.MaxEdge.Y + speed.Y * (*dtime) > COLL_ZERO) && (relbox.MaxEdge.Y + speed.Y * (*dtime) > COLL_ZERO) &&
(relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) && (relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) &&
(relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO)) (relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO))
return 0; return COLLISION_AXIS_X;
} }
else if(relbox.MinEdge.X > xsize) else if(relbox.MinEdge.X > xsize)
{ {
return -1; return COLLISION_AXIS_NONE;
} }
} }
else if(speed.X < 0) // Check for collision with X+ plane 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.MaxEdge.Y + speed.Y * (*dtime) > COLL_ZERO) &&
(relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) && (relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) &&
(relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO)) (relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO))
return 0; return COLLISION_AXIS_X;
} }
else if(relbox.MaxEdge.X < 0) 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.MaxEdge.X + speed.X * (*dtime) > COLL_ZERO) &&
(relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) && (relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) &&
(relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO)) (relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO))
return 1; return COLLISION_AXIS_Y;
} }
else if(relbox.MinEdge.Y > ysize) else if(relbox.MinEdge.Y > ysize)
{ {
return -1; return COLLISION_AXIS_NONE;
} }
} }
else if(speed.Y < 0) // Check for collision with Y+ plane 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.MaxEdge.X + speed.X * (*dtime) > COLL_ZERO) &&
(relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) && (relbox.MinEdge.Z + speed.Z * (*dtime) < zsize) &&
(relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO)) (relbox.MaxEdge.Z + speed.Z * (*dtime) > COLL_ZERO))
return 1; return COLLISION_AXIS_Y;
} }
else if(relbox.MaxEdge.Y < 0) 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.MaxEdge.X + speed.X * (*dtime) > COLL_ZERO) &&
(relbox.MinEdge.Y + speed.Y * (*dtime) < ysize) && (relbox.MinEdge.Y + speed.Y * (*dtime) < ysize) &&
(relbox.MaxEdge.Y + speed.Y * (*dtime) > COLL_ZERO)) (relbox.MaxEdge.Y + speed.Y * (*dtime) > COLL_ZERO))
return 2; return COLLISION_AXIS_Z;
} }
//else if(relbox.MinEdge.Z > zsize) //else if(relbox.MinEdge.Z > zsize)
//{ //{
// return -1; // return COLLISION_AXIS_NONE;
//} //}
} }
else if(speed.Z < 0) // Check for collision with Z+ plane 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.MaxEdge.X + speed.X * (*dtime) > COLL_ZERO) &&
(relbox.MinEdge.Y + speed.Y * (*dtime) < ysize) && (relbox.MinEdge.Y + speed.Y * (*dtime) < ysize) &&
(relbox.MaxEdge.Y + speed.Y * (*dtime) > COLL_ZERO)) (relbox.MaxEdge.Y + speed.Y * (*dtime) > COLL_ZERO))
return 2; return COLLISION_AXIS_Z;
} }
//else if(relbox.MaxEdge.Z < 0) //else if(relbox.MaxEdge.Z < 0)
//{ //{
// return -1; // return COLLISION_AXIS_NONE;
//} //}
} }
return -1; return COLLISION_AXIS_NONE;
} }
// Helper function: // Helper function:
@ -442,7 +442,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
movingbox.MinEdge += *pos_f; movingbox.MinEdge += *pos_f;
movingbox.MaxEdge += *pos_f; movingbox.MaxEdge += *pos_f;
int nearest_collided = -1; CollisionAxis nearest_collided = COLLISION_AXIS_NONE;
f32 nearest_dtime = dtime; f32 nearest_dtime = dtime;
int nearest_boxindex = -1; int nearest_boxindex = -1;
@ -457,7 +457,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
// Find nearest collision of the two boxes (raytracing-like) // Find nearest collision of the two boxes (raytracing-like)
f32 dtime_tmp; f32 dtime_tmp;
int collided = axisAlignedCollision(box_info.box, CollisionAxis collided = axisAlignedCollision(box_info.box,
movingbox, *speed_f, d, &dtime_tmp); movingbox, *speed_f, d, &dtime_tmp);
if (collided == -1 || dtime_tmp >= nearest_dtime) if (collided == -1 || dtime_tmp >= nearest_dtime)
@ -468,7 +468,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
nearest_boxindex = boxindex; nearest_boxindex = boxindex;
} }
if (nearest_collided == -1) { if (nearest_collided == COLLISION_AXIS_NONE) {
// No collision with any collision box. // No collision with any collision box.
*pos_f += *speed_f * dtime; *pos_f += *speed_f * dtime;
dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers 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]; NearbyCollisionInfo &nearest_info = cinfo[nearest_boxindex];
const aabb3f& cbox = nearest_info.box; const aabb3f& cbox = nearest_info.box;
// Check for stairs. // 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 < cbox.MaxEdge.Y) &&
(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) && (movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
(!wouldCollideWithCeiling(cinfo, movingbox, (!wouldCollideWithCeiling(cinfo, movingbox,
@ -491,11 +491,11 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
if (nearest_dtime < 0) { if (nearest_dtime < 0) {
// Handle negative nearest_dtime (can be caused by the d allowance) // Handle negative nearest_dtime (can be caused by the d allowance)
if (!step_up) { if (!step_up) {
if (nearest_collided == 0) if (nearest_collided == COLLISION_AXIS_X)
pos_f->X += speed_f->X * nearest_dtime; 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; 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; pos_f->Z += speed_f->Z * nearest_dtime;
} }
} else { } else {
@ -522,19 +522,19 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
// Special case: Handle stairs // Special case: Handle stairs
nearest_info.is_step_up = true; nearest_info.is_step_up = true;
is_collision = false; is_collision = false;
} else if (nearest_collided == 0) { // X } else if (nearest_collided == COLLISION_AXIS_X) {
if (fabs(speed_f->X) > BS * 3) if (fabs(speed_f->X) > BS * 3)
speed_f->X *= bounce; speed_f->X *= bounce;
else else
speed_f->X = 0; speed_f->X = 0;
result.collides = true; result.collides = true;
} else if (nearest_collided == 1) { // Y } else if (nearest_collided == COLLISION_AXIS_Y) {
if(fabs(speed_f->Y) > BS * 3) if(fabs(speed_f->Y) > BS * 3)
speed_f->Y *= bounce; speed_f->Y *= bounce;
else else
speed_f->Y = 0; speed_f->Y = 0;
result.collides = true; result.collides = true;
} else if (nearest_collided == 2) { // Z } else if (nearest_collided == COLLISION_AXIS_Z) {
if (fabs(speed_f->Z) > BS * 3) if (fabs(speed_f->Z) > BS * 3)
speed_f->Z *= bounce; speed_f->Z *= bounce;
else else
@ -547,6 +547,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
is_collision = false; is_collision = false;
if (is_collision) { if (is_collision) {
info.axis = nearest_collided;
result.collisions.push_back(info); result.collisions.push_back(info);
} }
} }

@ -33,11 +33,20 @@ enum CollisionType
COLLISION_OBJECT, COLLISION_OBJECT,
}; };
enum CollisionAxis
{
COLLISION_AXIS_NONE = -1,
COLLISION_AXIS_X,
COLLISION_AXIS_Y,
COLLISION_AXIS_Z,
};
struct CollisionInfo struct CollisionInfo
{ {
CollisionInfo() = default; CollisionInfo() = default;
CollisionType type = COLLISION_NODE; CollisionType type = COLLISION_NODE;
CollisionAxis axis = COLLISION_AXIS_NONE;
v3s16 node_p = v3s16(-32768,-32768,-32768); // COLLISION_NODE v3s16 node_p = v3s16(-32768,-32768,-32768); // COLLISION_NODE
v3f old_speed; v3f old_speed;
v3f new_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 // 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 // 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 // dtime receives time until first collision, invalid if -1 is returned
int axisAlignedCollision( CollisionAxis axisAlignedCollision(
const aabb3f &staticbox, const aabb3f &movingbox, const aabb3f &staticbox, const aabb3f &movingbox,
const v3f &speed, f32 d, f32 *dtime); const v3f &speed, f32 d, f32 *dtime);