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) * Moves an entity with physics applied (ie checking against blocks)
* *
* @param entity the entity to move * @param entity the entity to move
* @param positionOut the Position object in which the new position will be saved * @param deltaPosition
* @param velocityOut the Vector object in which the new velocity will be saved * @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 * @return whether this entity is on the ground
*/ */
public static boolean handlePhysics(Entity entity, Vector deltaPosition, Position positionOut, Vector velocityOut) { 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() // Synchronization with updated fields in #getPosition()
{ {
// X/Y/Z axis final boolean positionChange = cacheX != position.getX() ||
if (cacheX != position.getX() ||
cacheY != position.getY() || 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); teleport(position);
} } else if (positionChange && viewChange) {
// Yaw/Pitch EntityPositionAndRotationPacket positionAndRotationPacket =
if (cacheYaw != position.getYaw() || EntityPositionAndRotationPacket.getPacket(getEntityId(),
cachePitch != position.getPitch()) { 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); setView(position);
} }
} }
// Entity tick
if (shouldUpdate(time)) { if (shouldUpdate(time)) {
this.lastUpdate = time; this.lastUpdate = time;
// Velocity // Velocity
final boolean applyVelocity = !PlayerUtils.isNettyClient(this) || final boolean applyVelocity = (hasVelocity() && !PlayerUtils.isNettyClient(this)) ||
(PlayerUtils.isNettyClient(this) && hasVelocity()); (PlayerUtils.isNettyClient(this) && hasVelocity());
if (applyVelocity) { if (applyVelocity) {
final float tps = MinecraftServer.TICK_PER_SECOND; 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.HydrazinePathFinder;
import com.extollit.gaming.ai.path.model.IPath; import com.extollit.gaming.ai.path.model.IPath;
import net.minestom.server.MinecraftServer;
import net.minestom.server.attribute.Attributes; 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.GoalSelector;
import net.minestom.server.entity.ai.TargetSelector; import net.minestom.server.entity.ai.TargetSelector;
import net.minestom.server.entity.pathfinding.PFPathingEntity; import net.minestom.server.entity.pathfinding.PFPathingEntity;
@ -424,7 +424,7 @@ public abstract class EntityCreature extends LivingEntity {
final float dx = targetX - currentX; final float dx = targetX - currentX;
// the purpose of these few lines is to slow down entities when they reach their destination // 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) { if (speed > distSquared) {
speed = distSquared; speed = distSquared;
} }
@ -435,10 +435,14 @@ public abstract class EntityCreature extends LivingEntity {
lookAlong(dx, direction.getY(), dz); lookAlong(dx, direction.getY(), dz);
// TODO: is a hard set an issue if there are other external forces at play? Position newPosition = new Position();
final float tps = MinecraftServer.TICK_PER_SECOND; Vector newVelocityOut = new Vector();
velocity.setX(speedX * tps);
velocity.setZ(speedZ * tps); // 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 updatePacket;
ServerPacket optionalUpdatePacket = null; ServerPacket optionalUpdatePacket = null;
if (positionChanged && viewChanged) { if (positionChanged && viewChanged) {
EntityPositionAndRotationPacket entityPositionAndRotationPacket = new EntityPositionAndRotationPacket(); updatePacket = EntityPositionAndRotationPacket.getPacket(getEntityId(),
entityPositionAndRotationPacket.entityId = getEntityId(); position, new Position(lastPlayerSyncX, lastPlayerSyncY, lastPlayerSyncZ), onGround);
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;
} else if (positionChanged) { } else if (positionChanged) {
EntityPositionPacket entityPositionPacket = new EntityPositionPacket(); updatePacket = EntityPositionPacket.getPacket(getEntityId(),
entityPositionPacket.entityId = getEntityId(); position, new Position(lastPlayerSyncX, lastPlayerSyncY, lastPlayerSyncZ), onGround);
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;
} else { } else {
// View changed // View changed
EntityRotationPacket entityRotationPacket = new EntityRotationPacket(); EntityRotationPacket entityRotationPacket = new EntityRotationPacket();

View File

@ -29,7 +29,8 @@ public class FollowTargetGoal extends GoalSelector {
@Override @Override
public boolean shouldStart() { 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 @Override
@ -58,7 +59,9 @@ public class FollowTargetGoal extends GoalSelector {
@Override @Override
public void tick(long time) { 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; return;
} }
Position targetPos = entityCreature.getTarget() != null ? entityCreature.getTarget().getPosition() : null; Position targetPos = entityCreature.getTarget() != null ? entityCreature.getTarget().getPosition() : null;
@ -71,7 +74,9 @@ public class FollowTargetGoal extends GoalSelector {
@Override @Override
public boolean shouldEnd() { 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 @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.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier; import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryWriter; import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -28,4 +29,19 @@ public class EntityPositionAndRotationPacket implements ServerPacket {
public int getId() { public int getId() {
return ServerPacketIdentifier.ENTITY_POSITION_AND_ROTATION; 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.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier; import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryWriter; import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -24,4 +25,17 @@ public class EntityPositionPacket implements ServerPacket {
public int getId() { public int getId() {
return ServerPacketIdentifier.ENTITY_POSITION; 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; 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. * Gets the distance between 2 positions.
* In cases where performance matters, {@link #getDistanceSquared(Position)} should be used * In cases where performance matters, {@link #getDistanceSquared(Position)} should be used
@ -81,10 +87,8 @@ public class Position {
* @param position the second position * @param position the second position
* @return the distance between {@code this} and {@code position} * @return the distance between {@code this} and {@code position}
*/ */
public float getDistance(Position position) { public float getDistance(@NotNull Position position) {
return (float) Math.sqrt(MathUtils.square(position.getX() - getX()) + return getDistance(position.getX(), position.getY(), position.getZ());
MathUtils.square(position.getY() - getY()) +
MathUtils.square(position.getZ() - getZ()));
} }
/** /**
@ -93,7 +97,7 @@ public class Position {
* @param position the second position * @param position the second position
* @return the squared distance between {@code this} and {@code 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()) + return MathUtils.square(getX() - position.getX()) +
MathUtils.square(getY() - position.getY()) + MathUtils.square(getY() - position.getY()) +
MathUtils.square(getZ() - position.getZ()); MathUtils.square(getZ() - position.getZ());
@ -106,6 +110,7 @@ public class Position {
* @return a vector pointing the direction of this location's {@link * @return a vector pointing the direction of this location's {@link
* #getPitch() pitch} and {@link #getYaw() yaw} * #getPitch() pitch} and {@link #getYaw() yaw}
*/ */
@NotNull
public Vector getDirection() { public Vector getDirection() {
Vector vector = new Vector(); Vector vector = new Vector();
@ -126,7 +131,8 @@ public class Position {
* Sets the {@link #getYaw() yaw} and {@link #getPitch() pitch} to point * Sets the {@link #getYaw() yaw} and {@link #getPitch() pitch} to point
* in the direction of the vector. * in the direction of the vector.
*/ */
public Position setDirection(Vector vector) { @NotNull
public Position setDirection(@NotNull Vector vector) {
/* /*
* Sin = Opp / Hyp * Sin = Opp / Hyp
* Cos = Adj / Hyp * Cos = Adj / Hyp