All pastes #405371 Raw Edit

Untitled

public text v1 · immutable
·published 2007-03-21 18:18 UTC
rendered paste body
using System;
using System.Collections.Generic;
using log4net;
using WCell.Cryptography;
using WCell.Network;
using WCell.Network.Handler;
using WCell.RealmServer.UpdateFields;
//using WCell.DAL.TypedQueries;
//using Sooda;

namespace WCell.RealmServer
{
	///<summary>
	/// The world class
	///</summary>
	public class World
	{
		#region Fields

		protected static ILog m_log = LogManager.GetLogger(typeof(World));

		private static ObjectManager m_objectMgr;

		/// <summary>
		/// The Object Manager
		/// </summary>
		public static ObjectManager ObjectManager
		{
			get { return m_objectMgr; }
		}

		#endregion

		/// <summary>
		/// The resolver of World Class
		/// </summary>
		/// <param name="session"></param>
		/// <returns></returns>
		[Resolver]
		private static World Resolver(RealmClient session)
		{
			m_objectMgr = ObjectManager.Instance;
			return new World();
		}

		#region Packet Handlers

		/// <summary>
		/// Handles an incomming ping request
		/// </summary>
		/// <param name="session">the Session the incoming packet belongs to</param>
		/// <param name="packet">the full packet</param>
		[PacketHandler(RealmServerOpCode.CMSG_PING)]
		public void PingRequest(RealmClient session, RealmPacketIn packet)
		{
			SendPingReply(session, packet.ReadUInt32());
		}

		/// <summary>
		/// Handles incomming Auth Session Request
		/// </summary>
		/// <param name="session">the Session the incoming packet belongs to</param>
		/// <param name="packet">the full packet</param>
		[PacketHandler(RealmServerOpCode.CMSG_AUTH_SESSION)]
		public void AuthSessionRequest(RealmClient session, RealmPacketIn packet)
		{
			packet.SkipBytes(4); //GameBuild
			packet.SkipBytes(4); //Unknow field
			string accName = packet.ReadString();
			uint clientSeed = packet.ReadUInt32();
			BigInteger clientDigest = packet.ReadBigInteger(20);
			byte[] zeros = new byte[4];

			//SecureRemotePassword srp = session.Client.Server.SessionKeyService.RequestSRP(accName); Currently not working
			if (session.Account == null)
			{
				//TODO: implement acct lookup when we get DB. maybe find a better place to put this. currently session.Account is never assigned to.
				session.Account = new Account(session, accName);
				//session.Account.Username = accName;
			}

			BigInteger salt = new BigInteger(session.Server.SessionKeyService.RequestSalt(accName), 32);
			BigInteger verifier = new BigInteger(session.Server.SessionKeyService.RequestVerifier(accName));

			SecureRemotePassword srp = new SecureRemotePassword(accName, verifier, salt);

			session.Account.SessionKey =
				new BigInteger(session.Server.SessionKeyService.RequestSessionKey(accName));

			BigInteger clientVerifier =
				srp.Hash(srp.Username, zeros, clientSeed, 0xDEADBABE, session.Account.SessionKey);

			session.IsEncrypted = true; // all packets from here on are encrypted, including the AuthSessionReplys

			if (clientVerifier == clientDigest)
			{
				SendAuthSessionSuccessReply(session);
			}
			else
			{
				SendAuthSessionErrorReply(session, RealmErrorCode.AuthFailed);
			}
		}

		/// <summary>
		/// Handles incomming Char Enum Request
		/// </summary>
		/// <param name="session">the Session the incoming packet belongs to</param>
		/// <param name="packet">the full packet</param>        
		[PacketHandler(RealmServerOpCode.CMSG_CHAR_ENUM)]
		public void CharEnumRequest(RealmClient session, RealmPacketIn packet)
		{
			SendCharEnum(session);
		}

		/// <summary>
		/// Handles incomming Char creation Request
		/// </summary>
		/// <param name="session">the Session the incoming packet belongs to</param>
		/// <param name="packet">the full packet</param>        
		[PacketHandler(RealmServerOpCode.CMSG_CHAR_CREATE)]
		public void CharCreateRequest(RealmClient session, RealmPacketIn packet)
		{
			try
			{
				String characterName = packet.ReadString();
				//using (SoodaTransaction tran = new SoodaTransaction())
				//{
				//    if (WCell.DAL.Character.LoadSingleObject(CharacterField.Name == characterName) != null)
				//    {
				//        SendCharCreateReply(session, RealmErrorCode.CharacterCreateNameInUse);
				//        return;
				//    }
				//    Character ch = new Character(session.Account);
				//    //ch.Name = packet.ReadString();
				//    ch.Name = characterName;
				//    ch.Race = (RaceTypes)packet.ReadByte();
				//    ch.Class = (ClassTypes)packet.ReadByte();
				//    ch.Gender = (GenderTypes)packet.ReadByte();
				//    ch.Skin = packet.ReadByte();
				//    ch.Face = packet.ReadByte();
				//    ch.HairStyle = packet.ReadByte();
				//    ch.HairColour = packet.ReadByte();
				//    ch.FacialHair = packet.ReadByte();
				//    ch.OutFit = packet.ReadByte();

					// TODO: This should be handled elsewhere
					//ch.Level = (byte)(40);
					//ch.PositionX = -8949.950195f;
					//ch.PositionY = -132.492996f;
					//ch.PositionZ = 83.531197f;
					//ch.Orientation = 0.0f;

				//    ch.Save();

				//    session.Account.Characters.Add(ch.GUID, ch);
				//    SendCharCreateReply(session, RealmErrorCode.CharacterCreateOk);
				//}
			}
			catch (Exception e)
			{
				m_log.Error(e);
				SendCharCreateReply(session, RealmErrorCode.CharacterCreateNameInUse);
			}
		}

		/// <summary>
		/// Handles incomming Char delete Request
		/// </summary>
		/// <param name="session">the Session the incoming packet belongs to</param>
		/// <param name="packet">the full packet</param>        
		[PacketHandler(RealmServerOpCode.CMSG_CHAR_DELETE)]
		public void CharDeleteRequest(RealmClient session, RealmPacketIn packet)
		{
			ulong charGUID = packet.ReadUInt64();
			try
			{
				session.Account.Characters.Remove(charGUID);
				//session.Account.Characters[charGUID].Delete();
				SendCharDeleteReply(session, RealmErrorCode.CharacterDeleteOk);
			}
			catch (Exception)
			{
				SendCharDeleteReply(session, RealmErrorCode.CharacterDeleteFailed);
			}
		}

		/// <summary>
		/// Handles incomming Player Login Request
		/// </summary>
		/// <param name="session">the Session the incoming packet belongs to</param>
		/// <param name="packet">the full packet</param>        
		[PacketHandler(RealmServerOpCode.CMSG_PLAYER_LOGIN)]
		public void CharPlayerLoginRequest(RealmClient session, RealmPacketIn packet)
		{
			try
			{
				ulong charGUID = packet.ReadUInt64();
				if (charGUID != 0)
				{
					if (!m_objectMgr.CharacterListByGUID.ContainsKey(charGUID))
					{
						/*foreach (Character ch in session.Account.Characters.Values)
						{
							if (ch.GUID == charGUID)
							{
								session.ActiveCharacter = ch;
								m_worldUnitList.Add(ch.GUID, ch);
								break;
							}
						}*/
						if (session.Account.Characters.ContainsKey(charGUID))
						{
							session.ActiveCharacter = session.Account.Characters[charGUID];
							m_objectMgr.AddCharToLists(session.ActiveCharacter);
						}
						else
							throw new InvalidOperationException(
								string.Format("Character with guid {0} not found in this account!", charGUID));

						session.Account.SendAccountDataMD5(session);
						//session.ActiveCharacter.SendSetRestStart(session);
						//session.ActiveCharacter.SendBindPointUpdate(session);
						session.ActiveCharacter.SendTutorialFlags(session);
						//session.ActiveCharacter.SendInitialSpells(session);
						//session.ActiveCharacter.SendActionButtons(session);
						SendUpdateObject(session, UpdateTypes.CreateSelf);
						session.ActiveCharacter.SendMoveUnlockMovementReply(session);
					}
					else
					{
						session.ActiveCharacter.SendCharacterLoginFail(session,
																	   AccountCharacterErrorCodes.
																		   ACCNT_MANIP_ALREADY_LOGGED_IN);
						session.Server.DisconnectClient(m_objectMgr.CharacterListByGUID[charGUID].Account.Client);
					}
				}
			}
			catch (Exception e)
			{
				m_log.Error(e);
				session.ActiveCharacter.SendCharacterLoginFail(session,
															   AccountCharacterErrorCodes.ACCNT_MANIP_AUTH_FAILED);
			}
		}

		/// <summary>
		/// Handles incomming Query time Request
		/// </summary>
		/// <param name="session">the Session the incoming packet belongs to</param>
		/// <param name="packet">the full packet</param> 
		[PacketHandler(RealmServerOpCode.CMSG_QUERY_TIME)]
		public void QueryTimeRequest(RealmClient session, RealmPacketIn packet)
		{
			SendQueryTimeReply(session);
		}

		/// <summary>
		/// Handles incomming Name Query request
		/// </summary>
		/// <param name="session">the Session the incoming packet belongs to</param>
		/// <param name="packet">the full packet</param> 
		[PacketHandler(RealmServerOpCode.CMSG_NAME_QUERY)]
		public void NameQueryRequest(RealmClient session, RealmPacketIn packet)
		{
			SendNameQueryReply(session, session.ActiveCharacter);
		}

		/// <summary>
		/// Handles incomming Imediate Logout request
		/// </summary>
		/// <param name="session">the Session the incoming packet belongs to</param>
		/// <param name="packet">the full packet</param> 
		[PacketHandler(RealmServerOpCode.CMSG_PLAYER_LOGOUT)]
		public void PlayerImediateLogoutRequest(RealmClient session, RealmPacketIn packet)
		{
			SendPlayerImediateLogoutReply(session);
		}

		/// <summary>
		/// Handles incomming Logout request
		/// </summary>
		/// <param name="session">the Session the incoming packet belongs to</param>
		/// <param name="packet">the full packet</param> 
		[PacketHandler(RealmServerOpCode.CMSG_LOGOUT_REQUEST)]
		public void PlayerLogoutRequest(RealmClient session, RealmPacketIn packet)
		{
			SendLogoutReply(session, LogoutResponseCodes.LOGOUT_RESPONSE_ACCEPTED);
		}

		/// <summary>
		/// Handles incomming Logout Cancel Request
		/// </summary>
		/// <param name="session">the Session the incoming packet belongs to</param>
		/// <param name="packet">the full packet</param> 
		[PacketHandler(RealmServerOpCode.CMSG_LOGOUT_CANCEL)]
		public void PlayerLogoutCancel(RealmClient session, RealmPacketIn packet)
		{
			SendLogoutCancelReply(session);
		}

		#endregion

		#region Send/Reply methods

		/// <summary>
		/// Send the Ping Reply
		/// </summary>
		/// <param name="session">the Session the outdoing packet belongs to</param>
		/// <param name="sequencial">the sequencial number sent by client</param>
		public void SendPingReply(RealmClient session, uint sequencial)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_PONG))
			{
				packet.Write(sequencial);
				session.Send(packet);
			}
		}

		/// <summary>
		/// Send the Error of Auth Session to client
		/// </summary>
		/// <param name="session">the Session the outdoing packet belongs to</param>
		/// <param name="error">error code</param>
		public void SendAuthSessionErrorReply(RealmClient session, RealmErrorCode error)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_AUTH_RESPONSE))
			{
				packet.Write((byte)error);

				session.Send(packet);
			}
		}

		/// <summary>
		/// Send a success auth session reply to the client
		/// </summary>
		/// <param name="session">the Session the outdoing packet belongs to</param>
		public void SendAuthSessionSuccessReply(RealmClient session)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_AUTH_RESPONSE))
			{
				packet.WriteByte((byte)RealmErrorCode.AuthOk);
				packet.WriteByte(0xB0);
				packet.WriteByte(0x09);
				packet.WriteByte(0x02);
				packet.WriteByte(0x00);
				packet.WriteByte(0x02);
				packet.WriteInt(0);
				if (session.Account.BurningCrusadeEnabled)
				{
					packet.WriteByte(1);
				}
				else
				{
					packet.WriteByte(0);
				}
				session.Send(packet);
			}
		}

		/// <summary>
		/// Sends the Char Enum to client
		/// </summary>
		/// <param name="session">the Session the outdoing packet belongs to</param>
		public void SendCharEnum(RealmClient session)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_CHAR_ENUM))
			{
				Dictionary<ulong, Character> characters = session.Account.Characters;

				packet.WriteByte((byte)characters.Count);
				foreach (Character c in characters.Values) //change to foreach so we dont get KeyNotFoundExceptions
				{
					packet.Write(c.GUID.Full);
                    packet.WriteString(c.Name);
                    packet.WriteByte((byte) c.Race);
                    packet.WriteByte((byte) c.Class);
                    packet.WriteByte((byte) c.Gender);
                    packet.WriteByte(c.Skin);
                    packet.WriteByte(c.Face);
                    packet.WriteByte(c.HairStyle);
                    packet.WriteByte(c.HairColour);
                    packet.WriteByte(c.FacialHair);
                    packet.WriteByte((byte)c.Level);
                    packet.WriteByte(c.OutFit); // displayId?
                    packet.Write(c.ZoneId);
                    packet.Write(c.MapId);
                    packet.Write(c.PositionX);
                    packet.Write(c.PositionY);
                    packet.Write(c.PositionZ);
                    packet.WriteByte(0); //unk1
                    packet.WriteByte(0); //unk2
                    packet.WriteByte(0); //unk3
                    if (c.IsLocked)
                    {
                        packet.WriteByte(1);
                    }
                    else
                    {
                        packet.WriteByte(0);
                    }

					packet.WriteInt(0); // rest
					packet.Write(c.PetInfoId);
					packet.Write(c.PetLevel);
					packet.Write(c.PetFamilyId);
					packet.WriteZeros(100);
				}
				session.Send(packet);
			}
		}

		///<summary>
		/// Send Query Time Reply
		///</summary>
		///<param name="session">the Session the outdoing packet belongs to</param>
		public void SendQueryTimeReply(RealmClient session)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_QUERY_TIME_RESPONSE))
			{
				packet.WriteDateTime(DateTime.Now);
				session.Send(packet);
			}
		}

		/// <summary>
		/// Send a Name Query Reply
		/// </summary>
		///<param name="session">the Session the outdoing packet belongs to</param>
		/// <param name="character">the character that will be send</param>
		public void SendNameQueryReply(RealmClient session, Character character)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_NAME_QUERY_RESPONSE))
			{
				packet.Write(character.GUID);
				packet.Write(character.Name);
				packet.WriteZeros(1);
				packet.Write((byte)character.Race);
				packet.Write((byte)character.Gender);
				packet.Write((byte)character.Class);
				session.Send(packet);
			}
		}

		public void SendUpdateObject(RealmClient client, UpdateTypes updateType)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_UPDATE_OBJECT))
			{
				packet.Write(1); // block count.
				packet.WriteByte(1); // unk constant
				// start repeat
				packet.WriteByte((byte)updateType); // update type
				packet.Write(client.ActiveCharacter.GUID.Packed);
				packet.WriteByte((byte)ObjectTypeIds.Player); // player object type

				WriteMovementUpdate(packet, client.ActiveCharacter, updateType);

                client.ActiveCharacter.Strength = 12;
                client.ActiveCharacter.Stamina = 3;
                client.ActiveCharacter.Health = 1000;
                client.ActiveCharacter.MaxHealth = 1500;
                client.ActiveCharacter.Power1 = 10;
                client.ActiveCharacter.MaxPower1 = 20;
                client.ActiveCharacter.NativeDisplayId = client.ActiveCharacter.DisplayId;
                client.ActiveCharacter.MountDisplayId = 15677;
                client.ActiveCharacter.Type = (uint)(ObjectTypes.Player | ObjectTypes.Unit | ObjectTypes.Object);
                client.ActiveCharacter.ScaleX = 1.0f;

                client.ActiveCharacter.WriteUpdateMask(packet);

				/*UpdateMask mask = new UpdateMask(PlayerFields._Count);
				mask.SetBit(ObjectFields.Guid, session.ActiveCharacter.GUID);
				mask.SetBit(UnitFields.UnitBytes0, session.ActiveCharacter.UnitBytes0);
				mask.SetBit(UnitFields.Health, 100);
				mask.SetBit(UnitFields.MaxHealth, 150);
				mask.SetBit(UnitFields.Level, (uint)session.ActiveCharacter.Level);
				mask.SetBit(UnitFields.DisplayId, session.ActiveCharacter.DisplayId);
				mask.SetBit(UnitFields.NativeDisplayId, session.ActiveCharacter.DisplayId);
				mask.SetBit(UnitFields.Power1, 10);
				mask.SetBit(UnitFields.MaxPower1, 20);
				mask.SetBit(UnitFields.MountDisplayId, 15677);
				mask.SetBit(ObjectFields.Type, (uint)(ObjectTypes.Player | ObjectTypes.Unit | ObjectTypes.Object));
				mask.SetBit(ObjectFields.ScaleX, 1.0f);
				//mask.SetBit(
				mask.Write(packet);*/

				client.Send(packet);
			}
		}

		private void WriteMovementUpdate(RealmPacketOut packet, Character c, UpdateTypes updateType)
		{
			byte flag1 = 0;
			uint flag2 = 0;
			switch (updateType)
			{
                case UpdateTypes.Create:
                    {
                        flag1 = 0x60;
                        break;
                    }
				case UpdateTypes.CreateSelf:
					{
						flag1 = 0x61;
						break;
					}
			}
			packet.WriteByte(flag1);
			packet.Write(flag2);
			packet.WriteDateTime(DateTime.Now);
			packet.Write(c.PositionX);
			packet.Write(c.PositionY);
			packet.Write(c.PositionZ);
			packet.Write(c.Orientation); // orientation
			packet.Write(0.0f); //unk

			packet.Write(20f); // Walk
			packet.Write(20f); // Run
			packet.Write(20f); // SwimBack
			packet.Write(20f); // Swim
			packet.Write(20f); // WalkBack            
			packet.Write(20f); //FlightBack
			packet.Write(20f); // flight
			packet.Write((float)Math.PI); // turn
		}

		/// <summary>
		/// Send Char Create Reply
		/// </summary>
		///<param name="session">the Session the outdoing packet belongs to</param>
		/// <param name="error">Error code</param>
		public void SendCharCreateReply(RealmClient session, RealmErrorCode error)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_CHAR_CREATE))
			{
				packet.Write((byte)error);
				session.Send(packet);
			}
		}

		/// <summary>
		/// Send Char Delete Reply
		/// </summary>
		///<param name="session">the Session the outdoing packet belongs to</param>
		/// <param name="error">Error code</param>
		public void SendCharDeleteReply(RealmClient session, RealmErrorCode error)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_CHAR_DELETE))
			{
				packet.Write((byte)error);
				session.Send(packet);
			}
		}

		/// <summary>
		/// Sent by the server to notify the client about the environmental speed change. Usualy this speed equals to real life. 
		/// </summary>
		///<param name="session">the Session the outdoing packet belongs to</param>
		public void SendLoginSetTimeSpeed(RealmClient session)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_LOGIN_SETTIMESPEED))
			{
				packet.WriteDateTime(DateTime.Now);
				session.Send(packet);
			}
		}

		/// <summary>
		/// Sent by the server to mark the end of logout sequence. In reply to CMSG_PLAYER_LOGOUT.
		/// </summary>
		///<param name="session">the Session the outdoing packet belongs to</param>
		public void SendPlayerImediateLogoutReply(RealmClient session)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_LOGOUT_COMPLETE))
			{
				m_objectMgr.RemoveCharFromLists(session.ActiveCharacter);
				session.Send(packet);
			}
		}

		/// <summary>
		/// Send Logout Response
		/// </summary>
		///<param name="session">the Session the outdoing packet belongs to</param>
		/// <param name="error">error code</param>
		public void SendLogoutReply(RealmClient session, LogoutResponseCodes error)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_LOGOUT_RESPONSE))
			{
				packet.Write((byte)error);
				packet.WriteZeros(4);
				session.Send(packet);
			}
		}

		/// <summary>
		/// Send Logout Cancel Reply
		/// </summary>
		///<param name="session">the Session the outdoing packet belongs to</param>
		public void SendLogoutCancelReply(RealmClient session)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_LOGOUT_CANCEL_ACK))
			{
				session.Send(packet);
			}
		}

		#endregion
	}
}