Account for flying in velocity calculation (#1111)

This commit is contained in:
TogAr2 2022-05-22 16:46:54 +02:00 committed by GitHub
parent f80f653ee0
commit 3cd73310cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 7 deletions

View File

@ -581,8 +581,13 @@ public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, Ev
// World border collision
final Pos finalVelocityPosition = CollisionUtils.applyWorldBorder(instance, position, newPosition);
final boolean positionChanged = !finalVelocityPosition.samePoint(position);
final boolean flying = this instanceof Player player && player.isFlying();
if (!positionChanged) {
if (hasVelocity || newVelocity.isZero()) {
if (flying) {
this.velocity = Vec.ZERO;
sendPacketToViewers(getVelocityPacket());
return;
} else if (hasVelocity || newVelocity.isZero()) {
this.velocity = noGravity ? Vec.ZERO : new Vec(
0,
-gravityAcceleration * tps * (1 - gravityDragPerTick),
@ -612,7 +617,7 @@ public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, Ev
// Update velocity
if (hasVelocity || !newVelocity.isZero()) {
updateVelocity(wasOnGround, positionBeforeMove, newVelocity);
updateVelocity(wasOnGround, flying, positionBeforeMove, newVelocity);
}
// Verify if velocity packet has to be sent
if (!(this instanceof Player) && (hasVelocity || gravityTickCount > 0)) {
@ -620,7 +625,7 @@ public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, Ev
}
}
protected void updateVelocity(boolean wasOnGround, Pos positionBeforeMove, Vec newVelocity) {
protected void updateVelocity(boolean wasOnGround, boolean flying, Pos positionBeforeMove, Vec newVelocity) {
EntitySpawnType type = entityType.registry().spawnType();
final double airDrag = type == EntitySpawnType.LIVING || type == EntitySpawnType.PLAYER ? 0.91 : 0.98;
final double drag;
@ -631,11 +636,14 @@ public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, Ev
}
} else drag = airDrag;
double gravity = flying ? 0 : gravityAcceleration;
double gravityDrag = flying ? 0.6 : (1 - gravityDragPerTick);
this.velocity = newVelocity
// Apply drag
// Apply gravity and drag
.apply((x, y, z) -> new Vec(
x * drag,
!hasNoGravity() ? (y - gravityAcceleration) * (1 - gravityDragPerTick) : y,
!hasNoGravity() ? (y - gravity) * gravityDrag : y,
z * drag
))
// Convert from block/tick to block/sec

View File

@ -8,8 +8,6 @@ import net.minestom.server.instance.Instance;
import net.minestom.server.utils.chunk.ChunkUtils;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import static org.junit.jupiter.api.Assertions.*;
@EnvTest
@ -105,6 +103,31 @@ public class EntityVelocityIntegrationTest {
});
}
@Test
public void flyingVelocity(Env env) {
var instance = env.createFlatInstance();
loadChunks(instance);
var player = env.createPlayer(instance, new Pos(0, 42, 0));
env.tick();
final double epsilon = 0.0000001;
assertEquals(player.getVelocity().y(), -1.568, epsilon);
double previousVelocity = player.getVelocity().y();
player.setFlying(true);
env.tick();
// Every tick, the y velocity is multiplied by 0.6, and after 27 ticks it should be 0
for (int i = 0; i < 27; i++) {
assertEquals(player.getVelocity().y(), previousVelocity * 0.6, epsilon);
previousVelocity = player.getVelocity().y();
env.tick();
}
assertEquals(player.getVelocity().y(), 0);
}
@Test
public void testHasVelocity(Env env) {
var instance = env.createFlatInstance();