Fixed EntityTeleportPacket being sent for every position fields modification and use a proper entity movement packet instead of velocity

This commit is contained in:
Felix Cravic 2020-11-26 12:46:49 +01:00
parent 012e65337d
commit 63196e024b
8 changed files with 105 additions and 44 deletions

View File

@ -18,9 +18,10 @@ public class CollisionUtils {
/**
* Moves an entity with physics applied (ie checking against blocks)
*
* @param entity the entity to move
* @param positionOut the Position object in which the new position will be saved
* @param velocityOut the Vector object in which the new velocity will be saved
* @param entity the entity to move
* @param deltaPosition
* @param positionOut the Position object in which the new position will be saved
* @param velocityOut the Vector object in which the new velocity will be saved
* @return whether this entity is on the ground
*/
public static boolean handlePhysics(Entity entity, Vector deltaPosition, Position positionOut, Vector velocityOut) {

View File

@ -408,24 +408,53 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
// Synchronization with updated fields in #getPosition()
{
// X/Y/Z axis
if (cacheX != position.getX() ||
final boolean positionChange = cacheX != position.getX() ||
cacheY != position.getY() ||
cacheZ != position.getZ()) {
cacheZ != position.getZ();
final boolean viewChange = cacheYaw != position.getYaw() ||
cachePitch != position.getPitch();
final float distance = positionChange ? position.getDistance(cacheX, cacheY, cacheZ) : 0;
if (distance >= 8) {
// Teleport has the priority over everything else
teleport(position);
}
// Yaw/Pitch
if (cacheYaw != position.getYaw() ||
cachePitch != position.getPitch()) {
} else if (positionChange && viewChange) {
EntityPositionAndRotationPacket positionAndRotationPacket =
EntityPositionAndRotationPacket.getPacket(getEntityId(),
position, new Position(cacheX, cacheY, cacheZ), isOnGround());
sendPacketToViewersAndSelf(positionAndRotationPacket);
refreshPosition(position.copy());
// Fix head rotation
EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
entityHeadLookPacket.entityId = getEntityId();
entityHeadLookPacket.yaw = position.getYaw();
sendPacketToViewersAndSelf(entityHeadLookPacket);
} else if (positionChange) {
EntityPositionPacket entityPositionPacket = EntityPositionPacket.getPacket(getEntityId(),
position, new Position(cacheX, cacheY, cacheZ), isOnGround());
sendPacketToViewersAndSelf(entityPositionPacket);
refreshPosition(position.copy());
} else if (viewChange) {
// Yaw/Pitch
setView(position);
}
}
// Entity tick
if (shouldUpdate(time)) {
this.lastUpdate = time;
// Velocity
final boolean applyVelocity = !PlayerUtils.isNettyClient(this) ||
final boolean applyVelocity = (hasVelocity() && !PlayerUtils.isNettyClient(this)) ||
(PlayerUtils.isNettyClient(this) && hasVelocity());
if (applyVelocity) {
final float tps = MinecraftServer.TICK_PER_SECOND;

View File

@ -2,8 +2,8 @@ package net.minestom.server.entity;
import com.extollit.gaming.ai.path.HydrazinePathFinder;
import com.extollit.gaming.ai.path.model.IPath;
import net.minestom.server.MinecraftServer;
import net.minestom.server.attribute.Attributes;
import net.minestom.server.collision.CollisionUtils;
import net.minestom.server.entity.ai.GoalSelector;
import net.minestom.server.entity.ai.TargetSelector;
import net.minestom.server.entity.pathfinding.PFPathingEntity;
@ -424,7 +424,7 @@ public abstract class EntityCreature extends LivingEntity {
final float dx = targetX - currentX;
// the purpose of these few lines is to slow down entities when they reach their destination
float distSquared = dx * dx + dz * dz;
final float distSquared = dx * dx + dz * dz;
if (speed > distSquared) {
speed = distSquared;
}
@ -435,10 +435,14 @@ public abstract class EntityCreature extends LivingEntity {
lookAlong(dx, direction.getY(), dz);
// TODO: is a hard set an issue if there are other external forces at play?
final float tps = MinecraftServer.TICK_PER_SECOND;
velocity.setX(speedX * tps);
velocity.setZ(speedZ * tps);
Position newPosition = new Position();
Vector newVelocityOut = new Vector();
// Prevent ghosting
CollisionUtils.handlePhysics(this, new Vector(speedX, 0, speedZ), newPosition, newVelocityOut);
getPosition().setX(newPosition.getX());
getPosition().setZ(newPosition.getZ());
}
/**

View File

@ -463,25 +463,11 @@ public class Player extends LivingEntity implements CommandSender {
ServerPacket updatePacket;
ServerPacket optionalUpdatePacket = null;
if (positionChanged && viewChanged) {
EntityPositionAndRotationPacket entityPositionAndRotationPacket = new EntityPositionAndRotationPacket();
entityPositionAndRotationPacket.entityId = getEntityId();
entityPositionAndRotationPacket.deltaX = (short) ((position.getX() * 32 - lastPlayerSyncX * 32) * 128);
entityPositionAndRotationPacket.deltaY = (short) ((position.getY() * 32 - lastPlayerSyncY * 32) * 128);
entityPositionAndRotationPacket.deltaZ = (short) ((position.getZ() * 32 - lastPlayerSyncZ * 32) * 128);
entityPositionAndRotationPacket.yaw = position.getYaw();
entityPositionAndRotationPacket.pitch = position.getPitch();
entityPositionAndRotationPacket.onGround = onGround;
updatePacket = entityPositionAndRotationPacket;
updatePacket = EntityPositionAndRotationPacket.getPacket(getEntityId(),
position, new Position(lastPlayerSyncX, lastPlayerSyncY, lastPlayerSyncZ), onGround);
} else if (positionChanged) {
EntityPositionPacket entityPositionPacket = new EntityPositionPacket();
entityPositionPacket.entityId = getEntityId();
entityPositionPacket.deltaX = (short) ((position.getX() * 32 - lastPlayerSyncX * 32) * 128);
entityPositionPacket.deltaY = (short) ((position.getY() * 32 - lastPlayerSyncY * 32) * 128);
entityPositionPacket.deltaZ = (short) ((position.getZ() * 32 - lastPlayerSyncZ * 32) * 128);
entityPositionPacket.onGround = onGround;
updatePacket = entityPositionPacket;
updatePacket = EntityPositionPacket.getPacket(getEntityId(),
position, new Position(lastPlayerSyncX, lastPlayerSyncY, lastPlayerSyncZ), onGround);
} else {
// View changed
EntityRotationPacket entityRotationPacket = new EntityRotationPacket();

View File

@ -29,7 +29,8 @@ public class FollowTargetGoal extends GoalSelector {
@Override
public boolean shouldStart() {
return entityCreature.getTarget() != null && getDistance(entityCreature.getTarget().getPosition(), entityCreature.getPosition()) >= 2;
return entityCreature.getTarget() != null &&
getDistance(entityCreature.getTarget().getPosition(), entityCreature.getPosition()) >= 2;
}
@Override
@ -58,7 +59,9 @@ public class FollowTargetGoal extends GoalSelector {
@Override
public void tick(long time) {
if (forceEnd || updateOption.getValue() == 0 || updateOption.getTimeUnit().toMilliseconds(updateOption.getValue()) + lastUpdateTime > time) {
if (forceEnd ||
updateOption.getValue() == 0 ||
updateOption.getTimeUnit().toMilliseconds(updateOption.getValue()) + lastUpdateTime > time) {
return;
}
Position targetPos = entityCreature.getTarget() != null ? entityCreature.getTarget().getPosition() : null;
@ -71,7 +74,9 @@ public class FollowTargetGoal extends GoalSelector {
@Override
public boolean shouldEnd() {
return forceEnd || entityCreature.getTarget() == null || getDistance(entityCreature.getTarget().getPosition(), entityCreature.getPosition()) < 2;
return forceEnd ||
entityCreature.getTarget() == null ||
getDistance(entityCreature.getTarget().getPosition(), entityCreature.getPosition()) < 2;
}
@Override

View File

@ -2,6 +2,7 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -28,4 +29,19 @@ public class EntityPositionAndRotationPacket implements ServerPacket {
public int getId() {
return ServerPacketIdentifier.ENTITY_POSITION_AND_ROTATION;
}
public static EntityPositionAndRotationPacket getPacket(int entityId,
@NotNull Position newPosition, @NotNull Position oldPosition,
boolean onGround) {
EntityPositionAndRotationPacket entityPositionAndRotationPacket = new EntityPositionAndRotationPacket();
entityPositionAndRotationPacket.entityId = entityId;
entityPositionAndRotationPacket.deltaX = (short) ((newPosition.getX() * 32 - oldPosition.getX() * 32) * 128);
entityPositionAndRotationPacket.deltaY = (short) ((newPosition.getY() * 32 - oldPosition.getY() * 32) * 128);
entityPositionAndRotationPacket.deltaZ = (short) ((newPosition.getZ() * 32 - oldPosition.getZ() * 32) * 128);
entityPositionAndRotationPacket.yaw = newPosition.getYaw();
entityPositionAndRotationPacket.pitch = newPosition.getPitch();
entityPositionAndRotationPacket.onGround = onGround;
return entityPositionAndRotationPacket;
}
}

View File

@ -2,6 +2,7 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -24,4 +25,17 @@ public class EntityPositionPacket implements ServerPacket {
public int getId() {
return ServerPacketIdentifier.ENTITY_POSITION;
}
public static EntityPositionPacket getPacket(int entityId,
@NotNull Position newPosition, @NotNull Position oldPosition,
boolean onGround) {
EntityPositionPacket entityPositionPacket = new EntityPositionPacket();
entityPositionPacket.entityId = entityId;
entityPositionPacket.deltaX = (short) ((newPosition.getX() * 32 - oldPosition.getX() * 32) * 128);
entityPositionPacket.deltaY = (short) ((newPosition.getY() * 32 - oldPosition.getY() * 32) * 128);
entityPositionPacket.deltaZ = (short) ((newPosition.getZ() * 32 - oldPosition.getZ() * 32) * 128);
entityPositionPacket.onGround = onGround;
return entityPositionPacket;
}
}

View File

@ -73,6 +73,12 @@ public class Position {
return this;
}
public float getDistance(float x, float y, float z) {
return (float) Math.sqrt(MathUtils.square(x - getX()) +
MathUtils.square(y - getY()) +
MathUtils.square(z - getZ()));
}
/**
* Gets the distance between 2 positions.
* In cases where performance matters, {@link #getDistanceSquared(Position)} should be used
@ -81,10 +87,8 @@ public class Position {
* @param position the second position
* @return the distance between {@code this} and {@code position}
*/
public float getDistance(Position position) {
return (float) Math.sqrt(MathUtils.square(position.getX() - getX()) +
MathUtils.square(position.getY() - getY()) +
MathUtils.square(position.getZ() - getZ()));
public float getDistance(@NotNull Position position) {
return getDistance(position.getX(), position.getY(), position.getZ());
}
/**
@ -93,7 +97,7 @@ public class Position {
* @param position the second position
* @return the squared distance between {@code this} and {@code position}
*/
public float getDistanceSquared(Position position) {
public float getDistanceSquared(@NotNull Position position) {
return MathUtils.square(getX() - position.getX()) +
MathUtils.square(getY() - position.getY()) +
MathUtils.square(getZ() - position.getZ());
@ -106,6 +110,7 @@ public class Position {
* @return a vector pointing the direction of this location's {@link
* #getPitch() pitch} and {@link #getYaw() yaw}
*/
@NotNull
public Vector getDirection() {
Vector vector = new Vector();
@ -126,7 +131,8 @@ public class Position {
* Sets the {@link #getYaw() yaw} and {@link #getPitch() pitch} to point
* in the direction of the vector.
*/
public Position setDirection(Vector vector) {
@NotNull
public Position setDirection(@NotNull Vector vector) {
/*
* Sin = Opp / Hyp
* Cos = Adj / Hyp