public void DeserializeValue_WhenMap_ServerReturnedProperties() { var db = FirestoreDb.Create("proj", "db", new FakeFirestoreClient()); var context = new DeserializationContext(GetSampleSnapshot(db, "doc1")); var value = ProtoHelpers.CreateMap(("key1", ProtoHelpers.CreateValue("value1")), ("key2", ProtoHelpers.CreateValue("value2"))); var converter = CustomConverter.ForConverterType(typeof(DictionaryHolderConverter), typeof(DictionaryHolder)); var holder = (DictionaryHolder)converter.DeserializeValue(context, value); var dictionary = holder.Dictionary; // The regular fields deserialized from the map Assert.Equal("value1", dictionary["key1"]); Assert.Equal("value2", dictionary["key2"]); // The server-provided values Assert.Equal(context.DocumentReference, dictionary["DocumentId"]); Assert.Equal(context.Snapshot.CreateTime, dictionary["CreateTime"]); Assert.Equal(context.Snapshot.UpdateTime, dictionary["UpdateTime"]); Assert.Equal(context.Snapshot.ReadTime, dictionary["ReadTime"]); }
/// <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()); }
/// <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()); } }
/// <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; } } }