public SendEncrypted ( byte PacketID, byte Data ) : void | ||
PacketID | byte | The ID of the packet (will remain unencrypted). |
Data | byte | The data that will be encrypted. |
리턴 | void |
public static void HandleLoginNotify(NetworkClient Client, ProcessedPacket Packet) { //Should this be stored for permanent access? byte[] ServerPublicKey = Packet.ReadBytes(Packet.ReadByte()); byte[] EncryptedData = Packet.ReadBytes(Packet.ReadByte()); AESEncryptor Enc = (AESEncryptor)Client.ClientEncryptor; Enc.PublicKey = ServerPublicKey; Client.ClientEncryptor = Enc; NetworkFacade.Client.ClientEncryptor = Enc; ECDiffieHellmanCng PrivateKey = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs.PrivateKey; byte[] NOnce = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs.NOnce; byte[] ChallengeResponse = StaticStaticDiffieHellman.Decrypt(PrivateKey, ECDiffieHellmanCngPublicKey.FromByteArray(ServerPublicKey, CngKeyBlobFormat.EccPublicBlob), NOnce, EncryptedData); MemoryStream StreamToEncrypt = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(StreamToEncrypt); Writer.Write((byte)ChallengeResponse.Length); Writer.Write(ChallengeResponse, 0, ChallengeResponse.Length); Writer.Write(Client.ClientEncryptor.Username); Writer.Write((byte)PlayerAccount.Hash.Length); Writer.Write(PlayerAccount.Hash); Writer.Flush(); //Encrypt data using key and IV from server, hoping that it'll be decrypted correctly at the other end... Client.SendEncrypted((byte)PacketType.CHALLENGE_RESPONSE, StreamToEncrypt.ToArray()); }
public static void HandleChallengeResponse(NetworkClient Client, ProcessedPacket P) { PacketStream OutPacket; if (P.DecryptedSuccessfully) { int Length = P.ReadByte(); byte[] CResponse; if (P.BufferLength >= Length) CResponse = P.ReadBytes(Length); else { //Authentication failed, so send this packet unencrypted. OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE_CITY, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x03); //Bad challenge response. Client.Send(OutPacket.ToArray()); Logger.LogInfo("Sent LOGIN_FAILURE_CITY!"); return; } AESDecryptionArgs DecryptionArgs = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs; if (DecryptionArgs.Challenge.SequenceEqual(CResponse)) { OutPacket = new PacketStream((byte)PacketType.LOGIN_SUCCESS_CITY, 0); OutPacket.WriteByte(0x01); Client.SendEncrypted((byte)PacketType.LOGIN_SUCCESS_CITY, OutPacket.ToArray()); Logger.LogInfo("Sent LOGIN_SUCCESS_CITY!"); } else { //Authentication failed, so send this packet unencrypted. OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE_CITY, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x03); //Bad challenge response. Client.Send(OutPacket.ToArray()); Logger.LogInfo("Sent LOGIN_FAILURE_CITY!"); } } else { //Authentication failed, so send this packet unencrypted. OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE_CITY, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x03); //Bad challenge response. Client.Send(OutPacket.ToArray()); Debug.WriteLine("HandleChallengeResponse - decryption failed!"); Logger.LogInfo("Sent LOGIN_FAILURE_CITY!"); } }
/// <summary> /// Requests a token from the LoginServer, that can be used to log into a CityServer. /// </summary> /// <param name="Client">A NetworkClient instance.</param> public static void RequestCityToken(NetworkClient Client, UISim SelectedCharacter) { PacketStream Packet = new PacketStream((byte)PacketType.REQUEST_CITY_TOKEN, 0); Packet.WriteString(Client.ClientEncryptor.Username); Packet.WriteString(SelectedCharacter.ResidingCity.UUID); Packet.WriteString(SelectedCharacter.GUID.ToString()); Client.SendEncrypted((byte)PacketType.REQUEST_CITY_TOKEN, Packet.ToArray()); }
public static void HandleCharacterInfoRequest(NetworkClient Client, ProcessedPacket P) { Logger.LogInfo("Received CharacterInfoRequest!"); DateTime Timestamp = DateTime.Parse(P.ReadPascalString()); //Database.CheckCharacterTimestamp(Client.Username, Client, TimeStamp); Character[] Characters = new Character[] { }; using (var db = DataAccess.Get()) { var account = db.Accounts.GetByUsername(Client.ClientEncryptor.Username); Characters = db.Characters.GetForAccount((int)account.AccountID).ToArray(); } if (Characters != null) { PacketStream Packet = new PacketStream((byte)PacketType.CHARACTER_LIST, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); /** * Whats the point of checking a timestamp here? It saves a few bytes on a packet * sent once per user session. Premature optimization. */ PacketWriter.Write((byte)Characters.Length); foreach (Character avatar in Characters) { PacketWriter.Write((int)avatar.CharacterID); PacketWriter.Write(avatar.GUID.ToString()); PacketWriter.Write(avatar.LastCached); PacketWriter.Write(avatar.Name); PacketWriter.Write(avatar.Sex); PacketWriter.Write(avatar.Description); PacketWriter.Write((ulong)avatar.HeadOutfitID); PacketWriter.Write((ulong)avatar.BodyOutfitID); PacketWriter.Write((byte)avatar.AppearanceType); PacketWriter.Write((string)avatar.CityName); PacketWriter.Write((ulong)avatar.CityThumb); PacketWriter.Write((string)avatar.City); PacketWriter.Write((ulong)avatar.CityMap); PacketWriter.Write((string)avatar.CityIp); PacketWriter.Write((int)avatar.CityPort); } Packet.Write(PacketData.ToArray(), 0, (int)PacketData.Length); PacketWriter.Close(); Client.SendEncrypted(0x05, Packet.ToArray()); } else //No characters existed for the account. { PacketStream Packet = new PacketStream(0x05, 0); Packet.WriteByte(0x00); //0 characters. Client.SendEncrypted((byte)PacketType.CHARACTER_LIST, Packet.ToArray()); } }
/// <summary> /// Received client token. /// </summary> public static void HandleCityToken(NetworkClient Client, ProcessedPacket P) { try { //bool ClientAuthenticated = false; ClientToken TokenToRemove = new ClientToken(); using (DataAccess db = DataAccess.Get()) { string Token = P.ReadString(); ClientToken Tok; if (Token == string.Empty) return; Tok = NetworkFacade.GetClientToken(new Guid(Token)); if (Tok != null) { //ClientAuthenticated = true; TokenToRemove = Tok; Character Char = db.Characters.GetForCharacterGUID(new Guid(Tok.CharacterGUID)); if (Char != null) { NetworkFacade.CurrentSession.AddPlayer(Client, Char); PacketStream SuccessPacket = new PacketStream((byte)PacketType.CITY_TOKEN, 0); SuccessPacket.WriteByte((byte)CityTransferStatus.Success); House[] Houses = NetworkFacade.CurrentSession.GetHousesInSession(); SuccessPacket.WriteUInt16((ushort)Houses.Length); //Ho, ho, ho... foreach (House Ho in Houses) { SuccessPacket.WriteInt32(Ho.HouseID); SuccessPacket.WriteString(Ho.Name); SuccessPacket.WriteUInt16((ushort)Ho.X); SuccessPacket.WriteUInt16((ushort)Ho.Y); SuccessPacket.WriteByte((byte)Ho.Flags); //Might have to save this as unsigned in DB? SuccessPacket.WriteInt32(Ho.Cost); } SuccessPacket.WriteInt32(Char.Money); Client.SendEncrypted((byte)PacketType.CITY_TOKEN, SuccessPacket.ToArray()); } /*else { ClientAuthenticated = false; break; }*/ } NetworkFacade.TransferringClients.TryRemove(out TokenToRemove); //This is not really valid anymore, because if the token doesn't exist yet, //the client will now receive it when it arrives - see LoginPacketHandlers.cs // - HandleClientToken() /*if (!ClientAuthenticated) { PacketStream ErrorPacket = new PacketStream((byte)PacketType.CITY_TOKEN, 0); ErrorPacket.WriteByte((byte)CityTransferStatus.GeneralError); Client.SendEncrypted((byte)PacketType.CITY_TOKEN, ErrorPacket.ToArray()); }*/ } } catch (Exception E) { Logger.LogDebug("Exception in HandleCityToken: " + E.ToString()); Debug.WriteLine("Exception in HandleCityToken: " + E.ToString()); PacketStream ErrorPacket = new PacketStream((byte)PacketType.CITY_TOKEN, 0); ErrorPacket.WriteByte((byte)CityTransferStatus.GeneralError); Client.SendEncrypted((byte)PacketType.CITY_TOKEN, ErrorPacket.ToArray()); } }
/// <summary> /// Client requested information about a city. /// </summary> public static void HandleCityInfoRequest(NetworkClient Client, ProcessedPacket P) { //This packet only contains a dummy byte, don't bother reading it. PacketStream Packet = new PacketStream((byte)PacketType.CITY_LIST, 0); Packet.WriteByte((byte)NetworkFacade.CServerListener.CityServers.Count); if (NetworkFacade.CServerListener.CityServers.Count > 0) { lock (NetworkFacade.CServerListener.CityServers) { foreach (CityInfo CInfo in NetworkFacade.CServerListener.CityServers) { Packet.WriteString(CInfo.Name); Packet.WriteString(CInfo.Description); Packet.WriteString(CInfo.IP); Packet.WriteInt32(CInfo.Port); //Hack (?) to ensure status is written correctly. switch (CInfo.Status) { case CityInfoStatus.Ok: Packet.WriteByte(1); break; case CityInfoStatus.Busy: Packet.WriteByte(2); break; case CityInfoStatus.Full: Packet.WriteByte(3); break; case CityInfoStatus.Reserved: Packet.WriteByte(4); break; } Packet.WriteUInt64(CInfo.Thumbnail); Packet.WriteString(CInfo.UUID); Packet.WriteUInt64(CInfo.Map); } } } Client.SendEncrypted((byte)PacketType.CITY_LIST, Packet.ToArray()); }
/// <summary> /// Client requested information about its characters. /// </summary> public static void HandleCharacterInfoRequest(NetworkClient Client, ProcessedPacket P) { Logger.LogInfo("Received CharacterInfoRequest!"); string DateTimeStr = P.ReadString(); DateTime Timestamp; if (DateTimeStr != string.Empty) Timestamp = DateTime.Parse(DateTimeStr); else { //Unix epoch Timestamp = new DateTime(1970, 1, 1, 0, 0, 1); } Character[] Characters = new Character[] { }; using (var db = DataAccess.Get()) { var account = db.Accounts.GetByUsername(Client.ClientEncryptor.Username); Characters = db.Characters.GetForAccount((int)account.AccountID).ToArray(); } int NumChars = 0, NewChars = 0; if (Characters != null) { PacketStream Packet = new PacketStream((byte)PacketType.CHARACTER_LIST, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); NumChars = Characters.Length; foreach (Character avatar in Characters) { //Zero means same, less than zero means T1 is earlier than T2, more than zero means T1 is later. if (DateTime.Compare(Timestamp, avatar.LastCached) < 0) { NewChars++; PacketWriter.Write((int)avatar.CharacterID); PacketWriter.Write(avatar.GUID.ToString()); PacketWriter.Write(avatar.LastCached.ToString("yyyy.MM.dd hh:mm:ss", CultureInfo.InvariantCulture)); PacketWriter.Write(avatar.Name); PacketWriter.Write(avatar.Sex); PacketWriter.Write(avatar.Description); PacketWriter.Write((ulong)avatar.HeadOutfitID); PacketWriter.Write((ulong)avatar.BodyOutfitID); PacketWriter.Write((byte)avatar.AppearanceType); PacketWriter.Write((string)avatar.CityName); PacketWriter.Write((ulong)avatar.CityThumb); PacketWriter.Write((string)avatar.City); PacketWriter.Write((ulong)avatar.CityMap); PacketWriter.Write((string)avatar.CityIp); PacketWriter.Write((int)avatar.CityPort); PacketWriter.Write((int)avatar.Money); } } //NOTE: If Characters != null, but no chars were new, NumChars will be however many characters, // and NewChars will be 0. Packet.WriteByte((byte)NumChars); Packet.WriteByte((byte)NewChars); Packet.Write(PacketData.ToArray(), 0, (int)PacketData.Length); PacketWriter.Close(); Client.SendEncrypted((byte)PacketType.CHARACTER_LIST, Packet.ToArray()); } else //No characters existed for the account. { PacketStream Packet = new PacketStream(0x05, 0); Packet.WriteByte((byte)NumChars); //0 characters. Packet.WriteByte((byte)NewChars); //0 new characters. Client.SendEncrypted((byte)PacketType.CHARACTER_LIST, Packet.ToArray()); } }
/// <summary> /// Client created a character! /// </summary> public static void HandleCharacterCreate(NetworkClient Client, ProcessedPacket P) { Logger.LogInfo("Received CharacterCreate!"); string AccountName = SanitizeAccount(P.ReadString()); //Need to be variable length, because the success packet contains a token. PacketStream CCStatusPacket = new PacketStream((byte)PacketType.CHARACTER_CREATION_STATUS, 0); using (var db = DataAccess.Get()) { Account Acc = db.Accounts.GetByUsername(AccountName); if (Acc.NumCharacters >= 3) { CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.ExceededCharacterLimit); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); return; } //TODO: Send GUID to client... var Char = new Character(); string LastCached = P.ReadString(); if (LastCached == string.Empty) { //TODO: Proper error... CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); return; } Char.LastCached = ProtoHelpers.ParseDateTime(LastCached); Char.Name = P.ReadString(); Char.Sex = P.ReadString(); Char.Description = P.ReadString(); Char.GUID = Guid.NewGuid(); Char.HeadOutfitID = (long)P.ReadUInt64(); Char.BodyOutfitID = (long)P.ReadUInt64(); Char.AccountID = Acc.AccountID; Char.AppearanceType = P.ReadByte(); Char.CityName = P.ReadString(); Char.CityThumb = (long)P.ReadUInt64(); Char.City = P.ReadString(); Char.CityMap = (long)P.ReadUInt64(); Char.CityIp = P.ReadString(); Char.CityPort = P.ReadInt32(); Char.Money = NetworkFacade.INITIAL_MONEY; //These are going into DB, so be nazi. Sieg heil! if (Char.Name == string.Empty || Char.Sex == string.Empty || Char.Description == string.Empty) { CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); return; } var status = db.Characters.CreateCharacter(Char); switch (status) { case LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted: CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); break; case LoginDataModel.Entities.CharacterCreationStatus.NameTooLong: CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameTooLong); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); break; case LoginDataModel.Entities.CharacterCreationStatus.Success: Guid Token = Guid.NewGuid(); //This actually updates the record, not sure how. Acc.NumCharacters++; //THIS NEEDS TO HAPPEN FIRST FOR CITY SERVER AUTHENTICATION TO WORK! CityInfo CServer = NetworkFacade.CServerListener.GetCityServer(Char.City); //Just in case... if (CServer != null) { PacketStream CServerPacket = new PacketStream(0x01, 0); CServerPacket.WriteHeader(); ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 1 + 4 + (Client.RemoteIP.Length + 1) + 4 + (Char.GUID.ToString().Length + 1) + (Token.ToString().Length + 1)); CServerPacket.WriteUInt16(PacketLength); CServerPacket.WriteByte(1); //CharacterCreate = true CServerPacket.WriteInt32(Acc.AccountID); CServerPacket.WriteString(Client.RemoteIP); CServerPacket.WriteInt32(Client.RemotePort); CServerPacket.WriteString(Char.GUID.ToString()); CServerPacket.WriteString(Token.ToString("")); CServer.Client.Send(CServerPacket.ToArray()); } CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.Success); CCStatusPacket.WriteString(Char.GUID.ToString()); CCStatusPacket.WriteString(Token.ToString()); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); break; } } }
public static void HandleCharacterCreate(NetworkClient Client, ProcessedPacket P) { Logger.LogInfo("Received CharacterCreate!"); string AccountName = SanitizeAccount(P.ReadPascalString()); using (var db = DataAccess.Get()) { Account Acc = db.Accounts.GetByUsername(AccountName); //TODO: Send GUID to client... SimBase Char = new SimBase(Guid.NewGuid()); Char.Timestamp = P.ReadPascalString(); Char.Name = P.ReadPascalString(); Char.Sex = P.ReadPascalString(); Char.Description = P.ReadPascalString(); Char.HeadOutfitID = P.ReadUInt64(); Char.BodyOutfitID = P.ReadUInt64(); Char.Appearance = (AppearanceType)P.ReadByte(); Char.ResidingCity = new CityInfo(P.ReadPascalString(), "", P.ReadUInt64(), P.ReadPascalString(), P.ReadUInt64(), P.ReadPascalString(), P.ReadInt32()); Char.CreatedThisSession = true; var characterModel = new Character(); characterModel.Name = Char.Name; characterModel.Sex = Char.Sex; characterModel.Description = Char.Description; characterModel.LastCached = Char.Timestamp; characterModel.GUID = Char.GUID; characterModel.HeadOutfitID = (long)Char.HeadOutfitID; characterModel.BodyOutfitID = (long)Char.BodyOutfitID; characterModel.AccountID = Acc.AccountID; characterModel.AppearanceType = (int)Char.Appearance; characterModel.City = Char.ResidingCity.UUID; characterModel.CityName = Char.ResidingCity.Name; characterModel.CityThumb = (long)Char.ResidingCity.Thumbnail; characterModel.CityMap = (long)Char.ResidingCity.Map; characterModel.CityIp = Char.ResidingCity.IP; characterModel.CityPort = Char.ResidingCity.Port; var status = db.Characters.CreateCharacter(characterModel); //Need to be variable length, because the success packet contains a token. PacketStream CCStatusPacket = new PacketStream((byte)PacketType.CHARACTER_CREATION_STATUS, 0); switch (status) { case LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted: CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); break; case LoginDataModel.Entities.CharacterCreationStatus.ExceededCharacterLimit: CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.ExceededCharacterLimit); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); break; case LoginDataModel.Entities.CharacterCreationStatus.Success: CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.Success); CCStatusPacket.WritePascalString(Char.GUID.ToString()); Guid Token = Guid.NewGuid(); CCStatusPacket.WritePascalString(Token.ToString()); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); foreach (CityServerClient CServer in NetworkFacade.CServerListener.CityServers) { if (CServer.ServerInfo.UUID == Char.ResidingCity.UUID) { PacketStream CServerPacket = new PacketStream(0x01, 0); CServerPacket.WriteHeader(); ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 4 + (Client.RemoteIP.Length + 1) + (Char.GUID.ToString().Length + 1) + (Token.ToString().Length + 1)); CServerPacket.WriteUInt16(PacketLength); CServerPacket.WriteInt32(Acc.AccountID); CServerPacket.WritePascalString(Client.RemoteIP); CServerPacket.WritePascalString(Char.GUID.ToString()); CServerPacket.WritePascalString(Token.ToString()); CServer.Send(CServerPacket.ToArray()); break; } } break; } } //Client was modified, so update it. NetworkFacade.ClientListener.UpdateClient(Client); }
/// <summary> /// Sends a request to purchase a lot. /// </summary> /// <param name="Client">NetworkClient instance connected to city server.</param> /// <param name="X">X-coordinate of lot.</param> /// <param name="Y">Y-coordinate of lot.</param> public static void SendLotPurchaseRequest(NetworkClient Client, short X, short Y) { PacketStream Packet = new PacketStream((byte)PacketType.LOT_PURCHASE_REQUEST, 0); Packet.WriteUInt16((ushort)X); Packet.WriteUInt16((ushort)Y); Client.SendEncrypted((byte)PacketType.LOT_PURCHASE_REQUEST, Packet.ToArray()); }
public static void SendLetter(NetworkClient Client, string Msg, string Subject, string GUID) { PacketStream Packet = new PacketStream((byte)PacketType.PLAYER_SENT_LETTER, 0); Packet.WriteString(GUID); Packet.WriteString(Subject); Packet.WriteString(Msg); Client.SendEncrypted((byte)PacketType.PLAYER_SENT_LETTER, Packet.ToArray()); }
/// <summary> /// Sends a token to a CityServer, as received by a LoginServer. /// </summary> /// <param name="Client">A NetworkClient instance.</param> public static void SendCityToken(NetworkClient Client) { PacketStream Packet = new PacketStream((byte)PacketType.CITY_TOKEN, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(PacketData); Writer.Write(PlayerAccount.CityToken); Packet.WriteBytes(PacketData.ToArray()); Writer.Close(); Client.SendEncrypted((byte)PacketType.CITY_TOKEN, Packet.ToArray()); }
/// <summary> /// Received initial packet from CityServer. /// </summary> public static void OnLoginNotifyCity(NetworkClient Client, ProcessedPacket Packet) { LogThis.Log.LogThis("Received OnLoginNotifyCity!", LogThis.eloglevel.info); //Should this be stored for permanent access? byte[] ServerPublicKey = Packet.ReadBytes(Packet.ReadByte()); byte[] EncryptedData = Packet.ReadBytes(Packet.ReadByte()); // lock (Client.ClientEncryptor) // { // AESEncryptor Enc = (AESEncryptor)Client.ClientEncryptor; // Enc.PublicKey = ServerPublicKey; // Client.ClientEncryptor = Enc; // lock (NetworkFacade.Client) // NetworkFacade.Client.ClientEncryptor = Enc; // } // ECDiffieHellmanCng PrivateKey = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs.PrivateKey; // byte[] NOnce = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs.NOnce; // byte[] ChallengeResponse = StaticStaticDiffieHellman.Decrypt(PrivateKey, // ECDiffieHellmanCngPublicKey.FromByteArray(ServerPublicKey, CngKeyBlobFormat.EccPublicBlob), // NOnce, EncryptedData); MemoryStream StreamToEncrypt = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(StreamToEncrypt); // Writer.Write((byte)ChallengeResponse.Length); // Writer.Write(ChallengeResponse, 0, ChallengeResponse.Length); Writer.Flush(); //Encrypt data using key and IV from server, hoping that it'll be decrypted correctly at the other end... Client.SendEncrypted((byte)PacketType.CHALLENGE_RESPONSE, StreamToEncrypt.ToArray()); }
/// <summary> /// A player sent a lot purchase request! /// </summary> public static void HandleLotPurchaseRequest(NetworkClient Client, ProcessedPacket Packet) { int X = Packet.ReadUInt16(); int Y = Packet.ReadUInt16(); if (!NetworkFacade.CurrentSession.IsLotOccupied(X, Y)) { using (DataAccess db = DataAccess.Get()) { //TODO: Enable this later?? //if (db.Houses.GetForPosition(X, Y).HouseID != 0) //{ if (NetworkFacade.CurrentTerrain.IsLandBuildable(X, Y)) { Guid CharGuid = NetworkFacade.CurrentSession.GetPlayer(Client).GUID; Character Char = db.Characters.GetForCharacterGUID(CharGuid); if (Char.Money >= NetworkFacade.LOT_COST) { Char.HouseHouse = new House(); Char.HouseHouse.Name = "Yolo"; //TODO: Fixme Char.HouseHouse.X = X; Char.HouseHouse.Y = Y; switch(db.Houses.CreateHouse(Char.HouseHouse)) { case CityDataModel.Entities.HouseCreationStatus.GeneralError: PacketStream UnbuildablePacket = new PacketStream((byte)PacketType.LOT_UNBUILDABLE, 0); UnbuildablePacket.WriteByte(0x00); Client.SendEncrypted((byte)PacketType.LOT_UNBUILDABLE, UnbuildablePacket.ToArray()); return; case CityDataModel.Entities.HouseCreationStatus.NameTooLong: PacketStream NameTooLongPacket = new PacketStream((byte)PacketType.LOT_NAME_TOO_LONG, 0); NameTooLongPacket.WriteByte(0x00); Client.SendEncrypted((byte)PacketType.LOT_NAME_TOO_LONG, NameTooLongPacket.ToArray()); return; default: break; } Char.Money -= NetworkFacade.LOT_COST; PacketStream SuccessPacket = new PacketStream((byte)PacketType.LOT_PURCHASE_SUCCESSFUL, 0); SuccessPacket.WriteInt32(Char.Money); Client.SendEncrypted((byte)PacketType.LOT_PURCHASE_SUCCESSFUL, SuccessPacket.ToArray()); } else { PacketStream OutOfMoneyPacket = new PacketStream((byte)PacketType.LOT_PURCHASE_FAILED, 0); OutOfMoneyPacket.WriteByte(0x00); //Out of money Client.SendEncrypted((byte)PacketType.LOT_PURCHASE_FAILED, OutOfMoneyPacket.ToArray()); } } else { PacketStream UnbuildablePacket = new PacketStream((byte)PacketType.LOT_UNBUILDABLE, 0); UnbuildablePacket.WriteByte(0x00); Client.SendEncrypted((byte)PacketType.LOT_UNBUILDABLE, UnbuildablePacket.ToArray()); } } //} } else { PacketStream OccupiedPacket = new PacketStream((byte)PacketType.LOT_PURCHASE_OCCUPIED, 0); OccupiedPacket.WriteByte(0x00); Client.SendEncrypted((byte)PacketType.LOT_PURCHASE_OCCUPIED, OccupiedPacket.ToArray()); } }
/// <summary> /// Player requested the cost of a lot. /// </summary> public static void HandleLotCostRequest(NetworkClient Client, ProcessedPacket Packet) { ushort X = Packet.ReadUInt16(); ushort Y = Packet.ReadUInt16(); int LotID; string LotName; using (DataAccess db = DataAccess.Get()) { LotID = db.Houses.GetForPosition(X, Y).HouseID; LotName = db.Houses.GetForPosition(X, Y).Name; } PacketStream LotCostPacket = new PacketStream((byte)PacketType.LOT_PURCHASE_OCCUPIED, 0); LotCostPacket.WriteUInt16(X); LotCostPacket.WriteUInt16(Y); LotCostPacket.WriteInt32(LotID); LotCostPacket.WriteString(LotName); byte Flags = 0; using (DataAccess db = DataAccess.Get()) { if (db.Houses.GetForPosition(X, Y).HouseID == 0) { if (!NetworkFacade.CurrentSession.IsLotOccupied(X, Y)) { ProtoHelpers.SetBit(ref Flags, 0, false); //Online. ProtoHelpers.SetBit(ref Flags, 1, false); //Spotlight, this will have to be checked against DB. ProtoHelpers.SetBit(ref Flags, 2, false); //Locked - is the house locked for public access? ProtoHelpers.SetBit(ref Flags, 3, false); //Occupied. LotCostPacket.WriteByte(Flags); LotCostPacket.WriteInt32(NetworkFacade.LOT_COST); //TODO: Figure out a way to deal with this... } } else { if (NetworkFacade.CurrentSession.IsLotOccupied(X, Y)) { ProtoHelpers.SetBit(ref Flags, 0, true); //Online. ProtoHelpers.SetBit(ref Flags, 1, false); //Spotlight, this will have to be checked against DB. ProtoHelpers.SetBit(ref Flags, 2, false); //Locked - is the house locked for public access? ProtoHelpers.SetBit(ref Flags, 3, true); //Occupied. LotCostPacket.WriteByte(Flags); LotCostPacket.WriteInt32(0); } else if (!NetworkFacade.CurrentSession.IsLotOccupied(X, Y)) { ProtoHelpers.SetBit(ref Flags, 0, false); //Online. ProtoHelpers.SetBit(ref Flags, 1, false); //Spotlight, this will have to be checked against DB. ProtoHelpers.SetBit(ref Flags, 2, false); //Locked - is the house locked for public access? ProtoHelpers.SetBit(ref Flags, 3, true); //Occupied. LotCostPacket.WriteByte(Flags); LotCostPacket.WriteInt32(0); } } } Client.SendEncrypted((byte)PacketType.LOT_COST, LotCostPacket.ToArray()); }
public static void HandleCityInfoRequest(NetworkClient Client, ProcessedPacket P) { //This packet only contains a dummy byte, don't bother reading it. PacketStream Packet = new PacketStream((byte)PacketType.CITY_LIST, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); PacketWriter.Write((byte)NetworkFacade.CServerListener.CityServers.Count); foreach (CityServerClient City in NetworkFacade.CServerListener.CityServers) { PacketWriter.Write((string)City.ServerInfo.Name); PacketWriter.Write((string)City.ServerInfo.Description); PacketWriter.Write((string)City.ServerInfo.IP); PacketWriter.Write((int)City.ServerInfo.Port); //Hack (?) to ensure status is written correctly. switch (City.ServerInfo.Status) { case CityInfoStatus.Ok: PacketWriter.Write((byte)1); break; case CityInfoStatus.Busy: PacketWriter.Write((byte)2); break; case CityInfoStatus.Full: PacketWriter.Write((byte)3); break; case CityInfoStatus.Reserved: PacketWriter.Write((byte)4); break; } PacketWriter.Write((ulong)City.ServerInfo.Thumbnail); PacketWriter.Write((string)City.ServerInfo.UUID); PacketWriter.Write((ulong)City.ServerInfo.Map); PacketWriter.Flush(); } Packet.Write(PacketData.ToArray(), 0, PacketData.ToArray().Length); PacketWriter.Close(); Client.SendEncrypted((byte)PacketType.CITY_LIST, Packet.ToArray()); }
public static void HandleCityTokenRequest(NetworkClient Client, ProcessedPacket P) { string AccountName = P.ReadPascalString(); string CityGUID = P.ReadPascalString(); string CharGUID = P.ReadPascalString(); string Token = new Guid().ToString(); foreach (CityServerClient CServer in NetworkFacade.CServerListener.CityServers) { if (CityGUID == CServer.ServerInfo.UUID) { using (var db = DataAccess.Get()) { Account Acc = db.Accounts.GetByUsername(AccountName); PacketStream CServerPacket = new PacketStream(0x01, 0); CServerPacket.WriteHeader(); ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 4 + (Client.RemoteIP.Length + 1) + (CharGUID.ToString().Length + 1) + (Token.ToString().Length + 1)); CServerPacket.WriteUInt16(PacketLength); CServerPacket.WriteInt32(Acc.AccountID); CServerPacket.WritePascalString(Client.RemoteIP); CServerPacket.WritePascalString(CharGUID.ToString()); CServerPacket.WritePascalString(Token.ToString()); CServer.Send(CServerPacket.ToArray()); break; } } } PacketStream Packet = new PacketStream((byte)PacketType.REQUEST_CITY_TOKEN, 0); Packet.WritePascalString(Token); Client.SendEncrypted((byte)PacketType.REQUEST_CITY_TOKEN, Packet.ToArray()); }
/// <summary> /// Sends a CharacterCreate packet to a CityServer. /// </summary> /// <param name="LoginArgs">Arguments used to log onto the CityServer.</param> /// <param name="Character">The character to create on the CityServer.</param> public static void SendCharacterCreateCity(NetworkClient Client, UISim Character) { PacketStream Packet = new PacketStream((byte)PacketType.CHARACTER_CREATE_CITY, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(PacketData); Writer.Write((byte)Client.ClientEncryptor.Username.Length); Writer.Write(Encoding.ASCII.GetBytes(Client.ClientEncryptor.Username), 0, Encoding.ASCII.GetBytes(Client.ClientEncryptor.Username).Length); Writer.Write(PlayerAccount.CityToken); Writer.Write(Character.Timestamp); Writer.Write(Character.Name); Writer.Write(Character.Sex); Writer.Write(Character.Description); Writer.Write((ulong)Character.HeadOutfitID); Writer.Write((ulong)Character.BodyOutfitID); Writer.Write((byte)Character.Avatar.Appearance); Packet.WriteBytes(PacketData.ToArray()); Writer.Close(); Client.SendEncrypted((byte)PacketType.CHARACTER_CREATE_CITY, Packet.ToArray()); }
public static void HandleCharacterCreate(NetworkClient Client, ProcessedPacket P) { Logger.LogDebug("Received CharacterCreate!"); bool ClientAuthenticated = false; byte AccountStrLength = (byte)P.ReadByte(); byte[] AccountNameBuf = new byte[AccountStrLength]; P.Read(AccountNameBuf, 0, AccountStrLength); string AccountName = Encoding.ASCII.GetString(AccountNameBuf); using (var db = DataAccess.Get()) { var account = db.Accounts.GetByUsername(AccountName); byte KeyLength = (byte)P.ReadByte(); byte[] EncKey = new byte[KeyLength]; P.Read(EncKey, 0, KeyLength); Client.ClientEncryptor = new ARC4Encryptor(account.Password, EncKey); Client.ClientEncryptor.Username = AccountName; string Token = P.ReadString(); string GUID = ""; foreach (ClientToken CToken in NetworkFacade.TransferringClients.GetList()) { if (CToken.ClientIP == Client.RemoteIP) { if (CToken.Token == Token) { PacketStream SuccessPacket = new PacketStream(0x64, (int)(PacketHeaders.ENCRYPTED + 1)); SuccessPacket.WriteByte((byte)TSODataModel.Entities.CharacterCreationStatus.Success); Client.SendEncrypted(0x64, SuccessPacket.ToArray()); ClientAuthenticated = true; GUID = CToken.CharacterGUID; } break; } } SimBase Char = new SimBase(new Guid(GUID)); Char.Timestamp = P.ReadPascalString(); Char.Name = P.ReadPascalString(); Char.Sex = P.ReadPascalString(); Char.Description = P.ReadPascalString(); Char.HeadOutfitID = P.ReadUInt64(); Char.BodyOutfitID = P.ReadUInt64(); Char.Appearance = (AppearanceType)P.ReadByte(); Char.CityID = new Guid(P.ReadString()); Char.CreatedThisSession = true; var characterModel = new Character(); characterModel.Name = Char.Name; characterModel.Sex = Char.Sex; characterModel.Description = Char.Description; characterModel.LastCached = Char.Timestamp; characterModel.GUID = Char.GUID; characterModel.HeadOutfitID = (long)Char.HeadOutfitID; characterModel.BodyOutfitID = (long)Char.BodyOutfitID; characterModel.AccountID = account.AccountID; characterModel.AppearanceType = (int)Char.Appearance; characterModel.City = Char.CityID.ToString(); var status = db.Characters.CreateCharacter(characterModel); } //Invalid token, should never occur... if (!ClientAuthenticated) { PacketStream SuccessPacket = new PacketStream(0x65, (int)(PacketHeaders.ENCRYPTED + 1)); SuccessPacket.WriteByte((byte)TSODataModel.Entities.CharacterCreationStatus.GeneralError); Client.SendEncrypted(0x64, SuccessPacket.ToArray()); Client.Disconnect(); } }
public static void HandleCityToken(NetworkClient Client, ProcessedPacket P) { try { bool ClientAuthenticated = false; using (var db = DataAccess.Get()) { byte HashLength = (byte)P.ReadByte(); byte[] HashBuf = new byte[HashLength]; P.Read(HashBuf, 0, HashLength); byte KeyLength = (byte)P.ReadByte(); byte[] EncKey = new byte[KeyLength]; P.Read(EncKey, 0, KeyLength); Client.ClientEncryptor = new ARC4Encryptor(Convert.ToBase64String(HashBuf), EncKey); string Token = P.ReadString(); foreach (ClientToken Tok in NetworkFacade.TransferringClients.GetList()) { if (Tok.Token == Token) { ClientAuthenticated = true; PacketStream SuccessPacket = new PacketStream((byte)PacketType.CITY_TOKEN, 0); SuccessPacket.WriteByte((byte)CityTransferStatus.Success); Client.SendEncrypted((byte)PacketType.CITY_TOKEN, SuccessPacket.ToArray()); } } if (!ClientAuthenticated) { PacketStream ErrorPacket = new PacketStream((byte)PacketType.CITY_TOKEN, 0); ErrorPacket.WriteByte((byte)CityTransferStatus.GeneralError); Client.SendEncrypted((byte)PacketType.CITY_TOKEN, ErrorPacket.ToArray()); } } } catch (Exception E) { Logger.LogDebug("Exception in HandleCityToken: " + E.ToString()); } }
public static void OnLoginSuccess(NetworkClient Client, ProcessedPacket Packet) { ServerPublicKey = Packet.ReadBytes(Packet.ReadByte()); byte[] EncryptedData = Packet.ReadBytes(Packet.ReadByte()); AESEncryptor Enc = (AESEncryptor)Client.ClientEncryptor; Enc.PublicKey = ServerPublicKey; Client.ClientEncryptor = Enc; NetworkFacade.Client.ClientEncryptor = Enc; ECDiffieHellmanCng PrivateKey = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs.PrivateKey; byte[] NOnce = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs.NOnce; byte[] ChallengeResponse = StaticStaticDiffieHellman.Decrypt(PrivateKey, ECDiffieHellmanCngPublicKey.FromByteArray(ServerPublicKey, CngKeyBlobFormat.EccPublicBlob), NOnce, EncryptedData); MemoryStream StreamToEncrypt = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(StreamToEncrypt); Writer.Write((byte)ChallengeResponse.Length); Writer.Write(ChallengeResponse, 0, ChallengeResponse.Length); Writer.Write(Client.ClientEncryptor.Username); Writer.Write((byte)PasswordHash.Length); Writer.Write(PasswordHash); Writer.Flush(); Client.SendEncrypted(0x04, StreamToEncrypt.ToArray()); }
/// <summary> /// A new player joined the current session! /// </summary> /// <param name="Client">Client to inform about new player.</param> public void SendPlayerJoinSession(NetworkClient Client, Character Player) { PacketStream JoinPacket = new PacketStream((byte)PacketType.PLAYER_JOINED_SESSION, 0); JoinPacket.WriteString(Player.GUID.ToString()); JoinPacket.WriteString(Player.Name); JoinPacket.WriteString(Player.Sex); JoinPacket.WriteString(Player.Description); JoinPacket.WriteInt64(Player.HeadOutfitID); JoinPacket.WriteInt64(Player.BodyOutfitID); JoinPacket.WriteInt32(Player.AppearanceType); if (Player.House == 1) { JoinPacket.WriteByte(1); JoinPacket.WriteInt32(Player.HouseHouse.HouseID); JoinPacket.WriteUInt16((ushort)Player.HouseHouse.X); JoinPacket.WriteUInt16((ushort)Player.HouseHouse.Y); JoinPacket.WriteByte((byte)Player.HouseHouse.Flags); //Might have to save this as unsigned in DB? } else JoinPacket.WriteByte(0); Client.SendEncrypted((byte)PacketType.PLAYER_JOINED_SESSION, JoinPacket.ToArray()); }
/// <summary> /// Client sent a response to our challenge, as well as account name and password. /// </summary> public static void HandleChallengeResponse(NetworkClient Client, ProcessedPacket P) { PacketStream OutPacket; if (P.BufferLength <= 1) { OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteByte(0x03); //Bad challenge response. Client.Send(OutPacket.ToArray()); Logger.LogInfo("Bad challenge response - sent SLoginFailResponse!\r\n"); return; //How does this even happen?! } int Length = P.ReadByte(); byte[] CResponse; if (P.BufferLength >= Length) CResponse = P.ReadBytes(Length); else return; AESDecryptionArgs DecryptionArgs = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs; if (DecryptionArgs.Challenge.SequenceEqual(CResponse)) { string AccountName = SanitizeAccount(P.ReadString()); Length = P.ReadByte(); byte[] PasswordHash; if (P.BufferLength >= Length) PasswordHash = P.ReadBytes(Length); else return; // Check whether the accountname is empty or is/contains "username" if (AccountName == string.Empty || AccountName.ToLower().Equals("username") || AccountName.ToLower().Contains("username")) { OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x01); Client.Send(OutPacket.ToArray()); Logger.LogInfo(@"Bad accountname (""" + AccountName + @""") - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } using (var db = DataAccess.Get()) { var account = db.Accounts.GetByUsername(AccountName); if (!GlobalSettings.Default.CreateAccountsOnLogin) { Logger.LogInfo("Done reading LoginRequest, checking account...\r\n"); if (account == null) { OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x01); Client.Send(OutPacket.ToArray()); Logger.LogInfo(@"Bad accountname (""" + AccountName + @""") - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } } else { if (account == null) { try { if (!AccountName.ToLower().Equals("username") || !AccountName.ToLower().Contains("username")) db.Accounts.Create(new Account { AccountName = AccountName.ToLower(), Password = Convert.ToBase64String(PasswordHash) }); } catch (Exception) { OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x01); Client.Send(OutPacket.ToArray()); Logger.LogInfo(@"Bad accountname (""" + AccountName + @""") - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } account = db.Accounts.GetByUsername(AccountName); } } if (account.IsCorrectPassword(AccountName, PasswordHash)) { OutPacket = new PacketStream((byte)PacketType.LOGIN_SUCCESS, 0); OutPacket.WriteByte(0x01); Client.ClientEncryptor.Username = AccountName; Client.SendEncrypted((byte)PacketType.LOGIN_SUCCESS, OutPacket.ToArray()); Logger.LogInfo("Sent SLoginSuccessResponse!\r\n"); return; } else { OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x02); Client.Send(OutPacket.ToArray()); Logger.LogInfo("Bad password - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } } } OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x03); //Bad challenge response. Client.Send(OutPacket.ToArray()); Logger.LogInfo("Bad challenge response - sent SLoginFailResponse!\r\n"); return; }
/// <summary> /// A new player left the current session! /// </summary> /// <param name="Client">Client to inform about player leaving.</param> public void SendPlayerLeftSession(NetworkClient Client, Character Player) { PacketStream JoinPacket = new PacketStream((byte)PacketType.PLAYER_LEFT_SESSION, 0); JoinPacket.WriteString(Player.GUID.ToString()); Client.SendEncrypted((byte)PacketType.PLAYER_LEFT_SESSION, JoinPacket.ToArray()); }
/// <summary> /// Client wanted to retire a character. /// </summary> public static void HandleCharacterRetirement(NetworkClient Client, ProcessedPacket P) { PacketStream Packet; string AccountName = P.ReadString(); string GUID = P.ReadString(); if (AccountName == string.Empty || GUID == string.Empty) return; using (var db = DataAccess.Get()) { Account Acc = db.Accounts.GetByUsername(AccountName); IQueryable<Character> Query = db.Characters.GetForAccount(Acc.AccountID); //F**K, I hate LINQ. Guid CharGUID = new Guid(GUID); Character Char = Query.Where(x => x.GUID == CharGUID).SingleOrDefault(); if (Char != null) db.Characters.RetireCharacter(Char); else return; //This actually updates the record, not sure how. Acc.NumCharacters--; if (Char != null) { CityInfo CInfo = NetworkFacade.CServerListener.GetCityServer(Char.City); //Just in case... if (CInfo != null) { Packet = new PacketStream(0x02, 0); Packet.WriteHeader(); ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 4 + GUID.Length + 1); Packet.WriteUInt16(PacketLength); Packet.WriteInt32(Acc.AccountID); Packet.WriteString(GUID); CInfo.Client.Send(Packet.ToArray()); } } } Packet = new PacketStream((byte)PacketType.RETIRE_CHARACTER_STATUS, 0); Packet.WriteString(GUID); Client.SendEncrypted((byte)PacketType.RETIRE_CHARACTER_STATUS, Packet.ToArray()); }
/// <summary> /// Player received a letter from another player. /// </summary> /// <param name="Client">Client of receiving player.</param> /// <param name="Subject">Letter's subject.</param> /// <param name="Msg">Letter's body.</param> /// <param name="LetterFrom">Name of player sending the letter.</param> public void SendPlayerReceivedLetter(NetworkClient Client, string Subject, string Msg, string LetterFrom) { PacketStream Packet = new PacketStream((byte)PacketType.PLAYER_RECV_LETTER, 0); Packet.WriteString(LetterFrom); Packet.WriteString(Subject); Packet.WriteString(Msg); Client.SendEncrypted((byte)PacketType.PLAYER_RECV_LETTER, Packet.ToArray()); }
/// <summary> /// LoginServer sent information about the player's characters. /// </summary> /// <param name="Packet">The packet that was received.</param> public static void OnCharacterInfoResponse(ProcessedPacket Packet, NetworkClient Client) { byte NumCharacters = (byte)Packet.ReadByte(); byte NewCharacters = (byte)Packet.ReadByte(); List<UISim> FreshSims = new List<UISim>(); for (int i = 0; i < NewCharacters; i++) { int CharacterID = Packet.ReadInt32(); UISim FreshSim = new UISim(Packet.ReadString(), false); FreshSim.CharacterID = CharacterID; FreshSim.Timestamp = Packet.ReadString(); FreshSim.Name = Packet.ReadString(); FreshSim.Sex = Packet.ReadString(); FreshSim.Description = Packet.ReadString(); FreshSim.HeadOutfitID = Packet.ReadUInt64(); FreshSim.BodyOutfitID = Packet.ReadUInt64(); FreshSim.Avatar.Appearance = (AppearanceType)Packet.ReadByte(); FreshSim.ResidingCity = new CityInfo(false); FreshSim.ResidingCity.Name = Packet.ReadString(); FreshSim.ResidingCity.Thumbnail = Packet.ReadUInt64(); FreshSim.ResidingCity.UUID = Packet.ReadString(); FreshSim.ResidingCity.Map = Packet.ReadUInt64(); FreshSim.ResidingCity.IP = Packet.ReadString(); FreshSim.ResidingCity.Port = Packet.ReadInt32(); FreshSims.Add(FreshSim); } lock (NetworkFacade.Avatars) { if ((NumCharacters < 3) && (NewCharacters > 0)) { FreshSims = Cache.LoadCachedSims(FreshSims); NetworkFacade.Avatars = FreshSims; Cache.CacheSims(FreshSims); } if (NewCharacters == 0 && NumCharacters > 0) NetworkFacade.Avatars = Cache.LoadAllSims(); else if (NewCharacters == 3 && NumCharacters == 3) { NetworkFacade.Avatars = FreshSims; Cache.CacheSims(FreshSims); } else if (NewCharacters == 0 && NumCharacters == 0) { //Make sure if sims existed in the cache, they are deleted (because they didn't exist in DB). Cache.DeleteCache(); } else if (NumCharacters == 3 && NewCharacters == 3) { NetworkFacade.Avatars = FreshSims; } } PacketStream CityInfoRequest = new PacketStream(0x06, 0); CityInfoRequest.WriteByte(0x00); //Dummy Client.SendEncrypted((byte)PacketType.CITY_LIST, CityInfoRequest.ToArray()); }
/// <summary> /// Client wanted to create a new character. /// </summary> public static void HandleCharacterCreate(NetworkClient Client, ProcessedPacket P) { try { Logger.LogInfo("Received CharacterCreate!"); bool ClientAuthenticated = false; byte AccountStrLength = (byte)P.ReadByte(); byte[] AccountNameBuf = new byte[AccountStrLength]; if (P.BufferLength >= AccountStrLength) { P.Read(AccountNameBuf, 0, AccountStrLength); string AccountName = Encoding.ASCII.GetString(AccountNameBuf); } else return; using (DataAccess db = DataAccess.Get()) { //No need to check for empty string here, because all it will do is have ClientAuthenticated be false string Token = P.ReadString(); string GUID = ""; int AccountID = 0; ClientToken TokenToRemove = NetworkFacade.GetClientToken(Client.RemoteIP); //Just in case... if (TokenToRemove != null) { if (TokenToRemove.Token.Equals(Token, StringComparison.CurrentCultureIgnoreCase)) { PacketStream SuccessPacket = new PacketStream((byte)PacketType.CHARACTER_CREATE_CITY, 0); SuccessPacket.WriteByte((byte)CityDataModel.Entities.CharacterCreationStatus.Success); House[] Houses = NetworkFacade.CurrentSession.GetHousesInSession(); SuccessPacket.WriteUInt16((ushort)Houses.Length); //Ho, ho, ho... foreach (House Ho in Houses) { SuccessPacket.WriteInt32(Ho.HouseID); SuccessPacket.WriteString(Ho.Name); SuccessPacket.WriteUInt16((ushort)Ho.X); SuccessPacket.WriteUInt16((ushort)Ho.Y); SuccessPacket.WriteByte((byte)Ho.Flags); //Might have to save this as unsigned in DB? SuccessPacket.WriteInt32(Ho.Cost); } Client.SendEncrypted((byte)PacketType.CHARACTER_CREATE_CITY, SuccessPacket.ToArray()); ClientAuthenticated = true; GUID = TokenToRemove.CharacterGUID; AccountID = TokenToRemove.AccountID; Sim Char = new Sim(new Guid(GUID)); Char.Timestamp = P.ReadString(); Char.Name = P.ReadString(); Char.Sex = P.ReadString(); Char.Description = P.ReadString(); Char.HeadOutfitID = P.ReadUInt64(); Char.BodyOutfitID = P.ReadUInt64(); Char.Appearance = (AppearanceType)P.ReadByte(); Char.CreatedThisSession = true; //These are going into DB, so be nazi. Sieg heil! if (Char.Timestamp == string.Empty || Char.Name == string.Empty || Char.Sex == string.Empty || Char.Description == string.Empty) { //TODO: Tell loginserver to clean up DB? ClientAuthenticated = false; } var characterModel = new Character(); characterModel.Name = Char.Name; characterModel.Sex = Char.Sex; characterModel.Description = Char.Description; characterModel.LastCached = ProtoHelpers.ParseDateTime(Char.Timestamp); characterModel.GUID = Char.GUID; characterModel.HeadOutfitID = (long)Char.HeadOutfitID; characterModel.BodyOutfitID = (long)Char.BodyOutfitID; characterModel.AccountID = AccountID; characterModel.AppearanceType = (int)Char.Appearance; characterModel.Money = NetworkFacade.INITIAL_MONEY; NetworkFacade.CurrentSession.AddPlayer(Client, characterModel); var status = db.Characters.CreateCharacter(characterModel); } } NetworkFacade.TransferringClients.TryRemove(out TokenToRemove); } //Invalid token, should never occur... if (!ClientAuthenticated) { NetworkFacade.CurrentSession.RemovePlayer(Client); PacketStream FailPacket = new PacketStream((byte)PacketType.CHARACTER_CREATE_CITY_FAILED, (int)(PacketHeaders.ENCRYPTED + 1)); FailPacket.WriteByte((byte)CityDataModel.Entities.CharacterCreationStatus.GeneralError); Client.SendEncrypted((byte)PacketType.CHARACTER_CREATE_CITY_FAILED, FailPacket.ToArray()); } } catch (Exception E) { Debug.WriteLine("Exception in HandleCharacterCreate: " + E.ToString()); Logger.LogDebug("Exception in HandleCharacterCreate: " + E.ToString()); PacketStream FailPacket = new PacketStream((byte)PacketType.CHARACTER_CREATE_CITY_FAILED, (int)(PacketHeaders.ENCRYPTED + 1)); FailPacket.WriteByte((byte)CityDataModel.Entities.CharacterCreationStatus.GeneralError); Client.SendEncrypted((byte)PacketType.CHARACTER_CREATE_CITY_FAILED, FailPacket.ToArray()); } }