private static void GameProgressAdd(PlayerGameProgress gameProgress, Pawn pawn)
        {
            if (pawn.Dead)
            {
                return;
            }
            if (pawn.IsFreeColonist && !pawn.IsPrisoner && !pawn.IsPrisonerOfColony)
            {
                gameProgress.ColonistsCount++;
                if (pawn.Downed)
                {
                    gameProgress.ColonistsDownCount++;
                }
                if (pawn.health.hediffSet.BleedRateTotal > 0)
                {
                    gameProgress.ColonistsBleedCount++;
                }
                //pawn.health.hediffset.pain_total    // уровень боли

                int maxSkill = 0;
                for (int i = 0; i < pawn.skills.skills.Count; i++)
                {
                    if (pawn.skills.skills[i].Level == 20)
                    {
                        maxSkill++;
                    }
                }
                if (maxSkill >= 8)
                {
                    gameProgress.PawnMaxSkill++;
                }

                var kh = pawn.records.GetAsInt(RecordDefOf.KillsHumanlikes);
                var km = pawn.records.GetAsInt(RecordDefOf.KillsMechanoids);

                gameProgress.KillsHumanlikes += kh;
                gameProgress.KillsMechanoids += km;
                if (gameProgress.KillsBestHumanlikesPawnName == null ||
                    kh > gameProgress.KillsBestHumanlikes)
                {
                    gameProgress.KillsBestHumanlikesPawnName = pawn.LabelCapNoCount;
                    gameProgress.KillsBestHumanlikes         = kh;
                }
                if (gameProgress.KillsBestMechanoidsPawnName == null ||
                    km > gameProgress.KillsBestMechanoids)
                {
                    gameProgress.KillsBestMechanoidsPawnName = pawn.LabelCapNoCount;
                    gameProgress.KillsBestMechanoids         = km;
                }
            }
        }
        /// <summary>
        /// Только для своих объетков
        /// </summary>
        public static WorldObjectEntry GetWorldObjectEntry(WorldObject worldObject
                                                           , PlayerGameProgress gameProgress
                                                           , Dictionary <Map, List <Pawn> > cacheColonists)
        {
            var worldObjectEntry = new WorldObjectEntry();

            worldObjectEntry.Type       = worldObject is Caravan ? WorldObjectEntryType.Caravan : WorldObjectEntryType.Base;
            worldObjectEntry.Tile       = worldObject.Tile;
            worldObjectEntry.Name       = worldObject.LabelCap;
            worldObjectEntry.LoginOwner = SessionClientController.My.Login;
            worldObjectEntry.FreeWeight = 999999;

            //определяем цену и вес
            var caravan = worldObject as Caravan;

            if (caravan != null)
            {
                //Loger.Log("Client TestBagSD 002");
                var transferables = CalculateTransferables(caravan);
                //Loger.Log("Client TestBagSD 003");

                List <ThingCount> stackParts = new List <ThingCount>();
                for (int i = 0; i < transferables.Count; i++)
                {
                    TransferableUtility.TransferNoSplit(transferables[i].things, transferables[i].MaxCount /*CountToTransfer*/, delegate(Thing originalThing, int toTake)
                    {
                        stackParts.Add(new ThingCount(originalThing, toTake));
                    }, false, false);
                }
                //Loger.Log("Client TestBagSD 004");
                worldObjectEntry.FreeWeight = CollectionsMassCalculator.Capacity(stackParts)
                                              - CollectionsMassCalculator.MassUsage(stackParts, IgnorePawnsInventoryMode.Ignore, false, false);
                //Loger.Log("Client TestBagSD 005");

                worldObjectEntry.MarketValue     = 0f;
                worldObjectEntry.MarketValuePawn = 0f;
                for (int i = 0; i < stackParts.Count; i++)
                {
                    int count = stackParts[i].Count;

                    if (count > 0)
                    {
                        Thing thing = stackParts[i].Thing;
                        if (thing is Pawn)
                        {
                            worldObjectEntry.MarketValuePawn += thing.MarketValue
                                                                + WealthWatcher.GetEquipmentApparelAndInventoryWealth(thing as Pawn);
                            GameProgressAdd(gameProgress, thing as Pawn);
                        }
                        else
                        {
                            worldObjectEntry.MarketValue += thing.MarketValue * (float)count;
                        }
                    }
                }
                //Loger.Log("Client TestBagSD 006");
            }
            else if (worldObject is Settlement)
            {
                //Loger.Log("Client TestBagSD 007");
                var map = (worldObject as Settlement).Map;
                if (map != null)
                {
                    //Loger.Log("Client TestBagSD 008");
                    try
                    {
                        DateTime lastForceRecount;
                        if (!LastForceRecount.TryGetValue(map.uniqueID, out lastForceRecount))
                        {
                            LastForceRecount.Add(map.uniqueID, DateTime.UtcNow.AddSeconds(new Random(map.uniqueID * 7).Next(0, 10)));
                        }
                        else if ((DateTime.UtcNow - lastForceRecount).TotalSeconds > 30)
                        {
                            LastForceRecount[map.uniqueID] = DateTime.UtcNow;
                            ModBaseData.RunMainThread(() =>
                            {
                                map.wealthWatcher.ForceRecount();
                            });
                        }
                        worldObjectEntry.MarketValue = map.wealthWatcher.WealthTotal;
                    }
                    catch
                    {
                        Thread.Sleep(100);
                        try
                        {
                            worldObjectEntry.MarketValue = map.wealthWatcher.WealthTotal;
                        }
                        catch
                        {
                        }
                    }

                    worldObjectEntry.MarketValuePawn = 0;

                    //Loger.Log("Client TestBagSD 015");
                    List <Pawn> ps;
                    if (!cacheColonists.TryGetValue(map, out ps))
                    {
                        var mapPawnsA = new Pawn[map.mapPawns.AllPawnsSpawned.Count];
                        map.mapPawns.AllPawnsSpawned.CopyTo(mapPawnsA);

                        ps = mapPawnsA.Where(p => p.Faction == Faction.OfPlayer && p.RaceProps.Humanlike).ToList();
                        cacheColonists[map] = ps;
                    }

                    //Loger.Log("Client TestBagSD 016");
                    foreach (Pawn current in ps)
                    {
                        worldObjectEntry.MarketValuePawn += current.MarketValue;

                        GameProgressAdd(gameProgress, current);
                    }
                    //Loger.Log("Client TestBagSD 017");
                    //Loger.Log("Map things "+ worldObjectEntry.MarketValue + " pawns " + worldObjectEntry.MarketValuePawn);
                }
            }
            //Loger.Log("Client TestBagSD 018");

            WorldObjectEntry storeWO;

            if (WorldObjectEntrys.TryGetValue(worldObject.ID, out storeWO))
            {
                //если серверу приходит объект без данного ServerId, значит это наш новый объект (кроме первого запроса, т.к. не было ещё загрузки)
                worldObjectEntry.ServerId = storeWO.ServerId;
            }
            //Loger.Log("Client TestBagSD 019");

            return(worldObjectEntry);
        }
        public static void SendToServer(ModelPlayToServer toServ, bool firstRun, ModelGameServerInfo modelGameServerInfo)
        {
            //Loger.Log("Empire=" + Find.FactionManager.FirstFactionOfDef(FactionDefOf.Empire)?.GetUniqueLoadID());

            toServ.LastTick = (long)Find.TickManager.TicksGame;
            var gameProgress = new PlayerGameProgress();

            var allWorldObjectsArr = new WorldObject[Find.WorldObjects.AllWorldObjects.Count];

            Find.WorldObjects.AllWorldObjects.CopyTo(allWorldObjectsArr);

            var            allWorldObjects = allWorldObjectsArr.Where(wo => wo != null).ToList();
            List <Faction> factionList     = Find.FactionManager.AllFactionsListForReading;

            if (SessionClientController.Data.GeneralSettings.EquableWorldObjects)
            {
                #region Send to Server: firstRun EquableWorldObjects
                try
                {
                    // Game on init
                    if (firstRun && modelGameServerInfo != null)
                    {
                        if (modelGameServerInfo.WObjectOnlineList.Count > 0)
                        {
                            toServ.WObjectOnlineList = allWorldObjectsArr.Where(wo => wo is Settlement)
                                                       .Where(wo => wo.HasName && !wo.Faction.IsPlayer).Select(obj => GetWorldObjects(obj)).ToList();
                        }

                        if (modelGameServerInfo.FactionOnlineList.Count > 0)
                        {
                            List <Faction> factions = Find.FactionManager.AllFactionsListForReading;
                            toServ.FactionOnlineList = factions.Select(obj => GetFactions(obj)).ToList();
                        }
                        return;
                    }
                }
                catch (Exception e)
                {
                    Loger.Log("Exception >> " + e);
                    Log.Error("SendToServer FirstRun error");
                    return;
                }
                #endregion
            }

            if (!firstRun)
            {
                //Loger.Log("Client TestBagSD 035");
                Dictionary <Map, List <Pawn> > cacheColonists = new Dictionary <Map, List <Pawn> >();
                //отправка всех новых и измененных объектов игрока
                toServ.WObjects = allWorldObjects
                                  .Where(o => o.Faction?.IsPlayer == true && //o.Faction != null && o.Faction.IsPlayer
                                         (o is Settlement || o is Caravan)) //Чтобы отсеч разные карты событий
                                  .Select(o => GetWorldObjectEntry(o, gameProgress, cacheColonists))
                                  .ToList();
                LastSendMyWorldObjects = toServ.WObjects;

                //Loger.Log("Client TestBagSD 036");
                //свои объекты которые удалил пользователь с последнего обновления
                if (ToDelete != null)
                {
                    var toDeleteNewNow = WorldObjectEntrys
                                         .Where(p => !allWorldObjects.Any(wo => wo.ID == p.Key))
                                         .Select(p => p.Value)
                                         .ToList();
                    ToDelete.AddRange(toDeleteNewNow);
                }

                toServ.WObjectsToDelete = ToDelete;
            }
            toServ.GameProgress = gameProgress;

            if (SessionClientController.Data.GeneralSettings.EquableWorldObjects)
            {
                #region Send to Server: Non-Player World Objects
                //  Non-Player World Objects
                try
                {
                    var OnlineWObjArr = allWorldObjectsArr.Where(wo => wo is Settlement)
                                        .Where(wo => wo.HasName && !wo.Faction.IsPlayer);
                    if (!firstRun)
                    {
                        if (LastWorldObjectOnline != null && LastWorldObjectOnline.Count > 0)
                        {
                            toServ.WObjectOnlineToDelete = LastWorldObjectOnline.Where(WOnline => !OnlineWObjArr.Any(wo => ValidateOnlineWorldObject(WOnline, wo))).ToList();

                            toServ.WObjectOnlineToAdd = OnlineWObjArr.Where(wo => !LastWorldObjectOnline.Any(WOnline => ValidateOnlineWorldObject(WOnline, wo)))
                                                        .Select(obj => GetWorldObjects(obj)).ToList();
                        }
                    }

                    toServ.WObjectOnlineList = OnlineWObjArr.Select(obj => GetWorldObjects(obj)).ToList();
                    LastWorldObjectOnline    = toServ.WObjectOnlineList;
                }
                catch (Exception e)
                {
                    Loger.Log("Exception >> " + e);
                    Log.Error("ERROR SendToServer WorldObject Online");
                }
                #endregion

                #region Send to Server: Non-Player Factions
                // Non-Player Factions
                try
                {
                    if (!firstRun)
                    {
                        if (LastFactionOnline != null && LastFactionOnline.Count > 0)
                        {
                            toServ.FactionOnlineToDelete = LastFactionOnline.Where(FOnline => !factionList.Any(f => ValidateFaction(FOnline, f))).ToList();

                            toServ.FactionOnlineToAdd = factionList.Where(f => !LastFactionOnline.Any(FOnline => ValidateFaction(FOnline, f)))
                                                        .Select(obj => GetFactions(obj)).ToList();
                        }
                    }

                    toServ.FactionOnlineList = factionList.Select(obj => GetFactions(obj)).ToList();
                    LastFactionOnline        = toServ.FactionOnlineList;
                }
                catch (Exception e)
                {
                    Loger.Log("Exception >> " + e);
                    Log.Error("ERROR SendToServer Faction Online");
                }
                #endregion
            }
        }