void MoveEntity( VisibleEntity entity, Position newPos ) {
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),
H = (short)(newPos.H - oldPos.H),
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.H != 0);
bool rotChanged = (delta.R != 0) || (delta.L != 0);
if( skipUpdates ) {
int distSquared = delta.X * delta.X + delta.Y * delta.Y + delta.H * delta.H;
// 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.FitsIntoByte() && fullUpdateCounter < FullPositionUpdateInterval ) {
if( posChanged && rotChanged ) {
// incremental position + rotation update
packet = PacketWriter.MakeMoveRotate( entity.Id, new Position {
X = delta.X,
Y = delta.Y,
H = delta.H,
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 );
}