/// <summary> /// ホストを追加する /// </summary> /// <param name="host">新しいホストデータ</param> public async Task AddAsync(EntryHost host) { try { await this.container.Context.EntryHosts.AddAsync(host); } catch (Exception ex) { this.container.Error(ex); } }
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); }