public static async Task SendWarAndSaveAsync(MainRepository repo, CountryWar war) { MapLog mapLog = null; await repo.CountryDiplomacies.SetWarAsync(war); if ((war.Status == CountryWarStatus.InReady && war.RequestedStopCountryId == 0) || war.Status == CountryWarStatus.Stoped) { // 戦争を周りに通知 var country1 = await repo.Country.GetAliveByIdAsync(war.RequestedCountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); var country2 = await repo.Country.GetAliveByIdAsync(war.InsistedCountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); mapLog = new MapLog { ApiGameDateTime = (await repo.System.GetAsync()).GameDateTime, Date = DateTime.Now, IsImportant = true, }; if (war.Status == CountryWarStatus.InReady) { if (war.RequestedStopCountryId == 0) { mapLog.EventType = EventType.WarInReady; if (war.Mode == CountryWarMode.Religion) { mapLog.Message = "<country>" + country1.Name + "</country> は、<date>" + war.StartGameDate.ToString() + "</date> より <country>" + country2.Name + "</country> と宗教戦争を開始します"; } else { mapLog.Message = "<country>" + country1.Name + "</country> は、<date>" + war.StartGameDate.ToString() + "</date> より <country>" + country2.Name + "</country> へ侵攻します"; } await PushNotificationService.SendCountryAsync(repo, "宣戦布告", $"{war.StartGameDate.ToString()} より {country2.Name} と戦争します", country1.Id); await PushNotificationService.SendCountryAsync(repo, "宣戦布告", $"{war.StartGameDate.ToString()} より {country1.Name} と戦争します", country2.Id); } } else if (war.Status == CountryWarStatus.Stoped) { mapLog.EventType = EventType.WarStopped; mapLog.Message = "<country>" + country1.Name + "</country> と <country>" + country2.Name + "</country> の戦争は停戦しました"; await PushNotificationService.SendCountryAsync(repo, "停戦", $"{country2.Name} との戦争は停戦しました", country1.Id); await PushNotificationService.SendCountryAsync(repo, "停戦", $"{country1.Name} との戦争は停戦しました", country2.Id); } await repo.MapLog.AddAsync(mapLog); } await repo.SaveChangesAsync(); await StatusStreaming.Default.SendAllAsync(ApiData.From(war)); if (mapLog != null) { await StatusStreaming.Default.SendAllAsync(ApiData.From(mapLog)); await AnonymousStreaming.Default.SendAllAsync(ApiData.From(mapLog)); } }
/// <summary> /// ログを追加 /// </summary> /// <param name="log">追加するログ</param> public async Task AddAsync(MapLog log) { try { await this.container.Context.MapLogs.AddAsync(log); } catch (Exception ex) { this.container.Error(ex); } }
public static async Task <MapLog> AddMapLogAsync(MainRepository repo, bool isImportant, EventType type, string message) { var system = await repo.System.GetAsync(); var log = new MapLog { ApiGameDateTime = system.GameDateTime, Date = DateTime.Now, EventType = type, IsImportant = isImportant, Message = message, }; await repo.MapLog.AddAsync(log); await repo.SaveChangesAsync(); await StatusStreaming.Default.SendAllAsync(ApiData.From(log)); await AnonymousStreaming.Default.SendAllAsync(ApiData.From(log)); return(log); }
public async Task SetCountryAllianceAsync( [FromRoute] uint targetId, [FromBody] CountryAlliance param) { CountryAlliance alliance; MapLog mapLog = null; Optional <CountryAlliance> old = default; if (param.Status != CountryAllianceStatus.Available && param.Status != CountryAllianceStatus.ChangeRequesting && param.Status != CountryAllianceStatus.Dismissed && param.Status != CountryAllianceStatus.InBreaking && param.Status != CountryAllianceStatus.Requesting && param.Status != CountryAllianceStatus.Changed && param.Status != CountryAllianceStatus.None) { ErrorCode.InvalidParameterError.Throw(); } using (var repo = MainRepository.WithReadAndWrite()) { var system = await repo.System.GetAsync(); var self = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError); var myPosts = await repo.Country.GetCharacterPostsAsync(self.Id); if (!myPosts.Any(p => p.Type.CanDiplomacy())) { ErrorCode.NotPermissionError.Throw(); } if (system.IsBattleRoyaleMode) { // 全国戦争中に同盟操作はできない ErrorCode.InvalidOperationError.Throw(); } var target = await repo.Country.GetAliveByIdAsync(targetId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); if (target.AiType != CountryAiType.Human) { // 人間の国以外に同盟を申請することはできない ErrorCode.InvalidOperationError.Throw(); } old = await repo.CountryDiplomacies.GetCountryAllianceAsync(self.CountryId, targetId); var changeTo = await repo.CountryDiplomacies.GetCountryAllianceChangingValueAsync(self.CountryId, targetId); var war = await repo.CountryDiplomacies.GetCountryWarAsync(self.CountryId, targetId); if (old.HasData && old.Data.Status != CountryAllianceStatus.Broken && old.Data.Status != CountryAllianceStatus.Dismissed && old.Data.Status != CountryAllianceStatus.None) { var o = old.Data; if ((param.Status == CountryAllianceStatus.Available || param.Status == CountryAllianceStatus.ChangeRequesting || param.Status == CountryAllianceStatus.Changed) && o.Status == CountryAllianceStatus.Requesting) { if (self.CountryId == o.RequestedCountryId) { // 自分で自分の要求を承認しようとした ErrorCode.NotPermissionError.Throw(); } } else if (param.Status == CountryAllianceStatus.InBreaking && (o.Status != CountryAllianceStatus.Available && o.Status != CountryAllianceStatus.ChangeRequesting)) { // 結んでいないのに破棄はエラー ErrorCode.NotPermissionError.Throw(); } else if ((param.Status == CountryAllianceStatus.None || param.Status == CountryAllianceStatus.Requesting) && (o.Status == CountryAllianceStatus.Available || o.Status == CountryAllianceStatus.ChangeRequesting)) { // 結んでいるものを一瞬でなかったことにするのはエラー ErrorCode.NotPermissionError.Throw(); } else if (param.Status == o.Status && param.Status == CountryAllianceStatus.Available) { // 再承認はできない ErrorCode.MeaninglessOperationError.Throw(); } else if (param.Status == CountryAllianceStatus.Changed) { if (!changeTo.HasData || o.Status != CountryAllianceStatus.ChangeRequesting) { // 変更提案していないのに承諾はできない ErrorCode.InvalidOperationError.Throw(); } else if (changeTo.Data.RequestedCountryId == self.CountryId) { // 自分の変更要求を自分で承認できない ErrorCode.InvalidOperationError.Throw(); } } if (param.Status == CountryAllianceStatus.Available || param.Status == CountryAllianceStatus.InBreaking) { param.BreakingDelay = o.BreakingDelay; param.IsPublic = o.IsPublic; param.CanMissionary = o.CanMissionary; param.Memo = o.Memo; } else if (param.Status == CountryAllianceStatus.Changed) { param.BreakingDelay = changeTo.Data.BreakingDelay; param.IsPublic = changeTo.Data.IsPublic; param.CanMissionary = changeTo.Data.CanMissionary; param.Memo = changeTo.Data.Memo; } } else { if (param.Status != CountryAllianceStatus.Requesting) { // 同盟を結んでいない場合、同盟の要求以外にできることはない ErrorCode.NotPermissionError.Throw(); } war.Some((w) => { if (w.Status == CountryWarStatus.Available || w.Status == CountryWarStatus.InReady || w.Status == CountryWarStatus.StopRequesting) { // 戦争中 ErrorCode.NotPermissionError.Throw(); } }); } alliance = new CountryAlliance { RequestedCountryId = self.CountryId, InsistedCountryId = targetId, BreakingDelay = param.BreakingDelay, IsPublic = param.IsPublic, CanMissionary = param.CanMissionary, Memo = param.Memo, Status = param.Status == CountryAllianceStatus.Changed ? CountryAllianceStatus.Available : param.Status, }; if (param.Status != CountryAllianceStatus.ChangeRequesting) { await repo.CountryDiplomacies.SetAllianceAsync(alliance); } else { alliance.ChangeTargetId = old.Data.Id; alliance.Status = CountryAllianceStatus.ChangeRequestingValue; old.Data.Status = CountryAllianceStatus.ChangeRequesting; await repo.CountryDiplomacies.SetAllianceChangingValueAsync(alliance); } // 同盟関係を周りに通知 if (alliance.IsPublic && old.HasData && alliance.Status != CountryAllianceStatus.ChangeRequestingValue) { if (old.Data.Status == CountryAllianceStatus.Requesting && alliance.Status == CountryAllianceStatus.Available) { var country1 = await repo.Country.GetByIdAsync(alliance.RequestedCountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); var country2 = await repo.Country.GetByIdAsync(alliance.InsistedCountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); mapLog = new MapLog { ApiGameDateTime = (await repo.System.GetAsync()).GameDateTime, Date = DateTime.Now, EventType = EventType.AllianceStart, IsImportant = true, Message = "<country>" + country1.Name + "</country> と <country>" + country2.Name + "</country> は、同盟を締結しました", }; await repo.MapLog.AddAsync(mapLog); } } await repo.SaveChangesAsync(); } // 同盟関係を周りに通知 if (alliance.IsPublic && alliance.Status != CountryAllianceStatus.ChangeRequestingValue) { await StatusStreaming.Default.SendAllAsync(ApiData.From(alliance)); if (mapLog != null) { await StatusStreaming.Default.SendAllAsync(ApiData.From(mapLog)); await AnonymousStreaming.Default.SendAllAsync(ApiData.From(mapLog)); } } else { await StatusStreaming.Default.SendCountryAsync(ApiData.From(alliance), alliance.RequestedCountryId); await StatusStreaming.Default.SendCountryAsync(ApiData.From(alliance), alliance.InsistedCountryId); } if (alliance.Status == CountryAllianceStatus.ChangeRequestingValue && old.HasData) { await StatusStreaming.Default.SendCountryAsync(ApiData.From(old.Data), alliance.RequestedCountryId); await StatusStreaming.Default.SendCountryAsync(ApiData.From(old.Data), alliance.InsistedCountryId); } }
public async Task SetCountryWarAsync( [FromRoute] uint targetId, [FromBody] CountryWar param) { CountryWar war; Optional <CountryAlliance> alliance; MapLog mapLog = null; if (param.Status != CountryWarStatus.InReady && param.Status != CountryWarStatus.StopRequesting && param.Status != CountryWarStatus.Stoped) { ErrorCode.InvalidParameterError.Throw(); } using (var repo = MainRepository.WithReadAndWrite()) { var system = await repo.System.GetAsync(); if (system.IsSoftStoped) { ErrorCode.SystemSoftStopedError.Throw(); } var self = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError); var myPosts = await repo.Country.GetCharacterPostsAsync(self.Id); if (!myPosts.Any(p => p.Type.CanDiplomacy())) { ErrorCode.NotPermissionError.Throw(); } if (system.IsBattleRoyaleMode) { // 全国戦争中に戦争操作はできない ErrorCode.InvalidOperationError.Throw(); } if (system.RuleSet != GameRuleSet.Religion && param.Mode == CountryWarMode.Religion) { // 宗教戦争は宗教ルールでないと布告できない ErrorCode.RuleSetError.Throw(); } var towns = await repo.Town.GetAllAsync(); var myCountry = await repo.Country.GetAliveByIdAsync(self.CountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); var target = await repo.Country.GetAliveByIdAsync(targetId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); var wars = await repo.CountryDiplomacies.GetAllWarsAsync(); var old = await repo.CountryDiplomacies.GetCountryWarAsync(self.CountryId, targetId); alliance = await repo.CountryDiplomacies.GetCountryAllianceAsync(self.CountryId, targetId); old.Some((o) => { if (o.Status == param.Status) { ErrorCode.MeaninglessOperationError.Throw(); } if ((o.Status == CountryWarStatus.Available || o.Status == CountryWarStatus.InReady) && param.Status == CountryWarStatus.InReady) { // 重複して宣戦布告はできない ErrorCode.MeaninglessOperationError.Throw(); } else if (o.Status == CountryWarStatus.StopRequesting && param.Status == CountryWarStatus.Stoped && o.RequestedStopCountryId == self.CountryId) { // 自分の停戦要求を自分で承認できない ErrorCode.NotPermissionError.Throw(); } else if (o.Status == CountryWarStatus.Stoped && param.Status == CountryWarStatus.StopRequesting) { // 一度決まった停戦を撤回できない ErrorCode.NotPermissionError.Throw(); } if (o.Status == CountryWarStatus.Stoped && param.Status == CountryWarStatus.InReady) { // 停戦後の再布告 if (param.StartGameDate.ToInt() < system.IntGameDateTime + 12 * 12 + 1 || param.StartGameDate.Year < Config.StartYear + Config.UpdateStartYear + Config.CountryBattleStopDuring / 12) { // 開戦が早すぎる ErrorCode.InvalidParameterError.Throw(); } else if (param.StartGameDate.ToInt() > system.IntGameDateTime + 12 * 24) { // 開戦が遅すぎる ErrorCode.InvalidParameterError.Throw(); } } else if (o.Status == CountryWarStatus.StopRequesting && param.Status == CountryWarStatus.InReady) { // 停戦撤回または拒否 if (o.StartGameDate.ToInt() <= system.GameDateTime.ToInt()) { // 開戦後の場合は開戦扱い param.Status = CountryWarStatus.Available; } } param.RequestedStopCountryId = o.RequestedStopCountryId; if (param.Status == CountryWarStatus.StopRequesting) { param.RequestedStopCountryId = self.CountryId; } param.RequestedCountryId = o.RequestedCountryId; param.InsistedCountryId = o.InsistedCountryId; param.StartGameDate = o.StartGameDate; param.Mode = o.Mode; }); old.None(() => { if (param.Mode == CountryWarMode.Religion) { if (myCountry.Religion == ReligionType.Any || myCountry.Religion == ReligionType.None) { // 国教を持たない国は宗教戦争を布告できない ErrorCode.InvalidOperationError.Throw(); } if (target.Religion == myCountry.Religion) { // 同じ宗教の国には宗教戦争を布告できない ErrorCode.ReligionError.Throw(); } } if (wars.Where(w => w.Status == CountryWarStatus.Available || w.Status == CountryWarStatus.InReady || w.Status == CountryWarStatus.StopRequesting) .Where(w => w.IsJoin(myCountry.Id) || w.IsJoin(target.Id)) .Any(w => w.Mode != param.Mode)) { // 就業戦争と通常戦争を両方することはできない ErrorCode.InvalidWarModeError.Throw(); } if (!towns.GetAroundCountries(towns.Where(t => t.CountryId == param.InsistedCountryId)).Contains(param.RequestedCountryId)) { // 飛び地布告 ErrorCode.InvalidOperationError.Throw(); } if (param.Status == CountryWarStatus.StopRequesting || param.Status == CountryWarStatus.Stoped) { // 存在しない戦争を停戦にはできない ErrorCode.NotPermissionError.Throw(); } else if (param.StartGameDate.ToInt() < system.IntGameDateTime + 12 * 12 + 1 || param.StartGameDate.Year < Config.StartYear + Config.UpdateStartYear + Config.CountryBattleStopDuring / 12) { // 開戦が早すぎる ErrorCode.InvalidParameterError.Throw(); } else if (param.StartGameDate.ToInt() > system.IntGameDateTime + 12 * 24) { // 開戦が遅すぎる ErrorCode.InvalidParameterError.Throw(); } }); alliance.Some((a) => { if (a.Status == CountryAllianceStatus.Available || a.Status == CountryAllianceStatus.ChangeRequesting || a.Status == CountryAllianceStatus.InBreaking) { // 同盟が有効中 ErrorCode.NotPermissionError.Throw(); } if (a.Status == CountryAllianceStatus.Requesting) { // 自動で同盟申請を却下する a.Status = CountryAllianceStatus.Broken; } }); war = new CountryWar { RequestedCountryId = param.RequestedCountryId, InsistedCountryId = param.InsistedCountryId, StartGameDate = param.StartGameDate, Status = param.Status, RequestedStopCountryId = param.RequestedStopCountryId, Mode = param.Mode, }; await CountryService.SendWarAndSaveAsync(repo, war); } if (alliance.HasData) { var a = alliance.Data; await StatusStreaming.Default.SendCountryAsync(ApiData.From(a), a.RequestedCountryId); await StatusStreaming.Default.SendCountryAsync(ApiData.From(a), a.InsistedCountryId); } }
public async Task SetPromotionStatusAsync( [FromBody] ChatMessage message) { Character newCharacter = null; CharacterLog charalog = null; CharacterLog senderCharalog = null; MapLog maplog = null; Town newTown = null; Town oldTown = null; CountryMessage commanders = null; IEnumerable <uint> oldTownCharacters = null; IEnumerable <uint> newTownCharacters = null; using (var repo = MainRepository.WithReadAndWrite()) { var system = await repo.System.GetAsync(); var chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.CharacterNotFoundError); var old = await repo.ChatMessage.GetByIdAsync(message.Id).GetOrErrorAsync(ErrorCode.InvalidParameterError); var country = await repo.Country.GetAliveByIdAsync(chara.CountryId); if (country.HasData) { // 無所属以外は実行できない ErrorCode.InvalidOperationError.Throw(); } if (old.Type != ChatMessageType.Promotion) { // 登用文ではない ErrorCode.InvalidOperationError.Throw(); } if (message.Type == ChatMessageType.PromotionAccepted) { var sender = await repo.Character.GetByIdAsync(old.TypeData).GetOrErrorAsync(ErrorCode.CharacterNotFoundError); var senderCountry = await repo.Country.GetAliveByIdAsync(old.CharacterCountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); if (senderCountry.IntEstablished + Config.CountryBattleStopDuring > system.IntGameDateTime) { var characterCount = await repo.Country.CountCharactersAsync(senderCountry.Id, true); if (characterCount >= Config.CountryJoinMaxOnLimited) { // 戦闘解除前の国に士官できない ErrorCode.CantJoinAtSuchCountryhError.Throw(); } } var blockActions = await repo.BlockAction.GetAvailableTypesAsync(chara.Id); if (blockActions.Contains(BlockActionType.StopJoin) && !system.IsWaitingReset) { ErrorCode.BlockedActionError.Throw(); } oldTown = await repo.Town.GetByIdAsync(chara.TownId).GetOrErrorAsync(ErrorCode.TownNotFoundError); newTown = await repo.Town.GetByIdAsync(senderCountry.CapitalTownId).GetOrErrorAsync(ErrorCode.TownNotFoundError); oldTownCharacters = (await repo.Town.GetCharactersWithIconAsync(oldTown.Id)).Select(c => c.Character.Id); newTownCharacters = (await repo.Town.GetCharactersWithIconAsync(newTown.Id)).Select(c => c.Character.Id); commanders = (await repo.Country.GetMessageAsync(senderCountry.Id, CountryMessageType.Commanders)).Data; var reinforcements = await repo.Reinforcement.GetByCharacterIdAsync(chara.Id); if (reinforcements.Any(r => r.Status == ReinforcementStatus.Active)) { ErrorCode.NotPermissionError.Throw(); } await CharacterService.ChangeTownAsync(repo, senderCountry.CapitalTownId, chara); await CharacterService.ChangeCountryAsync(repo, senderCountry.Id, new Character[] { chara, }); charalog = new CharacterLog { CharacterId = chara.Id, DateTime = DateTime.Now, GameDateTime = system.GameDateTime, Message = $"<character>{sender.Name}</character> の登用に応じ、 <country>{senderCountry.Name}</country> に仕官しました", }; senderCharalog = new CharacterLog { CharacterId = old.TypeData, DateTime = DateTime.Now, GameDateTime = system.GameDateTime, Message = $"<character>{chara.Name}</character> があなたの登用に応じ、 <country>{senderCountry.Name}</country> に仕官しました", }; maplog = new MapLog { Date = DateTime.Now, ApiGameDateTime = system.GameDateTime, IsImportant = false, EventType = EventType.PromotionAccepted, Message = $"<character>{chara.Name}</character> は <country>{senderCountry.Name}</country> に仕官しました", }; old.Character = new CharacterChatData(sender, null); old.ReceiverName = chara.Name; old.Type = message.Type; newCharacter = chara; } else if (message.Type == ChatMessageType.PromotionRefused) { var sender = await repo.Character.GetByIdAsync(old.TypeData).GetOrErrorAsync(ErrorCode.CharacterNotFoundError); charalog = new CharacterLog { CharacterId = chara.Id, DateTime = DateTime.Now, GameDateTime = system.GameDateTime, Message = $"<character>{sender.Name}</character> の登用を断りました", }; senderCharalog = new CharacterLog { CharacterId = old.TypeData, DateTime = DateTime.Now, GameDateTime = system.GameDateTime, Message = $"<character>{chara.Name}</character> は、あなたの登用を断りました", }; old.Character = new CharacterChatData(sender, null); old.ReceiverName = chara.Name; old.Type = message.Type; } else { ErrorCode.InvalidParameterError.Throw(); } if (maplog != null) { await repo.MapLog.AddAsync(maplog); } if (charalog != null) { await repo.Character.AddCharacterLogAsync(charalog); } if (senderCharalog != null) { await repo.Character.AddCharacterLogAsync(senderCharalog); } message = old; await repo.SaveChangesAsync(); } if (newCharacter != null) { StatusStreaming.Default.UpdateCache(new Character[] { newCharacter, }); await StatusStreaming.Default.SendCharacterAsync(ApiData.From(newCharacter), newCharacter.Id); } if (charalog != null) { await StatusStreaming.Default.SendCharacterAsync(ApiData.From(charalog), charalog.CharacterId); await StatusStreaming.Default.SendCharacterAsync(ApiData.From(message), charalog.CharacterId); } if (senderCharalog != null) { await StatusStreaming.Default.SendCharacterAsync(ApiData.From(senderCharalog), senderCharalog.CharacterId); await StatusStreaming.Default.SendCharacterAsync(ApiData.From(message), senderCharalog.CharacterId); } if (maplog != null) { await StatusStreaming.Default.SendAllAsync(ApiData.From(maplog)); await AnonymousStreaming.Default.SendAllAsync(ApiData.From(maplog)); } }
public async Task SetAsync( [FromBody] Reinforcement param) { Reinforcement reinforcement; MapLog maplog = null; Character self; using (var repo = MainRepository.WithReadAndWrite()) { var chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.CharacterNotFoundError); var countryData = await repo.Country.GetAliveByIdAsync(chara.CountryId); var system = await repo.System.GetAsync(); self = chara; if (system.IsBattleRoyaleMode && param.Status == ReinforcementStatus.Active) { // 全面戦争中は援軍にいけない ErrorCode.InvalidOperationError.Throw(); } var oldTownId = chara.TownId; if (param.Status == ReinforcementStatus.Requesting || param.Status == ReinforcementStatus.RequestCanceled) { // chara: 要求するほう var country = countryData.GetOrError(ErrorCode.CountryNotFoundError); var posts = (await repo.Country.GetPostsAsync(country.Id)).Where(p => p.CharacterId == chara.Id); var hasPermission = posts.Any(p => p.Type.CanDiplomacy()); if (!hasPermission) { ErrorCode.NotPermissionError.Throw(); } var targetCharacter = await repo.Character.GetByIdAsync(param.CharacterId).GetOrErrorAsync(ErrorCode.CharacterNotFoundError); var targetCountry = await repo.Country.GetByIdAsync(targetCharacter.CountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); var olds = await repo.Reinforcement.GetByCharacterIdAsync(targetCharacter.Id); if (country.Id == targetCountry.Id) { ErrorCode.MeaninglessOperationError.Throw(); } var alliance = await repo.CountryDiplomacies.GetCountryAllianceAsync(country.Id, targetCountry.Id).GetOrErrorAsync(ErrorCode.NotPermissionError); if (alliance.Status != CountryAllianceStatus.Available && alliance.Status != CountryAllianceStatus.ChangeRequesting) { ErrorCode.NotPermissionError.Throw(); } if (olds.Any(r => r.Status == ReinforcementStatus.Active)) { ErrorCode.InvalidOperationError.Throw(); } if (olds.Any(r => r.Status == ReinforcementStatus.Requesting && r.RequestedCountryId == chara.CountryId)) { if (param.Status == ReinforcementStatus.Requesting) { ErrorCode.MeaninglessOperationError.Throw(); } } else { if (param.Status == ReinforcementStatus.RequestCanceled) { ErrorCode.InvalidOperationError.Throw(); } } if (param.Status == ReinforcementStatus.Requesting) { reinforcement = new Reinforcement { CharacterId = targetCharacter.Id, CharacterCountryId = targetCountry.Id, RequestedCountryId = country.Id, Status = ReinforcementStatus.Requesting, }; await repo.Reinforcement.AddAsync(reinforcement); } else { reinforcement = olds.FirstOrDefault(r => r.RequestedCountryId == chara.CountryId); reinforcement.Status = ReinforcementStatus.RequestCanceled; } } else if (param.Status == ReinforcementStatus.RequestDismissed || param.Status == ReinforcementStatus.Active || param.Status == ReinforcementStatus.Returned || param.Status == ReinforcementStatus.Submited) { // chara: 要求されるほう var olds = await repo.Reinforcement.GetByCharacterIdAsync(chara.Id); var old = olds.FirstOrDefault(r => r.CharacterCountryId == chara.CountryId && r.RequestedCountryId == param.RequestedCountryId); if (old == null && param.Status != ReinforcementStatus.Returned && param.Status != ReinforcementStatus.Submited) { ErrorCode.InvalidOperationError.Throw(); } if (param.Status == ReinforcementStatus.RequestDismissed) { if (old.Status != ReinforcementStatus.Requesting) { ErrorCode.InvalidOperationError.Throw(); } } if (param.Status == ReinforcementStatus.Active) { var country = countryData.GetOrError(ErrorCode.CountryNotFoundError); var requestedCountry = await repo.Country.GetByIdAsync(param.RequestedCountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); if (old.Status != ReinforcementStatus.Requesting) { ErrorCode.InvalidOperationError.Throw(); } if (requestedCountry.HasOverthrown) { ErrorCode.InvalidOperationError.Throw(); } var alliance = await repo.CountryDiplomacies.GetCountryAllianceAsync(old.RequestedCountryId, old.CharacterCountryId).GetOrErrorAsync(ErrorCode.NotPermissionError); if (alliance.Status != CountryAllianceStatus.Available && alliance.Status != CountryAllianceStatus.ChangeRequesting) { ErrorCode.NotPermissionError.Throw(); } var post = (await repo.Country.GetPostsAsync(chara.CountryId)).Where(p => p.CharacterId == chara.Id); var isMonarch = post.Any(p => p.Type == CountryPostType.Monarch); if (isMonarch && !Config.Game.IsAllowMonarchReinforcement) { ErrorCode.NotPermissionError.Throw(); } await CharacterService.ChangeTownAsync(repo, requestedCountry.CapitalTownId, chara); await CharacterService.ChangeCountryAsync(repo, requestedCountry.Id, new Character[] { chara, }); // 君主が援軍に行く場合、君主データを残す if (isMonarch) { var monarchPost = post.First(p => p.Type == CountryPostType.Monarch); var monarch = new CountryPost { CharacterId = chara.Id, CountryId = old.CharacterCountryId, Type = CountryPostType.MonarchDisabled, }; repo.Country.RemoveCharacterPost(monarchPost); await repo.Country.AddPostAsync(monarch); await StatusStreaming.Default.SendCountryAsync(ApiData.From(monarch), old.CharacterCountryId); } maplog = new MapLog { ApiGameDateTime = system.GameDateTime, Date = DateTime.Now, EventType = EventType.ReinforcementActived, IsImportant = false, Message = $"<country>{country.Name}</country> の <character>{chara.Name}</character> は、 <country>{requestedCountry.Name}</country> へ援軍に行きました", }; } if (param.Status == ReinforcementStatus.Returned) { old = olds.FirstOrDefault(o => o.Status == ReinforcementStatus.Active); if (old == null) { ErrorCode.InvalidOperationError.Throw(); } var originalCountry = await repo.Country.GetByIdAsync(old.CharacterCountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); if (originalCountry.HasOverthrown) { ErrorCode.InvalidOperationError.Throw(); } await CharacterService.ChangeTownAsync(repo, originalCountry.CapitalTownId, chara); await CharacterService.ChangeCountryAsync(repo, originalCountry.Id, new Character[] { chara, }); // 援軍に行ったのが君主の場合、復活する var post = await repo.Country.GetCharacterPostsAsync(chara.Id); if (post.Any(p => p.Type == CountryPostType.MonarchDisabled)) { repo.Country.RemoveCharacterPosts(chara.Id); var monarch = new CountryPost { CharacterId = chara.Id, CountryId = old.CharacterCountryId, Type = CountryPostType.Monarch, }; await repo.Country.AddPostAsync(monarch); await StatusStreaming.Default.SendCountryAsync(ApiData.From(monarch), old.CharacterCountryId); } var countryName = countryData.Data?.Name ?? "無所属"; maplog = new MapLog { ApiGameDateTime = system.GameDateTime, Date = DateTime.Now, EventType = EventType.ReinforcementReturned, IsImportant = false, Message = $"<country>{originalCountry.Name}</country> の援軍 <character>{chara.Name}</character> は、 <country>{countryName}</country> から帰還しました", }; } if (param.Status == ReinforcementStatus.Submited) { var country = countryData.GetOrError(ErrorCode.CountryNotFoundError); old = olds.FirstOrDefault(o => o.Status == ReinforcementStatus.Active); if (old == null) { ErrorCode.InvalidOperationError.Throw(); } var originalCountry = await repo.Country.GetByIdAsync(old.CharacterCountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); if (!originalCountry.HasOverthrown) { ErrorCode.InvalidOperationError.Throw(); } maplog = new MapLog { ApiGameDateTime = system.GameDateTime, Date = DateTime.Now, EventType = EventType.ReinforcementSubmited, IsImportant = false, Message = $"<country>{originalCountry.Name}</country> の援軍 <character>{chara.Name}</character> は、 <country>{country.Name}</country> に帰順しました", }; } reinforcement = old; reinforcement.Status = param.Status; } else { ErrorCode.InvalidParameterError.Throw(); reinforcement = null; } if (maplog != null) { await repo.MapLog.AddAsync(maplog); } await repo.SaveChangesAsync(); } // マップログ、援軍情報を通知 await StatusStreaming.Default.SendCountryAsync(ApiData.From(reinforcement), new uint[] { reinforcement.CharacterCountryId, reinforcement.RequestedCountryId, }); if (maplog != null) { await StatusStreaming.Default.SendAllAsync(ApiData.From(maplog)); await AnonymousStreaming.Default.SendAllAsync(ApiData.From(maplog)); } await StatusStreaming.Default.SendCharacterAsync(ApiData.From(self), self.Id); }
public MapLoggingEventArgs(MapLog log) { this.Log = log; }
internal void RaiseLog(MapLog log) { // using this inline vs checking for null is more thread safe OnLog?.Invoke(this, new MapLoggingEventArgs(log)); }
public static async Task EntryAsync(MainRepository repo, string ipAddress, Character newChara, CharacterIcon newIcon, string password, Country newCountry, string invitationCode, bool isFreeCountry) { var town = await repo.Town.GetByIdAsync(newChara.TownId).GetOrErrorAsync(ErrorCode.TownNotFoundError); var system = await repo.System.GetAsync(); CheckEntryStatus(system.GameDateTime, ipAddress, newChara, password, newIcon, town, newCountry, isFreeCountry); // 文字数チェックしてからエスケープ newChara.Name = HtmlUtil.Escape(newChara.Name); newCountry.Name = HtmlUtil.Escape(newCountry.Name); newChara.Message = HtmlUtil.Escape(newChara.Message); // 既存との重複チェック if (await repo.Character.IsAlreadyExistsAsync(newChara.Name, newChara.AliasId)) { ErrorCode.DuplicateCharacterNameOrAliasIdError.Throw(); } if ((system.IsDebug && (await repo.System.GetDebugDataAsync()).IsCheckDuplicateEntry || !system.IsDebug) && await repo.EntryHost.ExistsAsync(ipAddress)) { ErrorCode.DuplicateEntryError.Throw(); } // 招待コードチェック Optional <InvitationCode> invitationCodeOptional = default; if (system.InvitationCodeRequestedAtEntry) { invitationCodeOptional = await repo.InvitationCode.GetByCodeAsync(invitationCode); if (!invitationCodeOptional.HasData || invitationCodeOptional.Data.HasUsed || invitationCodeOptional.Data.Aim != InvitationCodeAim.Entry) { ErrorCode.InvitationCodeRequestedError.Throw(); } } var updateCountriesRequested = false; MapLog maplog = null; var chara = new Character { Name = newChara.Name, AliasId = newChara.AliasId, Strong = newChara.Strong, StrongEx = 0, Intellect = newChara.Intellect, IntellectEx = 0, Leadership = newChara.Leadership, LeadershipEx = 0, Popularity = newChara.Popularity, PopularityEx = 0, Contribution = 0, Class = 0, DeleteTurn = (short)(Config.DeleteTurns - 10), LastUpdated = DateTime.Now, LastUpdatedGameDate = system.GameDateTime, Message = newChara.Message, Money = 10_0000 + Math.Max(system.GameDateTime.ToInt() - (Config.StartYear + Config.UpdateStartYear + 4) * 12 - Config.StartMonth, 0) * 800, Rice = 5_0000 + Math.Max(system.GameDateTime.ToInt() - (Config.StartYear + Config.UpdateStartYear + 4) * 12 - Config.StartMonth, 0) * 400, SkillPoint = Math.Max(0, (int)((system.IntGameDateTime - Config.UpdateStartYear * 12) * 0.8f)), SoldierType = SoldierType.Common, SoldierNumber = 0, Proficiency = 0, TownId = newChara.TownId, From = newChara.From, Religion = ReligionType.Any, FormationType = newChara.FormationType, IsBeginner = newChara.IsBeginner, }; chara.SetPassword(password); // 出身 var skills = new List <CharacterSkillType>(); var items = new List <CharacterItemType>(); if (chara.From == CharacterFrom.Warrior) { skills.Add(CharacterSkillType.Strong1); chara.Strong += 20; } else if (chara.From == CharacterFrom.Civilian) { skills.Add(CharacterSkillType.Intellect1); chara.Intellect += 20; } else if (chara.From == CharacterFrom.Merchant) { skills.Add(CharacterSkillType.Merchant1); chara.Money += 200000; } else if (chara.From == CharacterFrom.Engineer) { skills.Add(CharacterSkillType.Engineer1); chara.Strong += 10; chara.Money += 100000; } else if (chara.From == CharacterFrom.Terrorist) { skills.Add(CharacterSkillType.Terrorist1); chara.Strong += 15; chara.Leadership += 5; } else if (chara.From == CharacterFrom.People) { skills.Add(CharacterSkillType.People1); chara.Popularity += 20; } else if (chara.From == CharacterFrom.Tactician) { skills.Add(CharacterSkillType.Tactician1); chara.Strong += 5; chara.Leadership += 15; } else if (chara.From == CharacterFrom.Scholar) { skills.Add(CharacterSkillType.Scholar1); chara.Intellect += 20; } else if (chara.From == CharacterFrom.Staff) { skills.Add(CharacterSkillType.Staff1); chara.Intellect += 20; } else if (chara.From == CharacterFrom.Buddhism) { if (system.RuleSet == GameRuleSet.SimpleBattle) { ErrorCode.RuleSetError.Throw(); } skills.Add(CharacterSkillType.Buddhism1); chara.Intellect += 15; chara.Religion = ReligionType.Buddhism; } else if (chara.From == CharacterFrom.Confucianism) { if (system.RuleSet == GameRuleSet.SimpleBattle) { ErrorCode.RuleSetError.Throw(); } skills.Add(CharacterSkillType.Confucianism1); chara.Intellect += 15; chara.Religion = ReligionType.Confucianism; } else if (chara.From == CharacterFrom.Taoism) { if (system.RuleSet == GameRuleSet.SimpleBattle) { ErrorCode.RuleSetError.Throw(); } skills.Add(CharacterSkillType.Taoism1); chara.Intellect += 15; chara.Religion = ReligionType.Taoism; } else { ErrorCode.InvalidParameterError.Throw(); } // 来月の更新がまだ終わってないタイミングで登録したときの、武将更新時刻の調整 if (chara.LastUpdated - system.CurrentMonthStartDateTime > TimeSpan.FromSeconds(Config.UpdateTime)) { chara.IntLastUpdatedGameDate++; } if (isFreeCountry) { // 無所属で開始 chara.CountryId = 0; await repo.Character.AddAsync(chara); maplog = new MapLog { Date = DateTime.Now, ApiGameDateTime = system.GameDateTime, EventType = EventType.CharacterEntryToFree, IsImportant = false, Message = $"<character>{chara.Name}</character> が無所属に出現しました", }; await repo.MapLog.AddAsync(maplog); } else if (town.CountryId > 0) { // 武将総数チェック var country = await repo.Country.GetByIdAsync(town.CountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); if (country.IntEstablished + Config.CountryBattleStopDuring > system.GameDateTime.ToInt()) { var countryCharaCount = await repo.Country.CountCharactersAsync(country.Id, true); if (countryCharaCount >= Config.CountryJoinMaxOnLimited) { ErrorCode.CantJoinAtSuchCountryhError.Throw(); } else if (countryCharaCount + 1 == Config.CountryJoinMaxOnLimited) { updateCountriesRequested = true; } } // AI国家チェック if (country.AiType != CountryAiType.Human) { ErrorCode.CantJoinAtSuchCountryhError.Throw(); } // 金と米を仕官先国の武将の平均にあわせる if (system.GameDateTime.Year >= Config.UpdateStartYear + Config.CountryBattleStopDuring / 12) { var countryCharacters = (await repo.Country.GetCharactersAsync(town.CountryId)).Where(c => c.AiType == CharacterAiType.Human || c.AiType == CharacterAiType.Administrator); if (countryCharacters.Any()) { chara.Money = Math.Min((int)countryCharacters.Average(c => c.Money) + 10_0000, chara.Money); chara.Rice = Math.Min((int)countryCharacters.Average(c => c.Rice) + 5_0000, chara.Rice); } } chara.CountryId = town.CountryId; await repo.Character.AddAsync(chara); maplog = new MapLog { Date = DateTime.Now, ApiGameDateTime = system.GameDateTime, EventType = EventType.CharacterEntry, IsImportant = false, Message = $"<character>{chara.Name}</character> が <country>{country.Name}</country> に仕官しました", }; await repo.MapLog.AddAsync(maplog); } else { // 重複チェック if ((await repo.Country.GetAllAsync()).Any(c => c.Name == newCountry.Name || c.CountryColorId == newCountry.CountryColorId)) { ErrorCode.DuplicateCountryNameOrColorError.Throw(); } if (system.RuleSet == GameRuleSet.SimpleBattle) { newCountry.Civilization = CountryCivilization.None; } var country = new Country { Name = newCountry.Name, CountryColorId = newCountry.CountryColorId, CapitalTownId = newChara.TownId, IntEstablished = Math.Max(system.GameDateTime.ToInt(), new GameDateTime { Year = Config.UpdateStartYear, Month = 1, }.ToInt()), HasOverthrown = false, IntOverthrownGameDate = 0, LastMoneyIncomes = 0, LastRiceIncomes = 0, PolicyPoint = 10000, Religion = RandomService.Next(new ReligionType[] { ReligionType.Buddhism, ReligionType.Confucianism, ReligionType.Taoism, }), Civilization = newCountry.Civilization, }; updateCountriesRequested = true; await repo.Country.AddAsync(country); var countries = await repo.Country.GetAllAsync(); var point = 500; if (system.RuleSet != GameRuleSet.Wandering) { // 大都市に変更 town.SubType = town.Type; MapService.UpdateTownType(town, TownType.Large); // 首都の宗教 if (system.RuleSet != GameRuleSet.SimpleBattle) { if (country.Religion == ReligionType.Buddhism) { town.Buddhism += point; town.Confucianism = Math.Min(town.Confucianism, 999); town.Taoism = Math.Min(town.Taoism, 999); } if (country.Religion == ReligionType.Confucianism) { town.Confucianism += point; town.Buddhism = Math.Min(town.Buddhism, 999); town.Taoism = Math.Min(town.Taoism, 999); } if (country.Religion == ReligionType.Taoism) { town.Taoism += point; town.Buddhism = Math.Min(town.Buddhism, 999); town.Confucianism = Math.Min(town.Confucianism, 999); } } } else { country.CapitalTownId = 0; items.Add(CharacterItemType.CastleBlueprint); items.Add(CharacterItemType.CastleBlueprint); items.Add(CharacterItemType.CastleBlueprint); chara.Money += 50_0000 * 3; } await repo.SaveChangesAsync(); chara.CountryId = country.Id; if (system.RuleSet != GameRuleSet.Wandering) { town.CountryId = country.Id; } await repo.Character.AddAsync(chara); await repo.SaveChangesAsync(); var countryPost = new CountryPost { Type = CountryPostType.Monarch, CountryId = country.Id, CharacterId = chara.Id, }; await repo.Country.AddPostAsync(countryPost); if (system.RuleSet == GameRuleSet.Wandering) { maplog = new MapLog { Date = DateTime.Now, ApiGameDateTime = system.GameDateTime, EventType = EventType.StartWandering, IsImportant = true, Message = $"<character>{chara.Name}</character> は <country>{country.Name}</country> の頭領となり放浪を開始しました", }; } else { maplog = new MapLog { Date = DateTime.Now, ApiGameDateTime = system.GameDateTime, EventType = EventType.Publish, IsImportant = true, Message = $"<character>{chara.Name}</character> が <town>{town.Name}</town> に <country>{country.Name}</country> を建国しました", }; } await repo.MapLog.AddAsync(maplog); } await repo.SaveChangesAsync(); // 陣形 var formation = new Formation { CharacterId = chara.Id, Type = chara.FormationType, Level = 1, }; await repo.Character.AddFormationAsync(formation); if (invitationCodeOptional.HasData) { var code = invitationCodeOptional.Data; code.HasUsed = true; code.Used = DateTime.Now; code.CharacterId = chara.Id; } var icon = new CharacterIcon { Type = newIcon.Type, IsAvailable = true, IsMain = true, FileName = newIcon.FileName, CharacterId = chara.Id, }; await repo.Character.AddCharacterIconAsync(icon); var host = new EntryHost { CharacterId = chara.Id, IpAddress = ipAddress, }; await repo.EntryHost.AddAsync(host); var skillItems = skills.Select(s => new CharacterSkill { CharacterId = chara.Id, Type = s, Status = CharacterSkillStatus.Available, }); foreach (var si in skillItems) { await SkillService.SetCharacterAndSaveAsync(repo, si, chara); } var itemData = items.Select(i => new CharacterItem { Type = i, CharacterId = chara.Id, Status = CharacterItemStatus.CharacterHold, }); foreach (var id in itemData) { await ItemService.GenerateItemAndSaveAsync(repo, id); } await repo.SaveChangesAsync(); if (updateCountriesRequested) { var countries = await repo.Country.GetAllForAnonymousAsync(); await AnonymousStreaming.Default.SendAllAsync(countries.Select(c => ApiData.From(c))); await StatusStreaming.Default.SendAllAsync(countries.Select(c => ApiData.From(c))); } var townData = ApiData.From(new TownForAnonymous(town)); var maplogData = ApiData.From(maplog); await AnonymousStreaming.Default.SendAllAsync(maplogData); await StatusStreaming.Default.SendAllAsync(maplogData); await AnonymousStreaming.Default.SendAllAsync(townData); await StatusStreaming.Default.SendAllAsync(townData); await StatusStreaming.Default.SendCountryAsync(ApiData.From(town), town.CountryId); await CharacterService.StreamCharacterAsync(repo, chara); }