public static void SendToServer(ModelPlayToServer toServ) { toServ.LastTick = (long)Find.TickManager.TicksGame; //отправка всех новых и измененных объектов игрока toServ.WObjects = Find.WorldObjects.AllWorldObjects .Where(o => o.Faction != null && o.Faction.IsPlayer && !(o is CaravanOnline) && !(o is BaseOnline)) .Select(o => GetWorldObjectEntry(o)) .ToList(); //свои объекты которые удалил пользователь с последнего обновления if (ToDelete != null) { var toDeleteNewNow = MyWorldObjectEntry .Where(p => !Find.WorldObjects.AllWorldObjects.Any(wo => wo.ID == p.Key)) .Select(p => p.Value) .ToList(); ToDelete.AddRange(toDeleteNewNow); } toServ.WObjectsToDelete = ToDelete; }
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 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 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 } }
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); } }