private static void ApplyNonPlayerWorldObject(ModelPlayToClient fromServ)
        {
            try
            {
                if (fromServ.WObjectOnlineToDelete != null && fromServ.WObjectOnlineToDelete.Count > 0)
                {
                    var objectToDelete = Find.WorldObjects.AllWorldObjects.Where(wo => wo is Settlement)
                                         .Where(wo => wo.HasName && !wo.Faction.IsPlayer)
                                         .Where(o => fromServ.WObjectOnlineToDelete.Any(fs => ValidateOnlineWorldObject(fs, o))).ToList();
                    objectToDelete.ForEach(o => {
                        Find.WorldObjects.SettlementAt(o.Tile).Destroy();
                        Find.World.WorldUpdate();
                    });
                    if (LastWorldObjectOnline != null && LastWorldObjectOnline.Count > 0)
                    {
                        LastWorldObjectOnline.RemoveAll(WOnline => objectToDelete.Any(o => ValidateOnlineWorldObject(WOnline, o)));
                    }
                }

                if (fromServ.WObjectOnlineToAdd != null && fromServ.WObjectOnlineToAdd.Count > 0)
                {
                    for (var i = 0; i < fromServ.WObjectOnlineToAdd.Count; i++)
                    {
                        if (!Find.WorldObjects.AnySettlementAt(fromServ.WObjectOnlineToAdd[i].Tile))
                        {
                            Faction faction = Find.FactionManager.AllFactionsListForReading.FirstOrDefault(fm =>
                                                                                                           fm.def.LabelCap == fromServ.WObjectOnlineToAdd[i].FactionGroup &&
                                                                                                           fm.loadID == fromServ.WObjectOnlineToAdd[i].loadID);
                            if (faction != null)
                            {
                                var npcBase = (Settlement)WorldObjectMaker.MakeWorldObject(WorldObjectDefOf.Settlement);
                                npcBase.SetFaction(faction);
                                npcBase.Tile = fromServ.WObjectOnlineToAdd[i].Tile;
                                npcBase.Name = fromServ.WObjectOnlineToAdd[i].Name;
                                Find.WorldObjects.Add(npcBase);
                                //LastWorldObjectOnline.Add(fromServ.OnlineWObjectToAdd[i]);
                            }
                            else
                            {
                                Log.Warning("Faction is missing or not found : " + fromServ.WObjectOnlineToAdd[i].FactionGroup);
                                Loger.Log("Skipping ToAdd Settlement : " + fromServ.WObjectOnlineToAdd[i].Name);
                            }
                        }
                        else
                        {
                            Loger.Log("Can't Add Settlement. Tile is already occupied " + Find.WorldObjects.SettlementAt(fromServ.WObjectOnlineToAdd[i].Tile));
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Log.Error("Exception LoadFromServer ApplyNonPlayerWorldObject >> " + e);
            }
        }
        private static void ApplyFactionsToWorld(ModelPlayToClient fromServ)
        {
            try
            {
                // ! WIP Factions
                if (fromServ.FactionOnlineToDelete != null && fromServ.FactionOnlineToDelete.Count > 0)
                {
                    var factionToDelete = Find.FactionManager.AllFactionsListForReading.Where(f => !f.IsPlayer)
                                          .Where(obj => fromServ.FactionOnlineToDelete.Any(fs => ValidateFaction(fs, obj))).ToList();

                    OCFactionManager.UpdateFactionIDS(fromServ.FactionOnlineList);
                    for (var i = 0; i < factionToDelete.Count; i++)
                    {
                        OCFactionManager.DeleteFaction(factionToDelete[i]);
                    }

                    if (LastFactionOnline != null && LastFactionOnline.Count > 0)
                    {
                        LastFactionOnline.RemoveAll(FOnline => factionToDelete.Any(obj => ValidateFaction(FOnline, obj)));
                    }
                }

                if (fromServ.FactionOnlineToAdd != null && fromServ.FactionOnlineToAdd.Count > 0)
                {
                    for (var i = 0; i < fromServ.FactionOnlineToAdd.Count; i++)
                    {
                        try
                        {
                            var existingFaction = Find.FactionManager.AllFactionsListForReading.Where(f => ValidateFaction(fromServ.FactionOnlineToAdd[i], f)).ToList();
                            if (existingFaction.Count == 0)
                            {
                                OCFactionManager.UpdateFactionIDS(fromServ.FactionOnlineList);
                                OCFactionManager.AddNewFaction(fromServ.FactionOnlineToAdd[i]);
                            }
                            else
                            {
                                Loger.Log("Failed to add faction. Faction already exists. > " + fromServ.FactionOnlineToAdd[i].LabelCap);
                            }
                        }
                        catch
                        {
                            Loger.Log("Error faction to add LabelCap >> " + fromServ.FactionOnlineToAdd[i].LabelCap);
                            Loger.Log("Error faction to add DefName >> " + fromServ.FactionOnlineToAdd[i].DefName);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Log.Error("OnlineCity: Error Apply new faction to world >> " + e);
            }
        }
        public static void LoadFromServer(ModelPlayToClient fromServ, bool removeMissing)
        {
            if (removeMissing)
            {
                //запускается только при первом получении данных от сервера после загрузки или создания карты
                //удаляем все объекты других игроков (на всякий случай, т.к. в сейв они не сохраняются)

                var missingWObjects = Find.WorldObjects.AllWorldObjects
                                      .Select(o => o as CaravanOnline)
                                      .Where(o => o != null)
                                      //.Where(o => !fromServ.WObjects.Any(wo => wo.ServerId == o.OnlineWObject.ServerId))
                                      .ToList();
                for (int i = 0; i < missingWObjects.Count; i++)
                {
                    Find.WorldObjects.Remove(missingWObjects[i]);
                }
                Loger.Log("RemoveMissing " + missingWObjects.Count);
            }

            //обновление всех объектов
            ToDelete = new List <WorldObjectEntry>();
            if (fromServ.WObjects != null && fromServ.WObjects.Count > 0)
            {
                for (int i = 0; i < fromServ.WObjects.Count; i++)
                {
                    ApplyWorldObject(fromServ.WObjects[i]);
                }
            }
            if (fromServ.WObjectsToDelete != null && fromServ.WObjectsToDelete.Count > 0)
            {
                for (int i = 0; i < fromServ.WObjectsToDelete.Count; i++)
                {
                    DeleteWorldObject(fromServ.WObjectsToDelete[i]);
                }
            }

            //пришла посылка от каравана другого игрока
            if (fromServ.Mails != null && fromServ.Mails.Count > 0)
            {
                LongEventHandler.QueueLongEvent(delegate
                                                //LongEventHandler.ExecuteWhenFinished(delegate
                {
                    foreach (var mail in fromServ.Mails)
                    {
                        if (mail.To == null ||
                            mail.To.Login != SessionClientController.My.Login ||
                            mail.Things == null ||
                            mail.Things.Count == 0 ||
                            mail.PlaceServerId <= 0)
                        {
                            continue;
                        }
                        //находим наш объект, кому пришла передача
                        var placeId = MyWorldObjectEntry
                                      .Where(p => p.Value.ServerId == mail.PlaceServerId)
                                      .Select(p => p.Key)
                                      .FirstOrDefault();

                        Loger.Log("Mail " + placeId + " "
                                  + (mail.From == null ? "-" : mail.From.Login) + "->"
                                  + (mail.To == null ? "-" : mail.To.Login) + ":"
                                  + mail.ContentString());
                        WorldObject place;
                        if (placeId == 0)
                        {
                            //если нет, и какой-то сбой, посылаем в первый поселек
                            place = Find.WorldObjects.Settlements
                                    .FirstOrDefault(f => f.Faction == Faction.OfPlayer && f is MapParent && ((MapParent)f).Map.IsPlayerHome);
                        }
                        else
                        {
                            place = Find.WorldObjects.AllWorldObjects
                                    .FirstOrDefault(o => o.ID == placeId && o.Faction == Faction.OfPlayer);
                        }
                        //создаем объекты
                        if (place != null)
                        {
                            DropToWorldObject(place, mail.Things, (mail.From == null ? "-" : mail.From.Login));
                        }
                    }
                }, "", false, null);
            }
        }
        private static void UpdateWorld(bool firstRun = false)
        {
            lock (UpdatingWorld)
            {
                Command((connect) =>
                {
                    //собираем пакет на сервер
                    var toServ = new ModelPlayToServer()
                    {
                        UpdateTime = Data.UpdateTime, //время прошлого запроса
                    };
                    //данные сохранения игры
                    if (Data.SaveFileData != null)
                    {
                        toServ.SaveFileData = Data.SaveFileData;
                        Data.SaveFileData   = null;
                    }

                    //собираем данные с планеты
                    if (!firstRun)
                    {
                        UpdateWorldController.SendToServer(toServ);
                    }

                    //запрос на информацию об игроках. Можно будет ограничить редкое получение для тех кто оффлайн
                    if (Data.Chats != null && Data.Chats[0].PartyLogin != null)
                    {
                        toServ.GetPlayersInfo = Data.Chats[0].PartyLogin;
                    }

                    //отправляем на сервер, получаем ответ
                    ModelPlayToClient fromServ = connect.PlayInfo(toServ);
                    Loger.Log("Client " + My.Login + " UpdateWorld "
                              + string.Format("Отпр. свои {0}, своиDel {1}{5}. Пришло {2}, del {3}, посылок {4}"
                                              , toServ.WObjects == null ? 0 : toServ.WObjects.Count
                                              , toServ.WObjectsToDelete == null ? 0 : toServ.WObjectsToDelete.Count
                                              , fromServ.WObjects == null ? 0 : fromServ.WObjects.Count
                                              , fromServ.WObjectsToDelete == null ? 0 : fromServ.WObjectsToDelete.Count
                                              , fromServ.Mails == null ? 0 : fromServ.Mails.Count
                                              , toServ.SaveFileData == null || toServ.SaveFileData.Length == 0 ? "" : ", сейв"
                                              ));

                    //сохраняем время актуальности данных
                    Data.UpdateTime = fromServ.UpdateTime;

                    //обновляем информацию по игрокам
                    if (fromServ.PlayersInfo != null && fromServ.PlayersInfo.Count > 0)
                    {
                        foreach (var pi in fromServ.PlayersInfo)
                        {
                            if (pi.Login == null)
                            {
                                continue;
                            }
                            if (Data.Players.ContainsKey(pi.Login))
                            {
                                Data.Players[pi.Login] = new PlayerClient()
                                {
                                    Public = pi
                                }
                            }
                            ;
                            else
                            {
                                Data.Players.Add(pi.Login, new PlayerClient()
                                {
                                    Public = pi
                                });
                            }
                        }
                    }
                    var allWObjects = Find.WorldObjects.AllWorldObjects
                                      .Where(o => o is CaravanOnline)
                                      .Select(o => o as CaravanOnline)
                                      .ToList();
                    foreach (var pi in Data.Players)
                    {
                        pi.Value.WObjects = allWObjects.Where(wo => wo.OnlinePlayerLogin == pi.Key).ToList();
                    }

                    //обновляем планету
                    UpdateWorldController.LoadFromServer(fromServ);
                });
            }
        }
Beispiel #5
0
        public ModelPlayToClient PlayInfo(ModelPlayToServer packet)
        {
            if (Player == null)
            {
                return(null);
            }

            lock (Player)
            {
                var data     = Repository.GetData;
                var timeNow  = DateTime.UtcNow;
                var toClient = new ModelPlayToClient();
                toClient.UpdateTime = timeNow;
                if (packet.GetPlayersInfo != null && packet.GetPlayersInfo.Count > 0)
                {
                    var pSee = PartyLoginSee();
                    var pGet = pSee.Where(s => packet.GetPlayersInfo.Any(p => s == p)).ToList();
                    toClient.PlayersInfo = Repository.GetData.PlayersAll
                                           .Where(p => pGet.Any(g => g == p.Public.Login))
                                           .Select(p => p.Public)
                                           .ToList();
                    if (pGet.Any(p => p == null))
                    {
                        Loger.Log("nulllllll");
                    }
                }
                if (packet.SaveFileData != null && packet.SaveFileData.Length > 0)
                {
                    Player.SaveDataPacket      = packet.SaveFileData;
                    Player.Public.LastSaveTime = timeNow;
                    Repository.Get.ChangeData  = true;
                }
                Player.Public.LastTick = packet.LastTick;

                var pLogin = Player.Public.Login;
                //packet.WObjects тут все объекты этого игрока, добавляем которых у нас нет
                var pWOs = packet.WObjects ?? new List <WorldObjectEntry>();
                //packet.WObjectsToDelete тут те объекты этого игрока, что нужно удалить
                var pDs = packet.WObjectsToDelete ?? new List <WorldObjectEntry>();
                //передаем назад объекты у которых не было ServerId, т.е. они новые для сервера + все с изменениями
                var outWO  = new List <WorldObjectEntry>();
                var outWOD = new List <WorldObjectEntry>();
                //это первое обращение, если не прислали своих объектов
                var first = pWOs.Count == 0;
                lock (data)
                {
                    for (int i = 0; i < pDs.Count; i++)
                    {
                        if (pDs[i].LoginOwner != Player.Public.Login)
                        {
                            continue;
                        }
                        var sid = pDs[i].ServerId;
                        var pD  = data.WorldObjects.FirstOrDefault(p => p.ServerId == sid);
                        if (pD != null)
                        {
                            //удаление из базы
                            pD.UpdateTime = timeNow;
                            data.WorldObjects.Remove(pD);
                            data.WorldObjectsDeleted.Add(pD);
                        }
                    }

                    for (int i = 0; i < pWOs.Count; i++)
                    {
                        if (pWOs[i].LoginOwner != Player.Public.Login)
                        {
                            continue;                                            // <-на всякий случай
                        }
                        var sid = pWOs[i].ServerId;
                        if (sid == 0)
                        {
                            //добавление в базу
                            pWOs[i].UpdateTime = timeNow;
                            pWOs[i].ServerId   = data.GetWorldObjectEntryId();
                            data.WorldObjects.Add(pWOs[i]);
                            outWO.Add(pWOs[i]);
                            continue;
                        }
                        var WO = data.WorldObjects.FirstOrDefault(p => p.ServerId == sid);
                        if (WO != null)
                        {
                            //данный объект уже есть в базу обновляем по нему информкацию
                            if (WO.Name != pWOs[i].Name)
                            {
                                WO.UpdateTime = timeNow;
                                WO.Name       = pWOs[i].Name;
                            }
                            if (WO.FreeWeight != pWOs[i].FreeWeight)
                            {
                                WO.UpdateTime = timeNow;
                                WO.FreeWeight = pWOs[i].FreeWeight;
                            }
                            if (WO.MarketValue != pWOs[i].MarketValue)
                            {
                                WO.UpdateTime  = timeNow;
                                WO.MarketValue = pWOs[i].MarketValue;
                            }
                            if (WO.MarketValuePawn != pWOs[i].MarketValuePawn)
                            {
                                WO.UpdateTime      = timeNow;
                                WO.MarketValuePawn = pWOs[i].MarketValuePawn;
                            }
                            if (WO.Tile != pWOs[i].Tile)
                            {
                                WO.UpdateTime = timeNow;
                                WO.Tile       = pWOs[i].Tile;
                            }
                        }
                        else
                        {
                            Loger.Log("PlayInfo find error add WO: " + pWOs[i].Name + " sid=" + sid);
                        }
                    }

                    //передаем объекты других игроков + при первом обращении first
                    for (int i = 0; i < data.WorldObjects.Count; i++)
                    {
                        if (data.WorldObjects[i].UpdateTime < packet.UpdateTime)
                        {
                            continue;
                        }
                        if (!first && data.WorldObjects[i].LoginOwner == pLogin)
                        {
                            continue;
                        }
                        outWO.Add(data.WorldObjects[i]);
                    }

                    //передаем удаленные объекты других игроков (не для первого запроса)
                    if (packet.UpdateTime > DateTime.MinValue)
                    {
                        for (int i = 0; i < data.WorldObjectsDeleted.Count; i++)
                        {
                            if (data.WorldObjectsDeleted[i].UpdateTime < packet.UpdateTime)
                            {
                                //Удаляем все записи сроком старше 2х минут (их нужно хранить время между тем как игрок у которого удалился караван зальёт это на сервер, и все другие онлайн игроки получат эту инфу, а обновление идет раз в 5 сек)
                                if ((timeNow - data.WorldObjectsDeleted[i].UpdateTime).TotalSeconds > 120000)
                                {
                                    data.WorldObjectsDeleted.RemoveAt(i--);
                                }
                                continue;
                            }
                            if (data.WorldObjectsDeleted[i].LoginOwner == pLogin)
                            {
                                continue;
                            }
                            outWOD.Add(data.WorldObjectsDeleted[i]);
                        }
                    }

                    //завершили сбор информации клиенту
                    toClient.WObjects         = outWO;
                    toClient.WObjectsToDelete = outWOD;
                    Player.LastUpdateTime     = timeNow;
                }

                //прикрепляем письма
                toClient.Mails = Player.Mails;
                Player.Mails   = new List <ModelMailTrade>();

                //флаг, что на клиента кто-то напал и он должен запросить подробности
                toClient.AreAttacking = Player.AttackData != null && Player.AttackData.Host == Player && Player.AttackData.State == 1;

                return(toClient);
            }
        }
Beispiel #6
0
        public static void LoadFromServer(ModelPlayToClient fromServ)
        {
            //обновление всех объектов
            ToDelete = new List <WorldObjectEntry>();
            if (fromServ.WObjects != null && fromServ.WObjects.Count > 0)
            {
                for (int i = 0; i < fromServ.WObjects.Count; i++)
                {
                    ApplyWorldObject(fromServ.WObjects[i]);
                }
            }
            if (fromServ.WObjectsToDelete != null && fromServ.WObjectsToDelete.Count > 0)
            {
                for (int i = 0; i < fromServ.WObjectsToDelete.Count; i++)
                {
                    DeleteWorldObject(fromServ.WObjectsToDelete[i]);
                }
            }

            //пришла посылка от каравана другого игрока
            if (fromServ.Mails != null && fromServ.Mails.Count > 0)
            {
                LongEventHandler.QueueLongEvent(delegate
                                                //LongEventHandler.ExecuteWhenFinished(delegate
                {
                    foreach (var mail in fromServ.Mails)
                    {
                        if (mail.To == null ||
                            mail.To.Login != SessionClientController.My.Login ||
                            mail.Things == null ||
                            mail.Things.Count == 0 ||
                            mail.PlaceServerId <= 0)
                        {
                            continue;
                        }
                        //находим наш объект, кому пришла передача
                        var placeId = MyWorldObjectEntry
                                      .Where(p => p.Value.ServerId == mail.PlaceServerId)
                                      .Select(p => p.Key)
                                      .FirstOrDefault();

                        Loger.Log("Mail " + placeId + " "
                                  + (mail.From == null ? "-" : mail.From.Login) + "->"
                                  + (mail.To == null ? "-" : mail.To.Login) + ":"
                                  + mail.ContentString());
                        WorldObject place;
                        if (placeId == 0)
                        {
                            //если нет, и какой-то сбой, посылаем в первый поселек
                            place = Find.WorldObjects.FactionBases
                                    .FirstOrDefault(f => f.Faction == Faction.OfPlayer);
                        }
                        else
                        {
                            place = Find.WorldObjects.AllWorldObjects
                                    .FirstOrDefault(o => o.ID == placeId && o.Faction == Faction.OfPlayer);
                        }
                        //создаем объекты
                        if (place != null)
                        {
                            DropToWorldObject(place, mail.Things, (mail.From == null ? "-" : mail.From.Login));
                        }
                    }
                }, "", false, null);
            }
        }
Beispiel #7
0
        public ModelPlayToClient PlayInfo(ModelPlayToServer packet)
        {
            if (Player == null)
            {
                return(null);
            }

            lock (Player)
            {
                var data     = Repository.GetData;
                var timeNow  = DateTime.UtcNow;
                var toClient = new ModelPlayToClient();
                toClient.UpdateTime = timeNow;
                if (packet.GetPlayersInfo != null && packet.GetPlayersInfo.Count > 0)
                {
                    var pSee = PartyLoginSee();
                    var pGet = pSee.Where(s => packet.GetPlayersInfo.Any(p => s == p)).ToList();
                    toClient.PlayersInfo = Repository.GetData.PlayersAll
                                           .Where(p => pGet.Any(g => g == p.Public.Login))
                                           .Select(p => p.Public)
                                           .ToList();
                    if (pGet.Any(p => p == null))
                    {
                        Loger.Log("nulllllll");
                    }
                }
                if (packet.SaveFileData != null && packet.SaveFileData.Length > 0)
                {
                    Player.SaveDataPacket      = GZip.ZipByteByte(packet.SaveFileData);
                    Player.Public.ExistMap     = true;
                    Player.Public.LastSaveTime = timeNow;
                    Repository.Get.ChangeData  = true;
                }
                Player.Public.LastTick = packet.LastTick;

                var pLogin = Player.Public.Login;
                //packet.WObjects тут все объекты этого игрока, добавляем которых у нас нет
                var pWOs = packet.WObjects ?? new List <WorldObjectEntry>();
                //packet.WObjectsToDelete тут те объекты этого игрока, что нужно удалить
                var pDs = packet.WObjectsToDelete ?? new List <WorldObjectEntry>();
                //передаем назад объекты у которых не было ServerId, т.е. они новые для сервера + все с изменениями
                var outWO  = new List <WorldObjectEntry>();
                var outWOD = new List <WorldObjectEntry>();
                //это первое обращение, если не прислали своих объектов
                var first = pWOs.Count == 0;
                lock (data)
                {
                    for (int i = 0; i < pDs.Count; i++)
                    {
                        if (pDs[i].LoginOwner != Player.Public.Login)
                        {
                            continue;
                        }
                        var sid = pDs[i].ServerId;
                        var pD  = data.WorldObjects.FirstOrDefault(p => p.ServerId == sid);
                        if (pD != null)
                        {
                            //удаление из базы
                            pD.UpdateTime = timeNow;
                            data.WorldObjects.Remove(pD);
                            data.WorldObjectsDeleted.Add(pD);
                        }
                    }

                    for (int i = 0; i < pWOs.Count; i++)
                    {
                        if (pWOs[i].LoginOwner != Player.Public.Login)
                        {
                            continue;                                            // <-на всякий случай
                        }
                        var sid = pWOs[i].ServerId;
                        if (sid == 0)
                        {
                            //добавление в базу
                            pWOs[i].UpdateTime = timeNow;
                            pWOs[i].ServerId   = data.GetWorldObjectEntryId();
                            data.WorldObjects.Add(pWOs[i]);
                            outWO.Add(pWOs[i]);
                            continue;
                        }
                        var WO = data.WorldObjects.FirstOrDefault(p => p.ServerId == sid);
                        if (WO != null)
                        {
                            //данный объект уже есть в базу обновляем по нему информкацию
                            if (WO.Name != pWOs[i].Name)
                            {
                                WO.UpdateTime = timeNow;
                                WO.Name       = pWOs[i].Name;
                            }
                            if (WO.FreeWeight != pWOs[i].FreeWeight)
                            {
                                WO.UpdateTime = timeNow;
                                WO.FreeWeight = pWOs[i].FreeWeight;
                            }
                            if (WO.MarketValue != pWOs[i].MarketValue)
                            {
                                WO.UpdateTime  = timeNow;
                                WO.MarketValue = pWOs[i].MarketValue;
                            }
                            if (WO.MarketValuePawn != pWOs[i].MarketValuePawn)
                            {
                                WO.UpdateTime      = timeNow;
                                WO.MarketValuePawn = pWOs[i].MarketValuePawn;
                            }
                            if (WO.Tile != pWOs[i].Tile)
                            {
                                WO.UpdateTime = timeNow;
                                WO.Tile       = pWOs[i].Tile;
                            }
                        }
                    }

                    //передаем объекты других игроков + при первом обращении first
                    for (int i = 0; i < data.WorldObjects.Count; i++)
                    {
                        if (data.WorldObjects[i].UpdateTime < packet.UpdateTime)
                        {
                            continue;
                        }
                        if (!first && data.WorldObjects[i].LoginOwner == pLogin)
                        {
                            continue;
                        }
                        outWO.Add(data.WorldObjects[i]);
                    }

                    //передаем удаленные объекты других игроков
                    for (int i = 0; i < data.WorldObjectsDeleted.Count; i++)
                    {
                        if (data.WorldObjectsDeleted[i].UpdateTime < packet.UpdateTime)
                        {
                            continue;
                        }
                        if (data.WorldObjectsDeleted[i].LoginOwner == pLogin)
                        {
                            continue;
                        }
                        outWOD.Add(data.WorldObjectsDeleted[i]);
                    }

                    //завершили сбор информации клиенту
                    toClient.WObjects         = outWO;
                    toClient.WObjectsToDelete = outWOD;
                    Player.LastUpdateTime     = timeNow;

                    //обслуживание data.WorldObjectsDeleted
                    for (int i = 0; i < data.WorldObjectsDeleted.Count; i++)
                    {
                        var delTime = data.WorldObjectsDeleted[i].UpdateTime;
                        if (data.PlayersAll.All(p => p.LastUpdateTime > delTime))
                        {
                            data.WorldObjectsDeleted.RemoveAt(i--);
                        }
                    }
                }

                //прикрепляем письма
                toClient.Mails = Player.Mails;
                Player.Mails   = new List <ModelMailTrade>();

                return(toClient);
            }
        }
Beispiel #8
0
        public ModelPlayToClient playInfo(ModelPlayToServer packet, ServiceContext context)
        {
            if (Repository.CheckIsBanIP(context.AddrIP))
            {
                context.Disconnect("New BanIP " + context.AddrIP);
                return(null);
            }
            if (context.PossiblyIntruder)
            {
                context.Disconnect("Possibly intruder");
                return(null);
            }
            lock (context.Player)
            {
                var data     = Repository.GetData;
                var timeNow  = DateTime.UtcNow;
                var toClient = new ModelPlayToClient();
                toClient.UpdateTime = timeNow;
                if (packet.GetPlayersInfo != null && packet.GetPlayersInfo.Count > 0)
                {
                    var pSee = StaticHelper.PartyLoginSee(context.Player);
                    var pGet = new HashSet <string>(packet.GetPlayersInfo);
                    pGet.IntersectWith(pSee);

                    toClient.PlayersInfo = pGet
                                           .Where(l => Repository.GetData.PlayersAllDic.ContainsKey(l))
                                           .Select(l => Repository.GetData.PlayersAllDic[l].Public)
                                           .ToList();
                }
                if (packet.SaveFileData != null && packet.SaveFileData.Length > 0)
                {
                    Repository.GetSaveData.SavePlayerData(context.Player.Public.Login, packet.SaveFileData, packet.SingleSave);
                    context.Player.Public.LastSaveTime = timeNow;

                    //Действия при сохранении, оно происодит только здесь!
                    context.Player.MailsConfirmationSave = new List <ModelMail>();

                    Repository.Get.ChangeData = true;
                }
                if (context.Player.GetKeyReconnect())
                {
                    toClient.KeyReconnect = context.Player.KeyReconnect1;
                }

                var pLogin = context.Player.Public.Login;
                //packet.WObjects тут все объекты этого игрока, добавляем которых у нас нет
                var pWOs = packet.WObjects ?? new List <WorldObjectEntry>();
                //packet.WObjectsToDelete тут те объекты этого игрока, что нужно удалить
                var pDs = packet.WObjectsToDelete ?? new List <WorldObjectEntry>();
                //передаем назад объекты у которых не было ServerId, т.е. они новые для сервера + все с изменениями
                var outWO  = new List <WorldObjectEntry>();
                var outWOD = new List <WorldObjectEntry>();
                //это первое обращение, если не прислали своих объектов
                var first = pWOs.Count == 0;
                lock (data)
                {
                    for (int i = 0; i < pDs.Count; i++)
                    {
                        if (pDs[i].LoginOwner != context.Player.Public.Login)
                        {
                            continue;
                        }
                        var sid = pDs[i].ServerId;
                        var pD  = data.WorldObjects.FirstOrDefault(p => p.ServerId == sid);
                        if (pD != null)
                        {
                            //удаление из базы
                            pD.UpdateTime = timeNow;
                            data.WorldObjects.Remove(pD);
                            data.WorldObjectsDeleted.Add(pD);
                        }
                    }

                    for (int i = 0; i < pWOs.Count; i++)
                    {
                        if (pWOs[i].LoginOwner != context.Player.Public.Login)
                        {
                            continue;                                                    // <-на всякий случай
                        }
                        var sid = pWOs[i].ServerId;
                        if (sid == 0)
                        {
                            //добавление в базу
                            pWOs[i].UpdateTime = timeNow;
                            pWOs[i].ServerId   = data.GetWorldObjectEntryId();
                            data.WorldObjects.Add(pWOs[i]);
                            outWO.Add(pWOs[i]);
                            continue;
                        }
                        var WO = data.WorldObjects.FirstOrDefault(p => p.ServerId == sid);
                        if (WO != null)
                        {
                            //данный объект уже есть в базу обновляем по нему информкацию
                            if (WO.Name != pWOs[i].Name)
                            {
                                WO.UpdateTime = timeNow;
                                WO.Name       = pWOs[i].Name;
                            }
                            if (WO.FreeWeight != pWOs[i].FreeWeight)
                            {
                                WO.UpdateTime = timeNow;
                                WO.FreeWeight = pWOs[i].FreeWeight;
                            }
                            if (WO.MarketValue != pWOs[i].MarketValue)
                            {
                                WO.UpdateTime  = timeNow;
                                WO.MarketValue = pWOs[i].MarketValue;
                            }
                            if (WO.MarketValuePawn != pWOs[i].MarketValuePawn)
                            {
                                WO.UpdateTime      = timeNow;
                                WO.MarketValuePawn = pWOs[i].MarketValuePawn;
                            }
                            if (WO.Tile != pWOs[i].Tile)
                            {
                                WO.UpdateTime = timeNow;
                                WO.Tile       = pWOs[i].Tile;
                            }
                        }
                        else
                        {
                            Loger.Log("PlayInfo find error add WO: " + pWOs[i].Name + " sid=" + sid);
                        }
                    }

                    //передаем объекты других игроков + при первом обращении first
                    for (int i = 0; i < data.WorldObjects.Count; i++)
                    {
                        if (data.WorldObjects[i].UpdateTime < packet.UpdateTime)
                        {
                            continue;
                        }
                        if (!first && data.WorldObjects[i].LoginOwner == pLogin)
                        {
                            continue;
                        }
                        outWO.Add(data.WorldObjects[i]);
                    }

                    //передаем удаленные объекты других игроков (не для первого запроса)
                    if (packet.UpdateTime > DateTime.MinValue)
                    {
                        for (int i = 0; i < data.WorldObjectsDeleted.Count; i++)
                        {
                            if (data.WorldObjectsDeleted[i].UpdateTime < packet.UpdateTime)
                            {
                                //Удаляем все записи сроком старше 2х минут (их нужно хранить время между тем как игрок у которого удалился караван зальёт это на сервер, и все другие онлайн игроки получат эту инфу, а обновление идет раз в 5 сек)
                                if ((timeNow - data.WorldObjectsDeleted[i].UpdateTime).TotalSeconds > 120000)
                                {
                                    data.WorldObjectsDeleted.RemoveAt(i--);
                                }
                                continue;
                            }
                            if (data.WorldObjectsDeleted[i].LoginOwner == pLogin)
                            {
                                continue;
                            }
                            outWOD.Add(data.WorldObjectsDeleted[i]);
                        }
                    }

                    //World Object Online
                    if (ServerManager.ServerSettings.GeneralSettings.EquableWorldObjects)
                    {
                        //World Object Online
                        try
                        {
                            if (packet.WObjectOnlineToDelete != null && packet.WObjectOnlineToDelete.Count > 0)
                            {
                                data.WorldObjectOnlineList.RemoveAll(data => packet.WObjectOnlineToDelete.Any(pkt => ValidateWorldObject(pkt, data)));
                            }
                            if (packet.WObjectOnlineToAdd != null && packet.WObjectOnlineToAdd.Count > 0)
                            {
                                data.WorldObjectOnlineList.AddRange(packet.WObjectOnlineToAdd);
                            }
                            if (packet.WObjectOnlineList != null && packet.WObjectOnlineList.Count > 0)
                            {
                                if (data.WorldObjectOnlineList.Count == 0)
                                {
                                    data.WorldObjectOnlineList = packet.WObjectOnlineList;
                                }
                                else if (data.WorldObjectOnlineList != null && data.WorldObjectOnlineList.Count > 0)
                                {
                                    toClient.WObjectOnlineToDelete = packet.WObjectOnlineList.Where(pkt => !data.WorldObjectOnlineList.Any(data => ValidateWorldObject(pkt, data))).ToList();
                                    toClient.WObjectOnlineToAdd    = data.WorldObjectOnlineList.Where(data => !packet.WObjectOnlineList.Any(pkt => ValidateWorldObject(pkt, data))).ToList();
                                }
                            }
                            toClient.WObjectOnlineList = data.WorldObjectOnlineList;
                        }
                        catch
                        {
                            Loger.Log("ERROR PLAYINFO World Object Online");
                        }

                        //Faction Online
                        try
                        {
                            if (packet.FactionOnlineToDelete != null && packet.FactionOnlineToDelete.Count > 0)
                            {
                                data.FactionOnlineList.RemoveAll(data => packet.FactionOnlineToDelete.Any(pkt => ValidateFaction(pkt, data)));
                            }
                            if (packet.FactionOnlineToAdd != null && packet.FactionOnlineToAdd.Count > 0)
                            {
                                data.FactionOnlineList.AddRange(packet.FactionOnlineToAdd);
                            }
                            if (packet.FactionOnlineList != null && packet.FactionOnlineList.Count > 0)
                            {
                                if (data.FactionOnlineList.Count == 0)
                                {
                                    data.FactionOnlineList = packet.FactionOnlineList;
                                }
                                else if (data.FactionOnlineList != null && data.FactionOnlineList.Count > 0)
                                {
                                    toClient.FactionOnlineToDelete = packet.FactionOnlineList.Where(pkt => !data.FactionOnlineList.Any(data => ValidateFaction(pkt, data))).ToList();
                                    toClient.FactionOnlineToAdd    = data.FactionOnlineList.Where(data => !packet.FactionOnlineList.Any(pkt => ValidateFaction(pkt, data))).ToList();
                                }
                            }
                            toClient.FactionOnlineList = data.FactionOnlineList;
                        }
                        catch
                        {
                            Loger.Log("ERROR PLAYINFO Faction Online");
                        }
                    }

                    //завершили сбор информации клиенту
                    toClient.WObjects         = outWO;
                    toClient.WObjectsToDelete = outWOD;

                    context.Player.WLastUpdateTime = timeNow;
                    context.Player.WLastTick       = packet.LastTick;

                    //обновляем статистические поля
                    var costAll = context.Player.CostWorldObjects();
                    if (context.Player.StartMarketValuePawn == 0)
                    {
                        context.Player.StartMarketValue     = costAll.MarketValue;
                        context.Player.StartMarketValuePawn = costAll.MarketValuePawn;

                        context.Player.DeltaMarketValue     = 0;
                        context.Player.DeltaMarketValuePawn = 0;
                    }
                    else if (context.Player.LastUpdateIsGood && (costAll.MarketValue > 0 || costAll.MarketValuePawn > 0))
                    {
                        //считаем дельту
                        context.Player.DeltaMarketValue     = (costAll.MarketValue - context.Player.LastMarketValue);
                        context.Player.DeltaMarketValuePawn = (costAll.MarketValuePawn - context.Player.LastMarketValuePawn);

                        context.Player.SumDeltaGameMarketValue     += context.Player.DeltaMarketValue;
                        context.Player.SumDeltaGameMarketValuePawn += context.Player.DeltaMarketValuePawn;
                        context.Player.SumDeltaRealMarketValue     += context.Player.DeltaMarketValue;
                        context.Player.SumDeltaRealMarketValuePawn += context.Player.DeltaMarketValuePawn;

                        if (packet.LastTick - context.Player.StatLastTick > 15 * 60000) // сбор раз в 15 дней
                        {
                            if (context.Player.StatMaxDeltaGameMarketValue < context.Player.SumDeltaGameMarketValue)
                            {
                                context.Player.StatMaxDeltaGameMarketValue = context.Player.SumDeltaGameMarketValue;
                            }
                            if (context.Player.StatMaxDeltaGameMarketValuePawn < context.Player.SumDeltaGameMarketValuePawn)
                            {
                                context.Player.StatMaxDeltaGameMarketValuePawn = context.Player.SumDeltaGameMarketValuePawn;
                            }

                            context.Player.SumDeltaGameMarketValue     = 0;
                            context.Player.SumDeltaGameMarketValuePawn = 0;
                            context.Player.StatLastTick = packet.LastTick;
                        }

                        if (context.Player.SumDeltaRealSecond > 60 * 60) //сбор раз в час
                        {
                            if (context.Player.StatMaxDeltaRealMarketValue < context.Player.SumDeltaRealMarketValue)
                            {
                                context.Player.StatMaxDeltaRealMarketValue = context.Player.SumDeltaRealMarketValue;
                            }
                            if (context.Player.StatMaxDeltaRealMarketValuePawn < context.Player.SumDeltaRealMarketValuePawn)
                            {
                                context.Player.StatMaxDeltaRealMarketValuePawn = context.Player.SumDeltaRealMarketValuePawn;
                            }
                            if (context.Player.StatMaxDeltaRealTicks < context.Player.SumDeltaRealTicks)
                            {
                                context.Player.StatMaxDeltaRealTicks = context.Player.SumDeltaRealTicks;
                            }

                            context.Player.SumDeltaRealMarketValue     = 0;
                            context.Player.SumDeltaRealMarketValuePawn = 0;
                            context.Player.SumDeltaRealTicks           = 0;
                            context.Player.SumDeltaRealSecond          = 0;
                        }
                    }
                    context.Player.LastUpdateIsGood = costAll.MarketValue > 0 || costAll.MarketValuePawn > 0;
                    if (context.Player.LastUpdateIsGood)
                    {
                        context.Player.LastMarketValue     = costAll.MarketValue;
                        context.Player.LastMarketValuePawn = costAll.MarketValuePawn;
                    }
                    var dt = packet.LastTick - context.Player.Public.LastTick;
                    context.Player.SumDeltaRealTicks += dt;
                    if (dt > 0)
                    {
                        var ds = (long)(timeNow - context.Player.LastUpdateTime).TotalSeconds;
                        context.Player.SumDeltaRealSecond += ds;
                        context.Player.TotalRealSecond    += ds;
                    }

                    context.Player.WLastUpdateTime = context.Player.LastUpdateTime;
                    context.Player.WLastTick       = context.Player.Public.LastTick;
                    context.Player.LastUpdateTime  = timeNow;
                    context.Player.Public.LastTick = packet.LastTick;
                }

                //обновляем состояние отложенной отправки писем
                if (context.Player.FunctionMails.Count > 0)
                {
                    for (int i = 0; i < context.Player.FunctionMails.Count; i++)
                    {
                        var needRemove = context.Player.FunctionMails[i].Run(context);
                        if (needRemove)
                        {
                            context.Player.FunctionMails.RemoveAt(i--);
                        }
                    }
                }

                //прикрепляем письма
                //если есть команда на отключение без сохранения, то посылаем только одно это письмо
                var md = context.Player.Mails.FirstOrDefault(m => m is ModelMailAttackCancel);
                if (md == null)
                {
                    toClient.Mails = context.Player.Mails;
                    context.Player.MailsConfirmationSave.AddRange(context.Player.Mails.Where(m => m.NeedSaveGame).ToList());
                    context.Player.Mails = new List <ModelMail>();
                }
                else
                {
                    toClient.Mails = new List <ModelMail>()
                    {
                        md
                    };
                    context.Player.Mails.Remove(md);
                }

                //команда выполнить сохранение и отключиться
                toClient.NeedSaveAndExit = !context.Player.IsAdmin && data.EverybodyLogoff;

                //флаг, что на клиента кто-то напал и он должен запросить подробности
                toClient.AreAttacking = context.Player.AttackData != null && context.Player.AttackData.Host == context.Player && context.Player.AttackData.State == 1;

                if (toClient.Mails.Count > 0)
                {
                    foreach (var mail in toClient.Mails)
                    {
                        Loger.Log($"DownloadMail {mail.GetType().Name} {mail.From.Login}->{mail.To.Login} {mail.ContentString()}");
                    }
                }

                return(toClient);
            }
        }
        private static void UpdateWorld(bool firstRun = false)
        {
            lock (UpdatingWorld)
            {
                Command((connect) =>
                {
                    //собираем пакет на сервер
                    var toServ = new ModelPlayToServer()
                    {
                        UpdateTime = Data.UpdateTime, //время прошлого запроса
                    };
                    //данные сохранения игры
                    if (Data.SaveFileData != null)
                    {
                        toServ.SaveFileData = Data.SaveFileData;
                        toServ.SingleSave   = Data.SingleSave;
                        Data.SaveFileData   = null;
                    }

                    //собираем данные с планеты
                    if (!firstRun)
                    {
                        UpdateWorldController.SendToServer(toServ);
                    }

                    if (firstRun)
                    {
                        GetPlayersInfoCountRequest = 0;
                    }

                    //запрос на информацию об игроках. Можно будет ограничить редкое получение для тех кто оффлайн
                    if (Data.Chats != null && Data.Chats[0].PartyLogin != null)
                    {
                        if (Data.Players == null || Data.Players.Count == 0 ||
                            GetPlayersInfoCountRequest % 5 == 0)
                        {
                            //в начале и раз в пол минуты (5 сек между UpdateWorld * 5) получаем инфу обо всех
                            toServ.GetPlayersInfo = Data.Chats[0].PartyLogin;
                        }
                        else
                        {
                            //в промежутках о тех кто онлайн
                            toServ.GetPlayersInfo = Data.Players.Values.Where(p => p.Online).Select(p => p.Public.Login).ToList();
                        }
                        GetPlayersInfoCountRequest++;
                        //Loger.Log("Client " + My.Login + " UpdateWorld* " + (toServ.GetPlayersInfo.Count.ToString())
                        //    + " " + (toServ.GetPlayersInfo.Any(p => p == SessionClientController.My.Login) ? "1" : "0"));
                    }

                    //отправляем на сервер, получаем ответ
                    ModelPlayToClient fromServ = connect.PlayInfo(toServ);

                    //Loger.Log("Client UpdateWorld 5 ");
                    Loger.Log("Client " + My.Login + " UpdateWorld "
                              + string.Format("Отпр. свои {0}, своиDel {1}{5}. Пришло {2}, del {3}, игроков {8}, посылок {4}{6}{7}"
                                              , toServ.WObjects == null ? 0 : toServ.WObjects.Count
                                              , toServ.WObjectsToDelete == null ? 0 : toServ.WObjectsToDelete.Count
                                              , fromServ.WObjects == null ? 0 : fromServ.WObjects.Count
                                              , fromServ.WObjectsToDelete == null ? 0 : fromServ.WObjectsToDelete.Count
                                              , fromServ.Mails == null ? 0 : fromServ.Mails.Count
                                              , toServ.SaveFileData == null || toServ.SaveFileData.Length == 0 ? "" : ", сейв"
                                              , fromServ.AreAttacking ? " Атакуют!" : ""
                                              , fromServ.NeedSaveAndExit ? " Команда на отключение" : ""
                                              , fromServ.PlayersInfo == null ? "null" : fromServ.PlayersInfo.Count.ToString()
                                              ));

                    //сохраняем время актуальности данных
                    Data.UpdateTime = fromServ.UpdateTime;
                    if (!string.IsNullOrEmpty(fromServ.KeyReconnect))
                    {
                        Data.KeyReconnect = fromServ.KeyReconnect;
                    }

                    //обновляем информацию по игрокам
                    if (fromServ.PlayersInfo != null && fromServ.PlayersInfo.Count > 0)
                    {
                        foreach (var pi in fromServ.PlayersInfo)
                        {
                            if (pi.Login == null)
                            {
                                continue;
                            }
                            Data.Players[pi.Login] = new PlayerClient()
                            {
                                Public = pi
                            };
                            if (pi.Login == My.Login)
                            {
                                My        = pi;
                                Data.MyEx = Data.Players[pi.Login];
                                //Loger.Log("Client " + My.Login + " UpdateWorld* " + My.LastOnlineTime.ToString("o") + " " + DateTime.UtcNow.ToString("o")
                                //   + " " + (toServ.GetPlayersInfo.Any(p => p == My.Login) ? "1" : "0"));
                            }
                        }
                    }

                    //обновляем планету
                    UpdateWorldController.LoadFromServer(fromServ, firstRun);

                    //обновляем инфу по поселениям
                    var allWObjects = Find.WorldObjects.AllWorldObjects
                                      .Select(o => o as CaravanOnline)
                                      .Where(o => o != null)
                                      .ToList();
                    foreach (var pi in Data.Players)
                    {
                        if (pi.Value.Public.Login == My.Login)
                        {
                            continue;
                        }
                        pi.Value.WObjects = allWObjects.Where(wo => wo.OnlinePlayerLogin == pi.Key).ToList();
                    }

                    //Сохраняем и выходим
                    if (fromServ.NeedSaveAndExit)
                    {
                        if (!SessionClientController.Data.BackgroundSaveGameOff)
                        {
                            SessionClientController.SaveGameNow(false, () =>
                            {
                                SessionClientController.Disconnected("OCity_SessionCC_Shutdown_Command_ProgressSaved".Translate());
                            });
                        }
                        else
                        {
                            SessionClientController.Disconnected("OCity_SessionCC_Shutdown_Command".Translate());
                        }
                    }

                    //если на нас напали запускаем процесс
                    if (fromServ.AreAttacking && GameAttackHost.AttackMessage())
                    {
                        GameAttackHost.Get.Start(connect);
                    }
                });
            }
        }
        public static void LoadFromServer(ModelPlayToClient fromServ, bool removeMissing)
        {
            if (SessionClientController.Data.GeneralSettings.EquableWorldObjects)
            {
                ApplyFactionsToWorld(fromServ);
                // ---------------------------------------------------------------------------------- //
                ApplyNonPlayerWorldObject(fromServ);
            }

            if (removeMissing)
            {
                //запускается только при первом получении данных от сервера после загрузки или создания карты
                //удаляем все объекты других игроков (на всякий случай, т.к. в сейв они не сохраняются)

                var missingWObjects = Find.WorldObjects.AllWorldObjects
                                      .Select(o => o as CaravanOnline)
                                      .Where(o => o != null)
                                      //.Where(o => !fromServ.WObjects.Any(wo => wo.ServerId == o.OnlineWObject.ServerId))
                                      .ToList();
                for (int i = 0; i < missingWObjects.Count; i++)
                {
                    Find.WorldObjects.Remove(missingWObjects[i]);
                }
                Loger.Log("RemoveMissing " + missingWObjects.Count);
            }

            //обновление всех объектов
            ToDelete = new List <WorldObjectEntry>();
            if (fromServ.WObjects != null && fromServ.WObjects.Count > 0)
            {
                for (int i = 0; i < fromServ.WObjects.Count; i++)
                {
                    ApplyWorldObject(fromServ.WObjects[i]);
                }
            }
            if (fromServ.WObjectsToDelete != null && fromServ.WObjectsToDelete.Count > 0)
            {
                for (int i = 0; i < fromServ.WObjectsToDelete.Count; i++)
                {
                    DeleteWorldObject(fromServ.WObjectsToDelete[i]);
                }
            }
            //свои поселения заполняем отдельно теми, что последний раз отправляли, но на всякий случай не первый раз
            //we fill our settlements separately with those that were last sent, but just in case not for the first time
            if (!removeMissing && SessionClientController.Data.Players.ContainsKey(SessionClientController.My.Login))
            {
                SessionClientController.Data.Players[SessionClientController.My.Login].WObjects = LastSendMyWorldObjects
                                                                                                  .Select(wo => wo.Type == WorldObjectEntryType.Base
                        ? (CaravanOnline) new BaseOnline()
                {
                    Tile = wo.Tile, OnlineWObject = wo,
                }
                        : new CaravanOnline()
                {
                    Tile = wo.Tile, OnlineWObject = wo
                })
                                                                                                  .ToList();

                /*
                 * UpdateWorldController.WorldObjectEntrys.Values
                 * .Where(wo => wo.LoginOwner == SessionClientController.My.Login)
                 * .Select(wo => wo.Type == WorldObjectEntryType.Base
                 *  ? (CaravanOnline)new BaseOnline() { Tile = wo.Tile, OnlineWObject = wo }
                 *  : new CaravanOnline() { Tile = wo.Tile, OnlineWObject = wo })
                 * .ToList();
                 */
            }

            //пришла посылка от каравана другого игрока
            if (fromServ.Mails != null && fromServ.Mails.Count > 0)
            {
                LongEventHandler.QueueLongEvent(delegate
                                                //LongEventHandler.ExecuteWhenFinished(delegate
                {
                    foreach (var mail in fromServ.Mails)
                    {
                        MailController.MailArrived(mail);
                    }
                }, "", false, null);
            }
        }
Beispiel #11
0
        public ModelPlayToClient playInfo(ModelPlayToServer packet, ServiceContext context)
        {
            lock (context.Player)
            {
                var data     = Repository.GetData;
                var timeNow  = DateTime.UtcNow;
                var toClient = new ModelPlayToClient();
                toClient.UpdateTime = timeNow;
                if (packet.GetPlayersInfo != null && packet.GetPlayersInfo.Count > 0)
                {
                    var pSee = StaticHelper.PartyLoginSee(context.Player);
                    var pGet = new HashSet <string>(packet.GetPlayersInfo);
                    pGet.IntersectWith(pSee);

                    toClient.PlayersInfo = pGet
                                           .Where(l => Repository.GetData.PlayersAllDic.ContainsKey(l))
                                           .Select(l => Repository.GetData.PlayersAllDic[l].Public)
                                           .ToList();
                }
                if (packet.SaveFileData != null && packet.SaveFileData.Length > 0)
                {
                    Repository.GetSaveData.SavePlayerData(context.Player.Public.Login, packet.SaveFileData, packet.SingleSave);
                    context.Player.Public.LastSaveTime = timeNow;
                    Repository.Get.ChangeData          = true;
                }
                context.Player.Public.LastTick = packet.LastTick;
                if (context.Player.GetKeyReconnect())
                {
                    toClient.KeyReconnect = context.Player.KeyReconnect1;
                }

                var pLogin = context.Player.Public.Login;
                //packet.WObjects тут все объекты этого игрока, добавляем которых у нас нет
                var pWOs = packet.WObjects ?? new List <WorldObjectEntry>();
                //packet.WObjectsToDelete тут те объекты этого игрока, что нужно удалить
                var pDs = packet.WObjectsToDelete ?? new List <WorldObjectEntry>();
                //передаем назад объекты у которых не было ServerId, т.е. они новые для сервера + все с изменениями
                var outWO  = new List <WorldObjectEntry>();
                var outWOD = new List <WorldObjectEntry>();
                //это первое обращение, если не прислали своих объектов
                var first = pWOs.Count == 0;
                lock (data)
                {
                    for (int i = 0; i < pDs.Count; i++)
                    {
                        if (pDs[i].LoginOwner != context.Player.Public.Login)
                        {
                            continue;
                        }
                        var sid = pDs[i].ServerId;
                        var pD  = data.WorldObjects.FirstOrDefault(p => p.ServerId == sid);
                        if (pD != null)
                        {
                            //удаление из базы
                            pD.UpdateTime = timeNow;
                            data.WorldObjects.Remove(pD);
                            data.WorldObjectsDeleted.Add(pD);
                        }
                    }

                    for (int i = 0; i < pWOs.Count; i++)
                    {
                        if (pWOs[i].LoginOwner != context.Player.Public.Login)
                        {
                            continue;                                                    // <-на всякий случай
                        }
                        var sid = pWOs[i].ServerId;
                        if (sid == 0)
                        {
                            //добавление в базу
                            pWOs[i].UpdateTime = timeNow;
                            pWOs[i].ServerId   = data.GetWorldObjectEntryId();
                            data.WorldObjects.Add(pWOs[i]);
                            outWO.Add(pWOs[i]);
                            continue;
                        }
                        var WO = data.WorldObjects.FirstOrDefault(p => p.ServerId == sid);
                        if (WO != null)
                        {
                            //данный объект уже есть в базу обновляем по нему информкацию
                            if (WO.Name != pWOs[i].Name)
                            {
                                WO.UpdateTime = timeNow;
                                WO.Name       = pWOs[i].Name;
                            }
                            if (WO.FreeWeight != pWOs[i].FreeWeight)
                            {
                                WO.UpdateTime = timeNow;
                                WO.FreeWeight = pWOs[i].FreeWeight;
                            }
                            if (WO.MarketValue != pWOs[i].MarketValue)
                            {
                                WO.UpdateTime  = timeNow;
                                WO.MarketValue = pWOs[i].MarketValue;
                            }
                            if (WO.MarketValuePawn != pWOs[i].MarketValuePawn)
                            {
                                WO.UpdateTime      = timeNow;
                                WO.MarketValuePawn = pWOs[i].MarketValuePawn;
                            }
                            if (WO.Tile != pWOs[i].Tile)
                            {
                                WO.UpdateTime = timeNow;
                                WO.Tile       = pWOs[i].Tile;
                            }
                        }
                        else
                        {
                            Loger.Log("PlayInfo find error add WO: " + pWOs[i].Name + " sid=" + sid);
                        }
                    }

                    //передаем объекты других игроков + при первом обращении first
                    for (int i = 0; i < data.WorldObjects.Count; i++)
                    {
                        if (data.WorldObjects[i].UpdateTime < packet.UpdateTime)
                        {
                            continue;
                        }
                        if (!first && data.WorldObjects[i].LoginOwner == pLogin)
                        {
                            continue;
                        }
                        outWO.Add(data.WorldObjects[i]);
                    }

                    //передаем удаленные объекты других игроков (не для первого запроса)
                    if (packet.UpdateTime > DateTime.MinValue)
                    {
                        for (int i = 0; i < data.WorldObjectsDeleted.Count; i++)
                        {
                            if (data.WorldObjectsDeleted[i].UpdateTime < packet.UpdateTime)
                            {
                                //Удаляем все записи сроком старше 2х минут (их нужно хранить время между тем как игрок у которого удалился караван зальёт это на сервер, и все другие онлайн игроки получат эту инфу, а обновление идет раз в 5 сек)
                                if ((timeNow - data.WorldObjectsDeleted[i].UpdateTime).TotalSeconds > 120000)
                                {
                                    data.WorldObjectsDeleted.RemoveAt(i--);
                                }
                                continue;
                            }
                            if (data.WorldObjectsDeleted[i].LoginOwner == pLogin)
                            {
                                continue;
                            }
                            outWOD.Add(data.WorldObjectsDeleted[i]);
                        }
                    }

                    //завершили сбор информации клиенту
                    toClient.WObjects             = outWO;
                    toClient.WObjectsToDelete     = outWOD;
                    context.Player.LastUpdateTime = timeNow;
                }

                //прикрепляем письма
                //если есть команда на отключение без сохранения, то посылаем только одно это письмо
                var md = context.Player.Mails.FirstOrDefault(m => m.Type == ModelMailTradeType.AttackCancel);
                if (md == null)
                {
                    toClient.Mails       = context.Player.Mails;
                    context.Player.Mails = new List <ModelMailTrade>();
                }
                else
                {
                    toClient.Mails = new List <ModelMailTrade>()
                    {
                        md
                    };
                    context.Player.Mails.Remove(md);
                }

                //команда выполнить сохранение и отключиться
                toClient.NeedSaveAndExit = !context.Player.IsAdmin && data.EverybodyLogoff;

                //флаг, что на клиента кто-то напал и он должен запросить подробности
                toClient.AreAttacking = context.Player.AttackData != null && context.Player.AttackData.Host == context.Player && context.Player.AttackData.State == 1;

                return(toClient);
            }
        }