mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 01:05:48 +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:
		@@ -360,7 +360,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
 | 
			
		||||
 | 
			
		||||
	collisionMoveResult result = collisionMoveSimple(env, m_client,
 | 
			
		||||
		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 &&
 | 
			
		||||
		!is_climbing && physics_override.sneak;
 | 
			
		||||
@@ -444,7 +444,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
 | 
			
		||||
			v3f check_pos = position;
 | 
			
		||||
			check_pos.Y += y_diff * dtime * 22.0f + BS * 0.01f;
 | 
			
		||||
			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')
 | 
			
		||||
				position.Y = std::min(check_pos.Y, bmax.Y);
 | 
			
		||||
				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,
 | 
			
		||||
		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
 | 
			
		||||
	if (touching_ground)
 | 
			
		||||
@@ -1254,7 +1254,7 @@ void LocalPlayer::handleAutojump(f32 dtime, Environment *env,
 | 
			
		||||
 | 
			
		||||
	// try at peak of jump, zero step height
 | 
			
		||||
	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
 | 
			
		||||
	// jumped
 | 
			
		||||
 
 | 
			
		||||
@@ -273,7 +273,7 @@ static void add_object_boxes(Environment *env,
 | 
			
		||||
		const v3f pos_f, const v3f speed_f, ActiveObject *self,
 | 
			
		||||
		std::vector<NearbyCollisionInfo> &cinfo)
 | 
			
		||||
{
 | 
			
		||||
	auto process_object = [&] (ActiveObject *object) {
 | 
			
		||||
	auto process_object = [&cinfo] (ActiveObject *object) {
 | 
			
		||||
		if (object && object->collideWithObjects()) {
 | 
			
		||||
			aabb3f box;
 | 
			
		||||
			if (object->getCollisionBox(&box))
 | 
			
		||||
@@ -292,7 +292,7 @@ static void add_object_boxes(Environment *env,
 | 
			
		||||
		c_env->getActiveObjects(pos_f, distance, 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 &&
 | 
			
		||||
					self != clientobject.obj->getParent())) {
 | 
			
		||||
				process_object(clientobject.obj);
 | 
			
		||||
@@ -301,12 +301,12 @@ static void add_object_boxes(Environment *env,
 | 
			
		||||
 | 
			
		||||
		// add collision with local player
 | 
			
		||||
		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();
 | 
			
		||||
			v3f lplayer_pos = lplayer->getPosition();
 | 
			
		||||
			lplayer_collisionbox.MinEdge += lplayer_pos;
 | 
			
		||||
			lplayer_collisionbox.MaxEdge += lplayer_pos;
 | 
			
		||||
			auto *obj = (ActiveObject*) lplayer->getCAO();
 | 
			
		||||
			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);
 | 
			
		||||
		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
 | 
			
		||||
			// looping afterwards.
 | 
			
		||||
			auto include_obj_cb = [self, &process_object] (ServerActiveObject *obj) {
 | 
			
		||||
@@ -623,8 +623,10 @@ bool collision_check_intersection(Environment *env, IGameDef *gamedef,
 | 
			
		||||
		Collision detection
 | 
			
		||||
	*/
 | 
			
		||||
	aabb3f checkbox = box_0;
 | 
			
		||||
	checkbox.MinEdge += pos_f;
 | 
			
		||||
	checkbox.MaxEdge += pos_f;
 | 
			
		||||
	// aabbox3d::intersectsWithBox(box) returns true when the faces are touching perfectly.
 | 
			
		||||
	// 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
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,8 @@ struct collisionMoveResult
 | 
			
		||||
	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,
 | 
			
		||||
		f32 pos_max_d, const aabb3f &box_0,
 | 
			
		||||
		f32 stepheight, f32 dtime,
 | 
			
		||||
@@ -73,7 +74,11 @@ collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
 | 
			
		||||
		v3f accel_f, ActiveObject *self=NULL,
 | 
			
		||||
		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,
 | 
			
		||||
		const aabb3f &box_0, const v3f &pos_f, ActiveObject *self = nullptr,
 | 
			
		||||
		bool collide_with_objects = true);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user