void ProcessMovementPacket() {
bytesReceived += 10;
reader.ReadByte();
Position newPos = new Position {
X = IPAddress.NetworkToHostOrder( reader.ReadInt16() ),
H = IPAddress.NetworkToHostOrder( reader.ReadInt16() ),
Y = IPAddress.NetworkToHostOrder( reader.ReadInt16() ),
R = reader.ReadByte(),
L = reader.ReadByte()
};
Position oldPos = Player.Position;
// 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 )
};
// skip everything if player hasn't moved
if( delta.IsZero() ) return;
bool rotChanged = (delta.R != 0) || (delta.L != 0);
// only reset the timer if player rotated
// if player is just pushed around, rotation does not change (and timer should not reset)
if( rotChanged ) Player.ResetIdleTimer();
if( Player.Info.IsFrozen ) {
// special handling for frozen players
if( delta.X * delta.X + delta.Y * delta.Y > AntiSpeedMaxDistanceSquared ||
Math.Abs( delta.H ) > 40 ) {
SendNow( PacketWriter.MakeSelfTeleport( Player.Position ) );
}
newPos.X = Player.Position.X;
newPos.Y = Player.Position.Y;
newPos.H = Player.Position.H;
// recalculate deltas
delta.X = 0;
delta.Y = 0;
delta.H = 0;
} else if( !Player.Can( Permission.UseSpeedHack ) ) {
int distSquared = delta.X * delta.X + delta.Y * delta.Y + delta.H * delta.H;
// speedhack detection
if( DetectMovementPacketSpam() ) {
return;
} else if( (distSquared - delta.H * delta.H > AntiSpeedMaxDistanceSquared || delta.H > AntiSpeedMaxJumpDelta) &&
speedHackDetectionCounter >= 0 ) {
if( speedHackDetectionCounter == 0 ) {
Player.LastValidPosition = Player.Position;
} else if( speedHackDetectionCounter > 1 ) {
DenyMovement();
speedHackDetectionCounter = 0;
return;
}
speedHackDetectionCounter++;
} else {
speedHackDetectionCounter = 0;
}
}
if( Server.RaisePlayerMovingEvent( Player, newPos ) ) {
DenyMovement();
return;
}
Player.Position = newPos;
Server.RaisePlayerMovedEvent( Player, oldPos );
}