Ejemplo n.º 1
0
        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;
                }
            }
        }