コード例 #1
0
 public AiExcuteAllController(IOptions <JwtIssuerOptions> jwtOptions, IOptions <AppSettings> appSettings)
 {
     _appSettings        = appSettings;
     _jwtOptions         = jwtOptions.Value;
     _serializerSettings = new JsonSerializerSettings
     {
         Formatting = Formatting.Indented
     };
     _aiService = new AiService(appSettings.Value);
 }
コード例 #2
0
        private static void RunServer()
        {
            Data.Data.DataPath = "data/";

            Stopwatch sw = Stopwatch.StartNew();

            AppDomain.CurrentDomain.UnhandledException += UnhandledException;

            Console.WriteLine("----===== Tera-Project C# GameServer Emulator =====----\n\n");
            Console.WriteLine("Starting Game Server!\n"
                              + "-------------------------------------------");

            TcpServer = new TcpServer("*", Config.GetServerPort(), Config.GetServerMaxCon());
            Connection.SendAllThread.Start();

            OpCodes.Init();
            Console.WriteLine("OpCodes - Revision 1725 initialized!\n"
                              + "-------------------------------------------\n");

            #region global_components

            //services
            FeedbackService    = new FeedbackService();
            AccountService     = new AccountService();
            PlayerService      = new PlayerService();
            MapService         = new MapService();
            ChatService        = new ChatService();
            VisibleService     = new VisibleService();
            ControllerService  = new ControllerService();
            CraftService       = new CraftService();
            ItemService        = new ItemService();
            AiService          = new AiService();
            GeoService         = new GeoService();
            StatsService       = new StatsService();
            ObserverService    = new ObserverService();
            AreaService        = new AreaService();
            InformerService    = new InformerService();
            TeleportService    = new TeleportService();
            PartyService       = new PartyService();
            SkillsLearnService = new SkillsLearnService();
            CraftLearnService  = new CraftLearnService();
            GuildService       = new GuildService();
            EmotionService     = new EmotionService();
            RelationService    = new RelationService();
            DuelService        = new DuelService();
            StorageService     = new StorageService();
            TradeService       = new TradeService();
            MountService       = new MountService();

            //engines
            ActionEngine = new ActionEngine.ActionEngine();
            AdminEngine  = new AdminEngine.AdminEngine();
            SkillEngine  = new SkillEngine.SkillEngine();
            QuestEngine  = new QuestEngine.QuestEngine();

            #endregion

            GlobalLogic.ServerStart("SERVER=" + Config.GetDatabaseHost() + ";DATABASE=" + Config.GetDatabaseName() + ";UID=" + Config.GetDatabaseUser() + ";PASSWORD="******";PORT=" + Config.GetDatabasePort() + ";charset=utf8");

            Console.WriteLine("-------------------------------------------\n"
                              + "Loading Tcp Service.\n"
                              + "-------------------------------------------");
            TcpServer.BeginListening();

            try
            {
                ServiceApplication = ScsServiceBuilder.CreateService(new ScsTcpEndPoint(23232));
                ServiceApplication.AddService <IInformerService, InformerService>((InformerService)InformerService);
                ServiceApplication.Start();
                Log.Info("InformerService started at *:23232.");

                var webservices = new ServiceManager();
                webservices.Run();
            }
            catch (Exception ex)
            {
                Log.ErrorException("InformerService can not be started.", ex);
            }

            sw.Stop();
            Console.WriteLine("-------------------------------------------");
            Console.WriteLine("           Server start in {0}", (sw.ElapsedMilliseconds / 1000.0).ToString("0.00s"));
            Console.WriteLine("-------------------------------------------");
        }
コード例 #3
0
ファイル: AiController.cs プロジェクト: Bubbhas/Examensarbete
 public AiController(AiService aiService)
 {
     _aiService = aiService;
 }
コード例 #4
0
ファイル: GameServer.cs プロジェクト: uvbs/TeraEmulator_1725
        private static void RunServer()
        {
            //Start ServerStartTime
            Stopwatch serverStartStopwatch = Stopwatch.StartNew();

            AppDomain.CurrentDomain.UnhandledException += UnhandledException;

            //CheckServerMode
            CheckServerMode();

            //ConsoleOutput-Infos
            PrintServerLicence();
            PrintServerInfo();

            //Initialize TcpServer
            TcpServer = new TcpServer("*", Configuration.Network.GetServerPort(), Configuration.Network.GetServerMaxCon());
            Connection.SendAllThread.Start();

            //Initialize Server OpCodes
            OpCodes.Init();
            Console.WriteLine("----------------------------------------------------------------------------\n"
                              + "---===== OpCodes - Revision: " + OpCodes.Version + " EU initialized!");

            //Global Services
            #region global_components
            //Services
            FeedbackService    = new FeedbackService();
            AccountService     = new AccountService();
            PlayerService      = new PlayerService();
            MapService         = new MapService();
            ChatService        = new ChatService();
            VisibleService     = new VisibleService();
            ControllerService  = new ControllerService();
            CraftService       = new CraftService();
            ItemService        = new ItemService();
            AiService          = new AiService();
            GeoService         = new GeoService();
            StatsService       = new StatsService();
            ObserverService    = new ObserverService();
            AreaService        = new AreaService();
            TeleportService    = new TeleportService();
            PartyService       = new PartyService();
            SkillsLearnService = new SkillsLearnService();
            CraftLearnService  = new CraftLearnService();
            GuildService       = new GuildService();
            EmotionService     = new EmotionService();
            RelationService    = new RelationService();
            DuelService        = new DuelService();
            StorageService     = new StorageService();
            TradeService       = new TradeService();
            MountService       = new MountService();

            //Engines
            ActionEngine = new ActionEngine.ActionEngine();
            AdminEngine  = new AdminEngine.AdminEngine();
            SkillEngine  = new SkillEngine.SkillEngine();
            QuestEngine  = new QuestEngine.QuestEngine();
            #endregion

            //Set SqlDatabase Connection
            GlobalLogic.ServerStart("SERVER=" + DAOManager.MySql_Host + ";DATABASE=" + DAOManager.MySql_Database + ";UID=" + DAOManager.MySql_User + ";PASSWORD="******";PORT=" + DAOManager.MySql_Port + ";charset=utf8");
            Console.ForegroundColor = ConsoleColor.Gray;

            //Start Tcp-Server Listening
            Console.WriteLine("----------------------------------------------------------------------------\n"
                              + "---===== Loading GameServer Service.\n"
                              + "----------------------------------------------------------------------------");
            TcpServer.BeginListening();

            //Stop ServerStartTime
            serverStartStopwatch.Stop();
            Console.WriteLine("----------------------------------------------------------------------------");
            Console.WriteLine("---===== GameServer start in {0}", (serverStartStopwatch.ElapsedMilliseconds / 1000.0).ToString("0.00s"));
            Console.WriteLine("----------------------------------------------------------------------------");
        }
コード例 #5
0
 public static void InitAi(Creature creature)
 {
     creature.Ai = AiService.CreateAi(creature);
     creature.Ai.Init(creature);
 }
コード例 #6
0
        private static void RunServer()
        {
            Stopwatch sw = Stopwatch.StartNew();

            AppDomain.CurrentDomain.UnhandledException += UnhandledException;

            Console.WriteLine("----===== Revolution WorldServer =====----\n\n"
                              + "Copyright (C) 2013 Revolution Team\n\n"
                              + "This program is CLOSE SOURCE project.\n"
                              + "You DON'T have any right's, if you are NOT autor\n"
                              + "or authorized representative of him.\n"
                              + "Using that program without any right's is ILLEGAL\n\n"
                              + "Authors: Jenose, IMaster\n"
                              + "Authorized representative: netgame.in.th\n\n"
                              + "-------------------------------------------");

            Log.Info("Init Services...");
            AccountService     = new AccountService();
            AiService          = new AiService();
            ChatService        = new ChatService();
            ControllerService  = new ControllerService();
            FeedbackService    = new FeedbackService();
            MapService         = new MapService();
            ObserverService    = new ObserverService();
            PlayerService      = new PlayerService();
            TeamService        = new TeamService();
            SkillsLearnService = new SkillsLearnService();
            StatsService       = new StatsService();
            ShopService        = new ShopService();
            StorageService     = new StorageService();
            TeleportService    = new TeleportService();
            VisibleService     = new VisibleService();

            Log.Info("Init Engines...");
            ScriptEngine = new ScriptEngine.ScriptEngine();
            AdminEngine  = new AdminEngine.AdminEngine();
            SkillEngine  = new SkillEngine.SkillEngine();
            QuestEngine  = new QuestEngine.QuestEngine();
            Console.WriteLine("\n-------------------------------------------\n");

            GlobalLogic.ServerStart();
            Console.WriteLine("\n-------------------------------------------\n");

            CountryCode = (CountryCode)Enum.Parse(typeof(CountryCode), Settings.Default.COUNTRY_CODE);

            InnerNetworkOpcode.Init();
            OuterNetworkOpcode.Init();

            InnerClient = new InnerNetworkClient("127.0.0.1", 22323);
            InnerClient.BeginConnect();

            foreach (var channel in DataBaseServer.GetServerChannel(Settings.Default.SERVER_ID))
            {
                var OuterNetwork = new OuterNetworkListener("*", channel.port, channel.max_user);
                OuterNetwork.BeginListening();
                OuterNetworks.Add(OuterNetwork);
            }

            InnerNetworkClient.SendAllThread.Start();
            OuterNetworkConnection.SendAllThread.Start();

            sw.Stop();
            Console.WriteLine("-------------------------------------------");
            Console.WriteLine("           Server start in {0}", (sw.ElapsedMilliseconds / 1000.0).ToString("0.00s"));
            Console.WriteLine("-------------------------------------------");
        }
コード例 #7
0
        private static void RunServer()
        {
            Data.Data.DataPath = "data/";

            Stopwatch sw = Stopwatch.StartNew();

            AppDomain.CurrentDomain.UnhandledException += UnhandledException;

            Console.WriteLine("----===== GameServer =====----\n\n"
                              + "Starting game server\n\n"
                              + "Loading data files.\n"
                              + "-------------------------------------------");

            TcpServer = new TcpServer("*", 11101, 1000);
            Connection.SendAllThread.Start();

            OpCodes.Init();

            #region global_components

            //services
            FeedbackService    = new FeedbackService();
            AccountService     = new AccountService();
            PlayerService      = new PlayerService();
            MapService         = new MapService();
            ChatService        = new ChatService();
            VisibleService     = new VisibleService();
            ControllerService  = new ControllerService();
            CraftService       = new CraftService();
            ItemService        = new ItemService();
            AiService          = new AiService();
            GeoService         = new GeoService();
            StatsService       = new StatsService();
            ObserverService    = new ObserverService();
            AreaService        = new AreaService();
            InformerService    = new InformerService();
            TeleportService    = new TeleportService();
            PartyService       = new PartyService();
            SkillsLearnService = new SkillsLearnService();
            CraftLearnService  = new CraftLearnService();
            GuildService       = new GuildService();
            EmotionService     = new EmotionService();
            RelationService    = new RelationService();
            DuelService        = new DuelService();
            StorageService     = new StorageService();
            TradeService       = new TradeService();
            MountService       = new MountService();

            //engines
            ActionEngine = new ActionEngine.ActionEngine();
            AdminEngine  = new AdminEngine.AdminEngine();
            SkillEngine  = new SkillEngine.SkillEngine();
            QuestEngine  = new QuestEngine.QuestEngine();

            #endregion

            GlobalLogic.ServerStart();

            TcpServer.BeginListening();

            try
            {
                ServiceApplication = ScsServiceBuilder.CreateService(new ScsTcpEndPoint(23232));
                ServiceApplication.AddService <IInformerService, InformerService>((InformerService)InformerService);
                ServiceApplication.Start();
                Log.Info("InformerService started at *:23232.");
            }
            catch (Exception ex)
            {
                Log.ErrorException("InformerService can not be started.", ex);
            }

            sw.Stop();
            Console.WriteLine("-------------------------------------------");
            Console.WriteLine("           Server start in {0}", (sw.ElapsedMilliseconds / 1000.0).ToString("0.00s"));
            Console.WriteLine("-------------------------------------------");
        }
コード例 #8
0
        protected override async Task RunInnerAsync(MainRepository repo)
        {
            await AiService.CheckManagedReinforcementsAsync(repo, this.Country.Id);

            await repo.SaveChangesAsync();

            var system = await repo.System.GetAsync();

            this.allTowns = await repo.Town.GetAllAsync();

            var towns = this.allTowns.Where(t => t.CountryId == this.Country.Id);

            this.allCharacters = await repo.Character.GetAllAliveAsync();

            var characters = this.allCharacters.Where(c => c.CountryId == this.Country.Id);
            var policies   = await repo.Country.GetPoliciesAsync(this.Country.Id);

            var allWars = await repo.CountryDiplomacies.GetAllWarsAsync();

            var wars = allWars
                       .Where(w => w.InsistedCountryId == this.Country.Id || w.RequestedCountryId == this.Country.Id)
                       .Where(w => w.Status == CountryWarStatus.InReady || w.Status == CountryWarStatus.Available || w.Status == CountryWarStatus.StopRequesting);

            var charaCount = characters.Count(c => c.AiType.IsManaged());

            this.Management.CharacterSize = charaCount <= Config.CountryJoinMaxOnLimited / 2 + 1 ? AiCountryCharacterSize.Small :
                                            charaCount <= Config.CountryJoinMaxOnLimited ? AiCountryCharacterSize.Medium : AiCountryCharacterSize.Large;

            if (!wars.Any() && !system.IsBattleRoyaleMode)
            {
                this.ResetCharacterAiTypes(characters.Where(c => c.AiType.IsManaged() && !c.AiType.IsMoneyInflator()));

                var isWar = false;
                if (await this.FindVirtualEnemyCountryAsync(repo, this.allTowns, this.allCharacters))
                {
                    if (this.Country.AiType != CountryAiType.Puppet)
                    {
                        isWar = await this.SetWarAsync(repo, this.allTowns, this.allCharacters);
                    }
                }

                if (!isWar)
                {
                    await this.ChangeSomeInNotWarAsync(repo, characters, this.allTowns, wars);
                }
                await this.ChangeSomeInNotWarOrInReadyAsync(repo, characters, this.allTowns, wars);
            }
            else
            {
                if (!wars.Any(w => w.Status == CountryWarStatus.Available || w.Status == CountryWarStatus.StopRequesting) &&
                    wars.Any(w => w.Status == CountryWarStatus.InReady))
                {
                    if (wars.Where(w => w.Status == CountryWarStatus.InReady).All(w => w.IntStartGameDate > this.Game.IntGameDateTime + 24))
                    {
                        await this.ChangeSomeInNotWarOrInReadyAsync(repo, characters, this.allTowns, wars);
                    }
                    else
                    {
                        this.Management.TownWarTargetTownId = 0;
                    }
                }
                await this.ChangeSomeInWarAsync(repo, characters, this.allTowns, wars);
            }

            this.Management.IsPolicyFirst = this.Management.IsPolicySecond = false;
        }
コード例 #9
0
        private async Task <bool> SetWarAsync(MainRepository repo, IEnumerable <Town> allTowns, IEnumerable <Character> allCharacters)
        {
            var system = await repo.System.GetAsync();

            var policies = await repo.Country.GetPoliciesAsync(this.Country.Id);

            var towns                 = allTowns.Where(t => t.CountryId == this.Country.Id);
            var characters            = allCharacters.Where(c => c.CountryId == this.Country.Id && !c.AiType.IsSecretary() && c.AiType != CharacterAiType.ManagedEvangelist);
            var townsInReady          = towns.Where(t => this.IsReadyForWar(t));
            var charactersInReady     = characters.Where(c => this.IsReadyForWar(c));
            var characterGroupInReady = charactersInReady.GroupBy(c => c.GetCharacterType());
            var storageOptional       = await repo.AiCountry.GetStorategyByCountryIdAsync(this.Country.Id);

            if (system.RuleSet == GameRuleSet.BattleRoyale)
            {
                return(false);
            }

            if (!characterGroupInReady.Any(g => g.Key == CharacterType.Strong || g.Key == CharacterType.Intellect))
            {
                return(false);
            }

            if (this.Management.WarPolicy == AiCountryWarPolicy.GoodFight)
            {
                if (!charactersInReady.Any() || !townsInReady.Any())
                {
                    return(false);
                }
            }
            if (this.Management.WarPolicy == AiCountryWarPolicy.Balance)
            {
                if ((float)charactersInReady.Count() / characters.Count() < 0.4f || (float)townsInReady.Count() / towns.Count() < 0.4f)
                {
                    return(false);
                }
            }
            if (this.Management.WarPolicy == AiCountryWarPolicy.Carefully)
            {
                if ((float)charactersInReady.Count() / characters.Count() < 1.0f || (float)townsInReady.Count() / towns.Count() < 0.8f)
                {
                    return(false);
                }
            }

            if (storageOptional.HasData &&
                ((storageOptional.Data.BorderTownId != 0 && !townsInReady.Any(t => t.Id == storageOptional.Data.BorderTownId)) ||
                 (storageOptional.Data.MainTownId != 0 && !townsInReady.Any(t => t.Id == storageOptional.Data.MainTownId))))
            {
                return(false);
            }

            Country target = null;

            if (this.Management.VirtualEnemyCountryId != 0)
            {
                var t = await repo.Country.GetAliveByIdAsync(this.Management.VirtualEnemyCountryId);

                target = t.Data;
            }
            else
            {
                return(false);
            }

            var isCreated      = false;
            var startMonth     = AiService.GetWarStartDateTime(this.Game.GameDateTime, this.Management.WarStartDatePolicy);
            var nextStartMonth = AiService.GetWarStartDateTime(this.Game.GameDateTime.NextMonth(), this.Management.WarStartDatePolicy);

            if (startMonth.ToInt() != nextStartMonth.ToInt())
            {
                // isCreated = await AiService.CreateWarIfNotWarAsync(repo, this.Country, target, startMonth);
                isCreated = await AiService.CreateWarAsync(repo, this.Country, target, startMonth);

                if (isCreated)
                {
                    this.Management.VirtualEnemyCountryId = 0;
                }
            }
            return(isCreated);
        }
コード例 #10
0
        public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game)
        {
            var countryOptional = await repo.Country.GetByIdAsync(character.CountryId);

            if (!countryOptional.HasData)
            {
                await game.CharacterLogAsync($"別動隊を雇おうとしましたが、あなたの国はすでに滅亡しているか無所属です");

                return;
            }
            var country = countryOptional.Data;

            if (character.Money < 10000)
            {
                await game.CharacterLogAsync($"別動隊を雇おうとしましたが、金が足りません");

                return;
            }

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

            if (ais.Any())
            {
                await game.CharacterLogAsync($"別動隊を雇おうとしましたが、すでに雇用しています");

                return;
            }

            var system = await repo.System.GetAsync();

            var ai = AiCharacterFactory.Create(CharacterAiType.FlyingColumn);

            ai.Initialize(game.GameDateTime);
            ai.Character.CountryId   = character.CountryId;
            ai.Character.TownId      = country.CapitalTownId;
            ai.Character.LastUpdated = character.LastUpdated.AddSeconds(Config.UpdateTime + 10);
            if (ai.Character.LastUpdated > system.CurrentMonthStartDateTime.AddSeconds(Config.UpdateTime))
            {
                ai.Character.LastUpdatedGameDate = game.GameDateTime.NextMonth();
            }
            else
            {
                ai.Character.LastUpdatedGameDate = game.GameDateTime;
            }
            await repo.Character.AddAsync(ai.Character);

            await repo.SaveChangesAsync();

            await AiService.SetIconAsync(repo, ai.Character);

            ai.Character.Name       = character.Name + "_" + ai.Character.Name + ai.Character.Id;
            ai.Character.Strong     = (short)(character.Strong * 0.8f);
            ai.Character.Intellect  = (short)(character.Intellect * 0.8f);
            ai.Character.Leadership = (short)(character.Leadership * 0.8f);
            ai.Character.Popularity = (short)(character.Popularity * 0.8f);

            var management = new AiCharacterManagement
            {
                Action            = AiCharacterAction.None,
                SoldierType       = AiCharacterSoldierType.Default,
                CharacterId       = ai.Character.Id,
                HolderCharacterId = character.Id,
                TargetTownId      = 0,
            };
            await repo.Character.AddManagementAsync(management);

            character.Money -= 10000;
            character.SkillPoint++;
            character.Contribution += 100;
            character.AddLeadershipEx(50);

            var limit = system.GameDateTime.AddMonth(72);

            await game.CharacterLogAsync($"別動隊 <character>{ai.Character.Name}</character> を雇いました。雇用期限は <num>{limit.Year}</num> 年 <num>{limit.Month}</num> 月です");

            await game.MapLogAsync(EventType.SecretaryAdded, $"<country>{country.Name}</country> の <character>{character.Name}</character> は、新しく別動隊 <character>{ai.Character.Name}</character> を雇いました", false);

            await CharacterService.StreamCharacterAsync(repo, ai.Character);

            await StatusStreaming.Default.SendCharacterAsync(ApiData.From(management), character.Id);
        }
コード例 #11
0
        public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game)
        {
            var typeParam = options.FirstOrDefault(p => p.Type == 1);

            if (typeParam == null)
            {
                await game.CharacterLogAsync($"政務官を雇おうとしましたが、コマンドパラメータが足りません。<emerge>管理者に連絡してください</emerge>");

                return;
            }
            var type = (CharacterAiType)typeParam.NumberValue;

            var targetTownParam    = options.FirstOrDefault(p => p.Type == 2);
            var targetTownId       = (uint)targetTownParam.NumberValue;
            var targetTownOptional = await repo.Town.GetByIdAsync(targetTownId);

            var countryOptional = await repo.Country.GetByIdAsync(character.CountryId);

            if (!countryOptional.HasData)
            {
                await game.CharacterLogAsync($"政務官を雇おうとしましたが、あなたの国はすでに滅亡しているか無所属です");

                return;
            }
            var country = countryOptional.Data;

            var secretaries = (await repo.Country.GetCharactersAsync(country.Id)).Where(c => c.AiType.IsSecretary());
            // var policies = await repo.Country.GetPoliciesAsync(country.Id);
            var secretaryMax          = 4; // CountryService.GetSecretaryMax(policies.Where(p => p.Status == CountryPolicyStatus.Available).Select(p => p.Type));
            var currentSecretaryPoint = CountryService.GetCurrentSecretaryPoint(secretaries.Select(c => c.AiType));

            if (currentSecretaryPoint >= secretaryMax)
            {
                await game.CharacterLogAsync($"政務官を雇おうとしましたが、すでに政務官ポイントが上限 <num>{secretaryMax}</num> に達しています");

                return;
            }

            var afterSecretaryPoint = CountryService.GetCurrentSecretaryPoint(secretaries.Select(c => c.AiType).Append(type));

            if (afterSecretaryPoint > secretaryMax)
            {
                await game.CharacterLogAsync($"政務官を雇おうとしましたが、雇用後の政務官ポイントが上限 <num>{secretaryMax}</num> を越えます");

                return;
            }

            var cost = Config.SecretaryCost;

            if (character.Money < cost && country.SafeMoney < cost)
            {
                await game.CharacterLogAsync($"政務官を雇おうとしましたが、武将所持または国庫に金 <num>{cost}</num> がありません");

                return;
            }

            if (country.SafeMoney >= cost)
            {
                country.SafeMoney -= cost;
            }
            else
            {
                character.Money -= cost;
            }

            var system = await repo.System.GetAsync();

            var ai = AiCharacterFactory.Create(type);

            ai.Initialize(game.GameDateTime);
            ai.Character.CountryId = character.CountryId;
            ai.Character.TownId    = (type != CharacterAiType.SecretaryUnitLeader && targetTownOptional.HasData) ?
                                     targetTownId : country.CapitalTownId;
            ai.Character.Money = 10000;
            ai.Character.Rice  = 10000;
            if (type == CharacterAiType.SecretaryEvangelist)
            {
                ai.Character.Religion = country.Religion;
                ai.Character.From     = country.Religion == ReligionType.Confucianism ? CharacterFrom.Confucianism : country.Religion == ReligionType.Taoism ? CharacterFrom.Taoism : CharacterFrom.Buddhism;
            }
            if (type != CharacterAiType.SecretaryScouter)
            {
                ai.Character.LastUpdated = character.LastUpdated.AddSeconds(Config.UpdateTime + 10);
                if (ai.Character.LastUpdated > system.CurrentMonthStartDateTime.AddSeconds(Config.UpdateTime))
                {
                    ai.Character.LastUpdatedGameDate = game.GameDateTime.NextMonth();
                }
                else
                {
                    ai.Character.LastUpdatedGameDate = game.GameDateTime;
                }
            }
            else
            {
                // 斥候は0分0秒更新で諜報する
                ai.Character.LastUpdated         = system.CurrentMonthStartDateTime.AddSeconds(Config.UpdateTime);
                ai.Character.LastUpdatedGameDate = game.GameDateTime.NextMonth();
            }
            await repo.Character.AddAsync(ai.Character);

            await repo.SaveChangesAsync();

            await AiService.SetIconAsync(repo, ai.Character);

            if (type == CharacterAiType.SecretaryUnitLeader)
            {
                await UnitService.CreateAndSaveAsync(repo, new Unit
                {
                    CountryId = character.CountryId,
                    IsLimited = false,
                    Name      = "政務官部隊 ID:" + ai.Character.Id,
                }, ai.Character.Id);
            }

            ai.Character.Name      += ai.Character.Id;
            character.Contribution += 30;
            character.AddLeadershipEx(50);
            character.SkillPoint++;
            if (targetTownOptional.HasData && type != CharacterAiType.SecretaryUnitLeader)
            {
                await game.CharacterLogAsync($"政務官 <character>{ai.Character.Name}</character> を <town>{targetTownOptional.Data.Name}</town> で雇いました");
            }
            else
            {
                await game.CharacterLogAsync($"政務官 <character>{ai.Character.Name}</character> を雇いました");
            }
            await game.MapLogAsync(EventType.SecretaryAdded, $"<country>{country.Name}</country> は、新しく政務官 <character>{ai.Character.Name}</character> を雇いました", false);

            await CharacterService.StreamCharacterAsync(repo, ai.Character);
        }