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 override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game) { var currentCountryOptional = await repo.Country.GetAliveByIdAsync(character.CountryId); if (currentCountryOptional.HasData) { await game.CharacterLogAsync("仕官は無所属でないと実行できません"); return; } var reinforcements = await repo.Reinforcement.GetByCharacterIdAsync(character.Id); var reinforcement = reinforcements.FirstOrDefault(r => r.Status == ReinforcementStatus.Active); if (reinforcement != null && (await repo.Country.GetAliveByIdAsync(reinforcement.CharacterCountryId)).HasData) { await game.CharacterLogAsync("援軍は仕官を実行できません"); return; } var blockActions = await repo.BlockAction.GetAvailableTypesAsync(character.Id); if (blockActions.Contains(BlockActionType.StopJoin) && !(await repo.System.GetAsync()).IsWaitingReset) { var blockAction = await repo.BlockAction.GetAsync(character.Id, BlockActionType.StopJoin); if (blockAction.HasData) { await game.CharacterLogAsync($"あなたは下野などの理由により仕官を制限されています。期限: {blockAction.Data.ExpiryDate:yyyy/MM/dd HH:mm:ss}"); return; } } var townOptional = await repo.Town.GetByIdAsync(character.TownId); if (!townOptional.HasData) { await game.CharacterLogAsync("ID:" + character.TownId + " の都市は存在しません。<emerge>管理者にお問い合わせください</emerge>"); return; } var town = townOptional.Data; if (town.CountryId == 0) { await game.CharacterLogAsync("<town>" + town.Name + "</town> で仕官しようとしましたが、その都市は国に支配されていません"); return; } var countryOptional = await repo.Country.GetAliveByIdAsync(town.CountryId); if (!countryOptional.HasData) { await game.CharacterLogAsync("ID:" + town.CountryId + " の国は存在しません。<emerge>管理者にお問い合わせください</emerge>"); return; } var country = countryOptional.Data; if (country.IntEstablished + Config.CountryBattleStopDuring > game.GameDateTime.ToInt()) { var characterCount = await repo.Country.CountCharactersAsync(country.Id, true); if (characterCount >= Config.CountryJoinMaxOnLimited) { await game.CharacterLogAsync("<country>" + town.Name + "</country> に仕官しようとしましたが、すでに仕官数上限に達しています"); return; } } if (country.AiType != CountryAiType.Human && character.AiType == CharacterAiType.Human) { var items = await repo.Character.GetItemsAsync(character.Id); var itemInfo = items.GetInfos().FirstOrDefault(i => i.UsingEffects != null && i.UsingEffects.Any(u => u.Type == CharacterItemEffectType.JoinableAiCountry && u.Value == (int)country.AiType)); if (itemInfo != null) { var item = items.FirstOrDefault(i => i.Type == itemInfo.Type); await ItemService.SpendCharacterAsync(repo, item, character); await game.CharacterLogAsync($"対象国はAIの統治する特別な国のため、仕官のさいにアイテム {itemInfo.Name} を使用しました"); } else { await game.CharacterLogAsync($"<country>{country.Name}</country> に仕官しようとしましたが、AIの統治する特別な国のため人間は仕官できません"); return; } } await CharacterService.ChangeCountryAsync(repo, country.Id, new Character[] { character, }); await game.CharacterLogAsync("<country>" + country.Name + "</country> に仕官しました"); await game.MapLogAsync(EventType.CharacterJoin, "<character>" + character.Name + "</character> は <country>" + country.Name + "</country> に仕官しました", false); var townCharas = await repo.Town.GetCharactersAsync(town.Id); await StatusStreaming.Default.SendCharacterAsync(ApiData.From(town), townCharas.Select(tc => tc.Id)); await StatusStreaming.Default.SendCharacterAsync(ApiData.From(country), character.Id); }
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 override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game) { var currentCountryOptional = await repo.Country.GetAliveByIdAsync(character.CountryId); if (!currentCountryOptional.HasData) { await game.CharacterLogAsync("下野は無所属は実行できません"); return; } var country = currentCountryOptional.Data; var reinforcements = await repo.Reinforcement.GetByCharacterIdAsync(character.Id); var reinforcement = reinforcements.FirstOrDefault(r => r.Status == ReinforcementStatus.Active); if (reinforcement != null && (await repo.Country.GetAliveByIdAsync(reinforcement.CharacterCountryId)).HasData) { await game.CharacterLogAsync("援軍は下野を実行できません"); return; } var townOptional = await repo.Town.GetByIdAsync(character.TownId); if (!townOptional.HasData) { await game.CharacterLogAsync("ID:" + character.TownId + " の都市は存在しません。<emerge>管理者にお問い合わせください</emerge>"); return; } var town = townOptional.Data; BlockAction blockAction = null; if (!(await repo.System.GetAsync()).IsWaitingReset) { character.ResignCount++; blockAction = new BlockAction { CharacterId = character.Id, Type = BlockActionType.StopJoin, ExpiryDate = DateTime.Now.AddDays(character.ResignCount), }; await repo.BlockAction.AddAsync(blockAction); } await CharacterService.ChangeCountryAsync(repo, 0, new Character[] { character, }); if (blockAction != null) { await game.CharacterLogAsync($"<country>{country.Name}</country> から下野しました。下野回数は <num>{character.ResignCount}</num> 回目です。仕官は以下の日時以降に行えます: {blockAction.ExpiryDate:yyyy/MM/dd HH:mm:ss}"); } else { await game.CharacterLogAsync("<country>" + country.Name + "</country> から下野しました"); } await game.MapLogAsync(EventType.CharacterResign, "<character>" + character.Name + "</character> は <country>" + country.Name + "</country> から下野しました", false); var townCharas = await repo.Town.GetCharactersAsync(town.Id); await StatusStreaming.Default.SendCharacterAsync(ApiData.From(town), townCharas.Select(tc => tc.Id)); await StatusStreaming.Default.SendCharacterAsync(ApiData.From(country), character.Id); }