Пример #1
0
        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);
        }
Пример #2
0
        public static async Task RemoveAsync(MainRepository repo, Character character)
        {
            var unitData = await repo.Unit.GetByMemberIdAsync(character.Id);

            if (unitData.Unit.HasData && unitData.Member.HasData)
            {
                if (unitData.Member.Data.Post == UnitMemberPostType.Leader)
                {
                    await UnitService.RemoveAsync(repo, unitData.Unit.Data.Id);
                }
                else
                {
                    UnitService.Leave(repo, character.Id);
                }
            }

            var countryPosts = (await repo.Country.GetCharacterPostsAsync(character.Id)).ToArray();

            if (countryPosts.Any())
            {
                foreach (var post in countryPosts)
                {
                    repo.Country.RemoveCharacterPost(post);
                }
            }

            var items = await repo.Character.GetItemsAsync(character.Id);

            foreach (var item in items)
            {
                var flag = false;

                var info = item.GetInfo();
                if (info.HasData)
                {
                    if (info.Data.IsUniqueCharacter)
                    {
                        // 一部のアイテムは放置削除と同時に消える
                        await ItemService.SpendCharacterAsync(repo, item, character, isWithEffect : false);

                        flag = true;
                    }
                }

                if (!flag)
                {
                    await ItemService.ReleaseCharacterAsync(repo, item, character);
                }
            }

            // 武将に関連付けられた都市を削除
            if ((await repo.System.GetAsync()).RuleSet != GameRuleSet.SimpleBattle)
            {
                var towns = await repo.Town.GetAllAsync();

                foreach (var town in towns.Where(t => t.UniqueCharacterId == character.Id))
                {
                    var charas = await repo.Town.GetCharactersAsync(town.Id);

                    foreach (var townChara in charas)
                    {
                        await ChangeTownAsync(repo, RandomService.Next(towns.Where(t => t.UniqueCharacterId != character.Id)).Id, townChara);
                    }
                    await repo.Town.RemoveTownDefendersAsync(town.Id);

                    repo.Town.Remove(town);

                    town.Type = TownType.Removed;
                    await StatusStreaming.Default.SendAllAsync(ApiData.From(town));

                    await AnonymousStreaming.Default.SendAllAsync(ApiData.From(town));

                    await LogService.AddMapLogAsync(repo, true, EventType.TownRemoved, $"<character>{character.Name}</character> の建設した <town>{town.Name}</town> は消滅しました");

                    if (!towns.Any(t => t.CountryId == town.CountryId && t.Type != TownType.Removed))
                    {
                        var countryOptional = await repo.Country.GetAliveByIdAsync(town.CountryId);

                        if (countryOptional.HasData)
                        {
                            await CountryService.OverThrowAsync(repo, countryOptional.Data, null);
                        }
                    }
                }
            }

            var ais = await repo.Character.GetManagementByHolderCharacterIdAsync(character.Id);

            foreach (var ai in ais)
            {
                var aiChara = await repo.Character.GetByIdAsync(ai.CharacterId);

                if (aiChara.HasData && !aiChara.Data.HasRemoved)
                {
                    aiChara.Data.DeleteTurn = (short)Config.DeleteTurns;
                }
                repo.Character.RemoveManagement(ai);
            }
            if (character.AiType == CharacterAiType.FlyingColumn)
            {
                var management = await repo.Character.GetManagementByAiCharacterIdAsync(character.Id);

                if (management.HasData)
                {
                    repo.Character.RemoveManagement(management.Data);
                }
            }

            repo.ScoutedTown.RemoveCharacter(character.Id);
            repo.Town.RemoveDefender(character.Id);
            repo.EntryHost.RemoveCharacter(character.Id);
            repo.PushNotificationKey.RemoveByCharacterId(character.Id);
            repo.Mute.RemoveCharacter(character.Id);
            await repo.AuthenticationData.RemoveCharacterAsync(character.Id);

            character.PasswordHash = character.AliasId;
            character.AliasId      = "RM"; // 新規登録で4文字未満のIDは登録できない
            character.HasRemoved   = true;
        }