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); }); } }
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); } }
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); } }
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); } }
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); } }
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); } }