private void MoveEntity( [NotNull] VisibleEntity entity, Position newPos )
{
if ( entity == null )
throw new ArgumentNullException( "entity" );
Position oldPos = entity.LastKnownPosition;
// calculate difference between old and new positions
Position delta = new Position {
X = ( short )( newPos.X - oldPos.X ),
Y = ( short )( newPos.Y - oldPos.Y ),
Z = ( short )( newPos.Z - oldPos.Z ),
R = ( byte )Math.Abs( newPos.R - oldPos.R ),
L = ( byte )Math.Abs( newPos.L - oldPos.L )
};
bool posChanged = ( delta.X != 0 ) || ( delta.Y != 0 ) || ( delta.Z != 0 );
bool rotChanged = ( delta.R != 0 ) || ( delta.L != 0 );
if ( skipUpdates ) {
int distSquared = delta.X * delta.X + delta.Y * delta.Y + delta.Z * delta.Z;
// movement optimization
if ( distSquared < SkipMovementThresholdSquared &&
( delta.R * delta.R + delta.L * delta.L ) < SkipRotationThresholdSquared &&
!entity.SkippedLastMove ) {
entity.SkippedLastMove = true;
return;
}
entity.SkippedLastMove = false;
}
Packet packet;
// create the movement packet
if ( partialUpdates && delta.FitsIntoMoveRotatePacket && fullUpdateCounter < FullPositionUpdateInterval ) {
if ( posChanged && rotChanged ) {
// incremental position + rotation update
packet = PacketWriter.MakeMoveRotate( entity.Id, new Position {
X = delta.X,
Y = delta.Y,
Z = delta.Z,
R = newPos.R,
L = newPos.L
} );
} else if ( posChanged ) {
// incremental position update
packet = PacketWriter.MakeMove( entity.Id, delta );
} else if ( rotChanged ) {
// absolute rotation update
packet = PacketWriter.MakeRotate( entity.Id, newPos );
} else {
return;
}
} else {
// full (absolute position + rotation) update
packet = PacketWriter.MakeTeleport( entity.Id, newPos );
}
entity.LastKnownPosition = newPos;
SendNow( packet );
}