using System; using System.Globalization; using RunServer.Common; using RunWoW.Accounting; using RunWoW.Common; using RunWoW.Misc; using RunWoW.Objects; namespace RunWoW.GamePackets { [PacketHandlerClass()] public class Movement {/* private struct MovementJob : IJob { private ClientBase m_client; private BinReader m_data; private CMSG m_msgId; public ExecutionPriority ExecutionPriority { get { return ExecutionPriority.Primary; } } public string Name { get { return m_msgId.ToString(); } } public bool Empty { get { return false; } } public MovementJob(ClientBase client, BinReader data, CMSG msgId) { m_client = client; m_data = data; m_data.NoDispose = true; m_msgId = msgId; } public void Execute(object state) { try { ProcessMovement(m_client, m_data, m_msgId); } finally { m_data.Clean(); } } } private static JobQueue[] m_moveJobs = new JobQueue[10]; static Movement() { for (int i = 0; i < m_moveJobs.Length; i++) { m_moveJobs[i] = new JobQueue(true, 1000); m_moveJobs[i].Start(CultureInfo.CurrentCulture); } } */ public static ShortPacket MakeMovement(SMSG msg, LivingObject living, int moveTime, out int timePos) { ShortPacket pkg = new ShortPacket(msg); pkg.WriteGuid(living.GUID); pkg.Write(living.MovementFlags); timePos = pkg.BaseStream.Position; pkg.Write(0); pkg.WriteVector(living.Position); pkg.Write(living.Facing); pkg.Write(moveTime); return pkg; } [PacketHandler(CMSG.MOVE_START_FORWARD)] [PacketHandler(CMSG.MOVE_START_BACKWARD)] [PacketHandler(CMSG.MOVE_STOP)] [PacketHandler(CMSG.MOVE_START_STRAFE_LEFT)] [PacketHandler(CMSG.MOVE_START_STRAFE_RIGHT)] [PacketHandler(CMSG.MOVE_STOP_STRAFE)] [PacketHandler(CMSG.MOVE_JUMP)] [PacketHandler(CMSG.MOVE_FALL_LAND)] [PacketHandler(CMSG.MOVE_SET_FACING)] [PacketHandler(CMSG.MOVE_HEARTBEAT)] [PacketHandler(CMSG.MOVE_STOP_TURN)] [PacketHandler(CMSG.MOVE_START_SWIM)] [PacketHandler(CMSG.MOVE_STOP_SWIM)] [PacketHandler(CMSG.MOVE_START_TURN_LEFT)] [PacketHandler(CMSG.MOVE_START_TURN_RIGHT)] [PacketHandler(CMSG.MOVE_FEATHER_FALL)] [PacketHandler(CMSG.MOVE_START_PITCH_UP)] [PacketHandler(CMSG.MOVE_START_PITCH_DOWN)] [PacketHandler(CMSG.MOVE_STOP_PITCH)] [PacketHandler(CMSG.MOVE_SET_RUN_MODE)] [PacketHandler(CMSG.MOVE_SET_WALK_MODE)] [PacketHandler(CMSG.MOVE_SET_PITCH)] public static void OnMovement(ClientBase client, BinReader data, int msgID) { ClientData Client = (ClientData) client.Data; if (Client == null || Client.Player == null || Client.Player.MapTile == null || data.Length <= 6) return; if (Client.Player.WorldChange == WCHANGESTATE.CHANGING) return; /* m_moveJobs[Client.CharacterID%m_moveJobs.Length].Enqueue(new MovementJob(client, data, (CMSG) msgID)); } private static void ProcessMovement(ClientBase client, BinReader data, CMSG msgID) { ClientData Client = (ClientData) client.Data; if (Client == null || Client.Player == null || Client.Player.MapTile == null || data.Length <= 6) return; if (Client.Player.WorldChange == WCHANGESTATE.CHANGING) return; /*switch ((CMSG)msgID) { case CMSG.MOVE_START_FORWARD: case CMSG.MOVE_START_BACKWARD: case CMSG.MOVE_START_STRAFE_LEFT: case CMSG.MOVE_START_STRAFE_RIGHT: case CMSG.MOVE_START_SWIM: case CMSG.MOVE_HEARTBEAT: if (Client.Player.Rooted || Client.Player.Stunned) { MonsterMove.FixPosition(Client.Player); return; } Client.Player.Moved(data.InnerTime); break; case CMSG.MOVE_STOP: case CMSG.MOVE_STOP_SWIM: case CMSG.MOVE_STOP_TURN: case CMSG.MOVE_STOP_STRAFE: break; default: break; }*/ int movementFlags = data.ReadInt32(); int moveTime = 0; try { int startTime = data.ReadInt32(); if (Client.ClientTimeDelay == 0) Client.ClientTimeDelay = Utility.PreciseTimestamp() - startTime; int delay = startTime - Client.ClientTime; //Console.WriteLine("{3}, {0} with movement flags 0x{1,4:X4}, time {2}, delay {3}", (CMSG)msgID, Client.Player.MovementFlags, new DateTime(startTime * TimeSpan.TicksPerMillisecond).ToString("HH:mm:ss.ffff"), delay); Vector playerPosition = data.ReadVector(); float playerFacing = data.ReadSingle(); moveTime = data.ReadInt32(); bool isTransporting = (Client.Player.MovementFlags & 0x2000000) == 0x2000000 || Client.Player.WorldMapID == 369; //bool isSwimming = (Client.Player.MovementFlags & 0x200000) == 0x200000; //bool isFalling = (Client.Player.MovementFlags & 0x2000) == 0x2000; if ((!isTransporting && playerPosition.DistanceFlat(Client.Player.Position) /*moved*/> 40f)) { Teleport.TeleportTo(Client.Player.Position, Client.Player); return; } //if ((Client.Player.MovementFlags & 31) != 0) { if (Client.Player.Rooted || Client.Player.Stunned || Client.Player.NoControl) { Client.Player.MovementFlags &= ~31; //playerPosition = Client.Player.Position; MonsterMove.FixPosition(Client.Player, delay); return; } else if (!Client.Player.Moved(data.InnerTime, playerPosition.DistanceAvr(Client.Player.Position) >0.1f)) return; // that movement is obsolete and can harm cast, etc } DateTime packetTime = CustomDateTime.Now.AddMilliseconds(delay); //Client.AddMovementPosition(playerPosition.Clone(), delay); // !!!!!!!!!!!!!!! //Client.Player.MapTile.Map.Move(Client.Player); // !!!!!!!!!!!!!!! // !!!!!!!!!!!!!!! switch ((CMSG) msgID) { case CMSG.MOVE_FALL_LAND: if (Client.Player.Attackable && Client.Player.WorldChange != WCHANGESTATE.CHANGED) { float height = Client.Player.LastPos.Z - playerPosition.Z; if (height > Constants.FallDamageMinHeightConst) { float damage = Client.Player.MaxHealth*height*Constants.FallDamageConst; Client.Player.TakeEnvironmentDamage(Client.Player, null, (DAMAGETYPE) 2, damage, damage); } //if (Constants.FallDamageTime > moveTime) //{ // float damage = Client.Player.MaxHealth * (moveTime - Constants.FallDamageTime) * Constants.FallDamageConst; // Client.Player.TakeEnvironmentDamage(Client.Player, 0, (DAMAGETYPE) 2, damage, damage); //} } goto case CMSG.MOVE_JUMP; case CMSG.MOVE_HEARTBEAT: /*if ((Client.Player.MovementFlags & 0x2000) != 0)*/ goto case CMSG.MOVE_JUMP; /*break;*/ case CMSG.MOVE_SET_FACING: if ((Client.Player.MovementFlags & 0x31) == 0) goto case CMSG.MOVE_JUMP; break; // send change facing only while standing case CMSG.MOVE_START_FORWARD: case CMSG.MOVE_START_BACKWARD: case CMSG.MOVE_STOP: case CMSG.MOVE_START_STRAFE_LEFT: case CMSG.MOVE_START_STRAFE_RIGHT: case CMSG.MOVE_STOP_STRAFE: case CMSG.MOVE_JUMP: case CMSG.MOVE_START_TURN_LEFT: case CMSG.MOVE_START_TURN_RIGHT: case CMSG.MOVE_STOP_TURN: case CMSG.MOVE_START_SWIM: case CMSG.MOVE_STOP_SWIM: if (packetTime >= Client.LastMovement) { Client.Player.Facing = playerFacing; Client.Player.Position = playerPosition; Client.LastMovement = packetTime; Client.Player.MovementFlags = movementFlags; } else return; int plength = data.BaseStream.Length - data.BaseStream.Position; int timePos; ShortPacket pkg = MakeMovement((SMSG) msgID, Client.Player, moveTime, out timePos); if (plength > 0) pkg.Write(data.ReadBytes(plength)); #if true Client.Player.MapTile.SendSurroundingTimed(pkg, Client.Player, Client.Player, timePos, delay); #else pkg.Set(timePos, startTime); Client.Player.MapTile.SendSurrounding(pkg, Client.Player, Client.Player); #endif /*if (Client.Player.Group != null) Client.Player.Group.SendExcept(pkg, Client.Player);*/ break; } } catch (Exception e) { Console.WriteLine("Exception {3} while reading move packet {0}, packet length {1}, movement flags {2}", (CMSG) msgID, data.Length, Client.Player.MovementFlags, e.ToString()); } Client.Player.LastPos = Client.Player.Position.Clone(); if (Client.Player.WorldChange == WCHANGESTATE.CHANGED) Client.Player.WorldChange = WCHANGESTATE.NONE; } } }