mirror of
https://github.com/minetest/minetest.git
synced 2024-12-23 06:32:23 +01:00
LocalPlayer: Restore 2u height sneak jump (#15015)
Fix 1: Do not consider LocalPlayer's CAO in the collision data. Fix 2: work around the "aabbox3d::intersectsWithBox" edge-case.
This commit is contained in:
parent
21ed680b10
commit
8109563a02
@ -360,7 +360,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
|
|
||||||
collisionMoveResult result = collisionMoveSimple(env, m_client,
|
collisionMoveResult result = collisionMoveSimple(env, m_client,
|
||||||
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, m_cao);
|
||||||
|
|
||||||
bool could_sneak = control.sneak && !free_move && !in_liquid &&
|
bool could_sneak = control.sneak && !free_move && !in_liquid &&
|
||||||
!is_climbing && physics_override.sneak;
|
!is_climbing && physics_override.sneak;
|
||||||
@ -444,7 +444,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
v3f check_pos = position;
|
v3f check_pos = position;
|
||||||
check_pos.Y += y_diff * dtime * 22.0f + BS * 0.01f;
|
check_pos.Y += y_diff * dtime * 22.0f + BS * 0.01f;
|
||||||
if (y_diff < BS * 0.6f || (physics_override.sneak_glitch
|
if (y_diff < BS * 0.6f || (physics_override.sneak_glitch
|
||||||
&& !collision_check_intersection(env, m_client, m_collisionbox, check_pos))) {
|
&& !collision_check_intersection(env, m_client, m_collisionbox, check_pos, m_cao))) {
|
||||||
// Smoothen the movement (based on 'position.Y = bmax.Y')
|
// Smoothen the movement (based on 'position.Y = bmax.Y')
|
||||||
position.Y = std::min(check_pos.Y, bmax.Y);
|
position.Y = std::min(check_pos.Y, bmax.Y);
|
||||||
m_speed.Y = 0.0f;
|
m_speed.Y = 0.0f;
|
||||||
@ -990,7 +990,7 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
|
|
||||||
collisionMoveResult result = collisionMoveSimple(env, m_client,
|
collisionMoveResult result = collisionMoveSimple(env, m_client,
|
||||||
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, m_cao);
|
||||||
|
|
||||||
// Position was slightly changed; update standing node pos
|
// Position was slightly changed; update standing node pos
|
||||||
if (touching_ground)
|
if (touching_ground)
|
||||||
@ -1254,7 +1254,7 @@ void LocalPlayer::handleAutojump(f32 dtime, Environment *env,
|
|||||||
|
|
||||||
// try at peak of jump, zero step height
|
// try at peak of jump, zero step height
|
||||||
collisionMoveResult jump_result = collisionMoveSimple(env, m_client, pos_max_d,
|
collisionMoveResult jump_result = collisionMoveSimple(env, m_client, pos_max_d,
|
||||||
m_collisionbox, 0.0f, dtime, &jump_pos, &jump_speed, v3f(0.0f));
|
m_collisionbox, 0.0f, dtime, &jump_pos, &jump_speed, v3f(0.0f), m_cao);
|
||||||
|
|
||||||
// see if we can get a little bit farther horizontally if we had
|
// see if we can get a little bit farther horizontally if we had
|
||||||
// jumped
|
// jumped
|
||||||
|
@ -273,7 +273,7 @@ static void add_object_boxes(Environment *env,
|
|||||||
const v3f pos_f, const v3f speed_f, ActiveObject *self,
|
const v3f pos_f, const v3f speed_f, ActiveObject *self,
|
||||||
std::vector<NearbyCollisionInfo> &cinfo)
|
std::vector<NearbyCollisionInfo> &cinfo)
|
||||||
{
|
{
|
||||||
auto process_object = [&] (ActiveObject *object) {
|
auto process_object = [&cinfo] (ActiveObject *object) {
|
||||||
if (object && object->collideWithObjects()) {
|
if (object && object->collideWithObjects()) {
|
||||||
aabb3f box;
|
aabb3f box;
|
||||||
if (object->getCollisionBox(&box))
|
if (object->getCollisionBox(&box))
|
||||||
@ -292,7 +292,7 @@ static void add_object_boxes(Environment *env,
|
|||||||
c_env->getActiveObjects(pos_f, distance, clientobjects);
|
c_env->getActiveObjects(pos_f, distance, clientobjects);
|
||||||
|
|
||||||
for (auto &clientobject : clientobjects) {
|
for (auto &clientobject : clientobjects) {
|
||||||
// Do collide with everything but itself and the parent CAO
|
// Do collide with everything but itself and children
|
||||||
if (!self || (self != clientobject.obj &&
|
if (!self || (self != clientobject.obj &&
|
||||||
self != clientobject.obj->getParent())) {
|
self != clientobject.obj->getParent())) {
|
||||||
process_object(clientobject.obj);
|
process_object(clientobject.obj);
|
||||||
@ -301,12 +301,12 @@ static void add_object_boxes(Environment *env,
|
|||||||
|
|
||||||
// add collision with local player
|
// add collision with local player
|
||||||
LocalPlayer *lplayer = c_env->getLocalPlayer();
|
LocalPlayer *lplayer = c_env->getLocalPlayer();
|
||||||
if (lplayer->getParent() == nullptr) {
|
auto *obj = (ClientActiveObject*) lplayer->getCAO();
|
||||||
|
if (!self || (self != obj && self != obj->getParent())) {
|
||||||
aabb3f lplayer_collisionbox = lplayer->getCollisionbox();
|
aabb3f lplayer_collisionbox = lplayer->getCollisionbox();
|
||||||
v3f lplayer_pos = lplayer->getPosition();
|
v3f lplayer_pos = lplayer->getPosition();
|
||||||
lplayer_collisionbox.MinEdge += lplayer_pos;
|
lplayer_collisionbox.MinEdge += lplayer_pos;
|
||||||
lplayer_collisionbox.MaxEdge += lplayer_pos;
|
lplayer_collisionbox.MaxEdge += lplayer_pos;
|
||||||
auto *obj = (ActiveObject*) lplayer->getCAO();
|
|
||||||
cinfo.emplace_back(obj, 0, lplayer_collisionbox);
|
cinfo.emplace_back(obj, 0, lplayer_collisionbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,7 +315,7 @@ static void add_object_boxes(Environment *env,
|
|||||||
{
|
{
|
||||||
ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
|
ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
|
||||||
if (s_env) {
|
if (s_env) {
|
||||||
// search for objects which are not us, or we are not its parent.
|
// search for objects which are not us and not our children.
|
||||||
// we directly process the object in this callback to avoid useless
|
// we directly process the object in this callback to avoid useless
|
||||||
// looping afterwards.
|
// looping afterwards.
|
||||||
auto include_obj_cb = [self, &process_object] (ServerActiveObject *obj) {
|
auto include_obj_cb = [self, &process_object] (ServerActiveObject *obj) {
|
||||||
@ -623,8 +623,10 @@ bool collision_check_intersection(Environment *env, IGameDef *gamedef,
|
|||||||
Collision detection
|
Collision detection
|
||||||
*/
|
*/
|
||||||
aabb3f checkbox = box_0;
|
aabb3f checkbox = box_0;
|
||||||
checkbox.MinEdge += pos_f;
|
// aabbox3d::intersectsWithBox(box) returns true when the faces are touching perfectly.
|
||||||
checkbox.MaxEdge += pos_f;
|
// However, we do not want want a true-ish return value in that case. Add some tolerance.
|
||||||
|
checkbox.MinEdge += pos_f + (0.1f * BS);
|
||||||
|
checkbox.MaxEdge += pos_f - (0.1f * BS);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Go through every node and object box
|
Go through every node and object box
|
||||||
|
@ -65,7 +65,8 @@ struct collisionMoveResult
|
|||||||
std::vector<CollisionInfo> collisions;
|
std::vector<CollisionInfo> collisions;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Moves using a single iteration; speed should not exceed pos_max_d/dtime
|
/// @brief Moves using a single iteration; speed should not exceed pos_max_d/dtime
|
||||||
|
/// @param self (optional) ActiveObject to ignore in the collision detection.
|
||||||
collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
|
collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
|
||||||
f32 pos_max_d, const aabb3f &box_0,
|
f32 pos_max_d, const aabb3f &box_0,
|
||||||
f32 stepheight, f32 dtime,
|
f32 stepheight, f32 dtime,
|
||||||
@ -73,7 +74,11 @@ collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
|
|||||||
v3f accel_f, ActiveObject *self=NULL,
|
v3f accel_f, ActiveObject *self=NULL,
|
||||||
bool collide_with_objects=true);
|
bool collide_with_objects=true);
|
||||||
|
|
||||||
// check if box is in collision on actual position
|
/// @brief A simpler version of "collisionMoveSimple" that only checks whether
|
||||||
|
/// a collision occurs at the given position.
|
||||||
|
/// @param self (optional) ActiveObject to ignore in the collision detection.
|
||||||
|
/// @returns `true` when `box_0` truly intersects with a node or object.
|
||||||
|
/// Touching faces are not counted as intersection.
|
||||||
bool collision_check_intersection(Environment *env, IGameDef *gamedef,
|
bool collision_check_intersection(Environment *env, IGameDef *gamedef,
|
||||||
const aabb3f &box_0, const v3f &pos_f, ActiveObject *self = nullptr,
|
const aabb3f &box_0, const v3f &pos_f, ActiveObject *self = nullptr,
|
||||||
bool collide_with_objects = true);
|
bool collide_with_objects = true);
|
||||||
|
Loading…
Reference in New Issue
Block a user