예제 #1
0
        public async Task DeleteCountryBbsAsync(
            [FromRoute] uint id)
        {
            ThreadBbsItem message;
            Character     chara;

            using (var repo = MainRepository.WithReadAndWrite())
            {
                chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError);

                var item = await repo.ThreadBbs.GetByIdAsync(id).GetOrErrorAsync(ErrorCode.NodeNotFoundError);

                if (item.CharacterId != chara.Id)
                {
                    var posts = await repo.Country.GetCharacterPostsAsync(chara.Id);

                    var characterPosts = posts.Select(p => p.Type);
                    if (!characterPosts.Any(p => p == CountryPostType.Monarch || p == CountryPostType.Warrior))
                    {
                        ErrorCode.NotPermissionError.Throw();
                    }
                }

                message = item;
                repo.ThreadBbs.Remove(item);
                await repo.SaveChangesAsync();
            }

            message.IsRemove = true;
            await StatusStreaming.Default.SendCountryAsync(ApiData.From(message), chara.CountryId);
        }
예제 #2
0
        public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game)
        {
            if (character.CountryId == 0)
            {
                await game.CharacterLogAsync($"国庫に金を納入しようとしましたが、無所属は実行できません");

                return;
            }

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

            if (!countryOptional.HasData)
            {
                await game.CharacterLogAsync($"ID: <num>{character.CountryId}</num> の国は存在しません。<emerge>管理者にお問い合わせください</emerge>");

                return;
            }

            var country = countryOptional.Data;

            if (country.HasOverthrown)
            {
                await game.CharacterLogAsync($"国庫に金を納入しようとしましたが、あなたの所属国 <country>{country.Name}</country> はすでに滅亡しています");

                return;
            }

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

            var max = 1000_0000; // CountryService.GetCountrySafeMax(policies.Where(p => p.Status == CountryPolicyStatus.Available).Select(p => p.Type));

            var money = options.FirstOrDefault(o => o.Type == 1)?.NumberValue ?? 0;

            if (money > character.Money)
            {
                await game.CharacterLogAsync($"国庫に金 <num>{money}</num> を納入しようとしましたが、所持金が足りません");

                return;
            }

            if (country.SafeMoney + money > max)
            {
                money = max - country.SafeMoney;
                if (money < 0)
                {
                    // 支配とか災害とかで上限が下がることがある
                    money = 0;
                }
            }
            country.SafeMoney      += money;
            character.Money        -= money;
            character.Contribution += 30;
            character.SkillPoint++;

            await game.CharacterLogAsync($"国庫に金 <num>{money}</num> を納入しました");

            await StatusStreaming.Default.SendCountryAsync(ApiData.From(country), country.Id);

            return;
        }
예제 #3
0
        public static async Task <CharacterItem> DivideResourceAndSaveAsync(MainRepository repo, CharacterItem item, int resourceSize)
        {
            if (item.Resource <= resourceSize)
            {
                return(item);
            }

            item.Resource -= resourceSize;

            var newItem = new CharacterItem
            {
                Type        = item.Type,
                Status      = item.Status,
                CharacterId = item.CharacterId,
                TownId      = item.TownId,
                IntLastStatusChangedGameDate = item.IntLastStatusChangedGameDate,
                Resource = resourceSize,
            };

            await GenerateItemAndSaveAsync(repo, newItem);

            await StatusStreaming.Default.SendAllAsync(ApiData.From(newItem));

            await StatusStreaming.Default.SendAllAsync(ApiData.From(item));

            return(newItem);
        }
예제 #4
0
        public async Task PostGlobalChatMessageAsync(
            [FromBody] ChatMessage param)
        {
            var         ip = this.HttpContext.Connection.RemoteIpAddress?.ToString();
            ChatMessage message;
            Character   chara;

            if (string.IsNullOrEmpty(param.Message) || param.Message?.Length > 400)
            {
                ErrorCode.NumberRangeError.Throw(new ErrorCode.RangeErrorParameter("message", param.Message.Length, 1, 400));
            }

            using (var repo = MainRepository.WithReadAndWrite())
            {
                chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError);

                if (await repo.BlockAction.IsBlockedAsync(chara.Id, BlockActionType.StopGlobalChat))
                {
                    ErrorCode.BlockedActionError.Throw();
                }

                message = await ChatService.PostChatMessageAsync(repo, param, chara, ip, ChatMessageType.Global, param.TypeData);

                await repo.SaveChangesAsync();
            }

            await StatusStreaming.Default.SendAllAsync(ApiData.From(message));
        }
예제 #5
0
        public static async Task SetCharacterPendingAsync(MainRepository repo, CharacterItem item, Character chara)
        {
            if (item.Status == CharacterItemStatus.CharacterHold || item.Status == CharacterItemStatus.CharacterPending)
            {
                if (item.CharacterId == chara.Id)
                {
                    return;
                }

                var oldChara = await repo.Character.GetByIdAsync(item.CharacterId);

                if (oldChara.HasData)
                {
                    await ReleaseCharacterAsync(repo, item, oldChara.Data);
                }
            }

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

            item.Status      = CharacterItemStatus.CharacterPending;
            item.CharacterId = chara.Id;
            item.TownId      = 0;
            item.LastStatusChangedGameDate = system.GameDateTime;

            await CharacterService.StreamCharacterAsync(repo, chara);

            await StatusStreaming.Default.SendAllAsync(ApiData.From(item));
        }
예제 #6
0
        public static async Task StreamCharacterAsync(MainRepository repo, Character character)
        {
            // 同じ都市にいる他国の武将への通知、移動前の都市に滞在かつ違う国の武将への都市移動の通知は、以下の処理の中に含まれるので特段の対処は不要
            var icon = (await repo.Character.GetCharacterAllIconsAsync(character.Id)).GetMainOrFirst();
            var town = await repo.Town.GetByIdAsync(character.TownId);

            var townCharacters = await repo.Town.GetCharactersAsync(character.TownId);

            // この武将の所属する国の武将
            await StatusStreaming.Default.SendCountryExceptForCharacterAsync(ApiData.From(new CharacterForAnonymous(character, icon.Data, CharacterShareLevel.SameCountry)), character.CountryId, character.Id);

            // 都市の武将
            await StatusStreaming.Default.SendCharacterAsync(ApiData.From(new CharacterForAnonymous(character, icon.Data, character.AiType != CharacterAiType.SecretaryScouter ? CharacterShareLevel.SameTown : CharacterShareLevel.Anonymous)), townCharacters.Where(tc => tc.Id != character.Id && tc.CountryId != character.CountryId).Select(tc => tc.Id));

            if (town.HasData && town.Data.CountryId != character.CountryId)
            {
                // この都市を所有している国の武将
                await StatusStreaming.Default.SendCountryExceptForCharacterAsync(ApiData.From(new CharacterForAnonymous(character, icon.Data, character.AiType != CharacterAiType.SecretaryScouter ? CharacterShareLevel.SameCountryTownOtherCountry : CharacterShareLevel.Anonymous)), town.Data?.CountryId ?? 0, townCharacters.Where(tc => tc.CountryId == town.Data?.CountryId).Select(tc => tc.Id));
            }

            // 本人と違う国で、かつ同じ都市にいない武将
            await StatusStreaming.Default.SendAllExceptForCharactersAndCountryAsync(ApiData.From(new CharacterForAnonymous(character, icon.Data, CharacterShareLevel.Anonymous)), townCharacters.Select(tc => tc.Id), new uint[] { town.Data?.CountryId ?? 0, character.CountryId, });

            // 本人
            await StatusStreaming.Default.SendCharacterAsync(ApiData.From(character), character.Id);
        }
예제 #7
0
        public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game)
        {
            var items = await repo.Character.GetItemsAsync(character.Id);

            var item = items.FirstOrDefault(i => i.Type == CharacterItemType.TimeChanger);

            if (item == null || item.Resource <= 0)
            {
                if (item != null)
                {
                    await ItemService.SpendCharacterAsync(repo, item, character);
                }
                await game.CharacterLogAsync("静養しようとしましたが、コマンド実行に必要なアイテムを所持していません");

                return;
            }

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

            var time = RandomService.Next(0, Config.UpdateTime * 100_000) / 100_000.0;

            character.LastUpdated = system.CurrentMonthStartDateTime.AddSeconds(time - Config.UpdateTime);

            item.Resource--;
            if (item.Resource <= 0)
            {
                await ItemService.SpendCharacterAsync(repo, item, character);
            }
            else
            {
                await StatusStreaming.Default.SendCharacterAsync(ApiData.From(item), character.Id);
            }

            await game.CharacterLogAsync($"更新時刻を月開始の <num>{(int)time}</num> 秒後に変更しました。アイテム残り: <num>{item.Resource}</num>");
        }
예제 #8
0
        public async Task SetMuteKeywordsAsync([FromBody] MuteKeyword keyword)
        {
            if (keyword == null)
            {
                ErrorCode.LackOfParameterError.Throw();
            }

            using (var repo = MainRepository.WithReadAndWrite())
            {
                var chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError);

                keyword.CharacterId = this.AuthData.CharacterId;

                var old = await repo.Mute.GetCharacterKeywordAsync(chara.Id);

                if (old.HasData)
                {
                    old.Data.Keywords = keyword.Keywords;
                }
                else
                {
                    await repo.Mute.AddAsync(keyword);
                }

                await repo.SaveChangesAsync();
            }

            await StatusStreaming.Default.SendCharacterAsync(ApiData.From(keyword), keyword.CharacterId);
        }
        public override void OnException(ExceptionContext context)
        {
            base.OnException(context);

            if (!(context.Exception is SangokuKmyException exception))
            {
                exception = new SangokuKmyException(context.Exception, ErrorCode.InternalError);
            }

            this.logger.LogError(exception, $"{context.HttpContext.Request.Method} [{(context.HttpContext.Request.Path.HasValue ? context.HttpContext.Request.Path.Value : "no-path")}]");

            try
            {
                context.HttpContext.Response.StatusCode = exception.StatusCode;
                context.Result = new JsonResult(ApiData.From(new ApiError {
                    Code = exception.ErrorCode.Code, Data = exception.AdditionalData
                }));
            }
            catch
            {
                context.HttpContext.Response.StatusCode = 500;
                context.Result = new JsonResult(ApiData.From(new ApiError {
                    Code = -1, Data = default(object)
                }));
            }

            context.ExceptionHandled = true;
        }
예제 #10
0
        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));
            }
        }
예제 #11
0
        public static async Task SendTownWarAndSaveAsync(MainRepository repo, TownWar war)
        {
            await repo.CountryDiplomacies.SetTownWarAsync(war);

            await repo.SaveChangesAsync();

            await StatusStreaming.Default.SendCountryAsync(ApiData.From(war), war.RequestedCountryId);
        }
예제 #12
0
        public async Task UpdateItemStatusAsync(
            [FromBody] IssueBbsItem param)
        {
            IssueBbsItem message;
            Character    chara;

            using (var repo = MainRepository.WithReadAndWrite())
            {
                chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError);

                if (chara.AiType != CharacterAiType.Administrator)
                {
                    ErrorCode.NotPermissionError.Throw();
                }

                message = await repo.IssueBbs.GetByIdAsync(param.Id).GetOrErrorAsync(ErrorCode.NodeNotFoundError);

                if (param.Status != IssueStatus.Undefined)
                {
                    message.Status = param.Status;
                }
                if (param.Category != IssueCategory.Undefined)
                {
                    message.Category = param.Category;
                }
                if (param.Period != 0 || param.Milestone != IssueMilestone.Unknown)
                {
                    var system = await repo.System.GetAsync();

                    if (param.Milestone == IssueMilestone.CurrentPeriod)
                    {
                        message.Period      = system.Period;
                        message.BetaVersion = system.BetaVersion;
                    }
                    else if (param.Milestone == IssueMilestone.NextPeriod)
                    {
                        var period = system.IsNextPeriodBeta ? system.Period : system.Period + 1;
                        var beta   = system.IsNextPeriodBeta ? system.BetaVersion + 1 : 0;
                        message.Period      = (short)period;
                        message.BetaVersion = (short)beta;
                    }
                    else if (param.Milestone == IssueMilestone.Clear)
                    {
                        message.Period      = 0;
                        message.BetaVersion = 0;
                    }
                    else
                    {
                        message.Period      = param.Period;
                        message.BetaVersion = param.BetaVersion;
                    }
                }

                await repo.SaveChangesAsync();
            }

            await StatusStreaming.Default.SendAllAsync(ApiData.From(message));
        }
예제 #13
0
        public async Task RemoveMuteAsync([FromBody] Mute mute)
        {
            var ip = this.HttpContext.Connection.RemoteIpAddress?.ToString();
            IList <ChatMessage>     chats  = null;
            IEnumerable <Character> admins = null;

            if (mute == null)
            {
                ErrorCode.LackOfParameterError.Throw();
            }

            using (var repo = MainRepository.WithReadAndWrite())
            {
                var chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError);

                var mutes = await repo.Mute.GetCharacterAsync(chara.Id);

                var target = mutes.FirstOrDefault(m => m.Id == mute.Id ||
                                                  (m.TargetCharacterId != 0 && m.TargetCharacterId == mute.TargetCharacterId) ||
                                                  (m.ChatMessageId != 0 && m.ChatMessageId == mute.ChatMessageId) ||
                                                  (m.ThreadBbsItemId != 0 && m.ThreadBbsItemId == mute.ThreadBbsItemId) ||
                                                  (m.IssueBbsItemId != 0 && m.IssueBbsItemId == mute.IssueBbsItemId));
                if (target == null)
                {
                    ErrorCode.InvalidOperationError.Throw();
                }

                mute = target;
                repo.Mute.Remove(target);

                if (target.Type == MuteType.Reported)
                {
                    admins = await repo.Character.GetAdministratorsAsync();

                    chats = new List <ChatMessage>();
                    foreach (var admin in admins)
                    {
                        chats.Add(await ChatService.PostChatMessageAsync(repo, new ChatMessage
                        {
                            Message = $"[b][s]【報告解除】[-s][-b]\n\nMute ID: {mute.Id}",
                        }, chara, ip, ChatMessageType.Private, admin.Id, admin.Id));
                    }
                }

                await repo.SaveChangesAsync();
            }

            mute.Type = MuteType.None;
            await StatusStreaming.Default.SendCharacterAsync(ApiData.From(mute), mute.CharacterId);

            if (admins != null && chats != null)
            {
                await StatusStreaming.Default.SendCharacterAsync(chats.Select(c => ApiData.From(c)), admins.Select(a => a.Id));
            }
        }
예제 #14
0
        public static async Task RemoveAsync(MainRepository repo, uint unitId)
        {
            var members = await repo.Unit.GetMembersAsync(unitId);

            repo.Unit.RemoveUnit(unitId);

            await StatusStreaming.Default.SendCharacterAsync(ApiData.From(new ApiSignal
            {
                Type = SignalType.UnitRemoved,
            }), members.Select(um => um.CharacterId));
        }
예제 #15
0
        public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game)
        {
            var townIdOptional = options.FirstOrDefault(p => p.Type == 1).ToOptional();

            if (character.Money < 200)
            {
                await game.CharacterLogAsync("偵察に必要な金が足りません");
            }
            if (!townIdOptional.HasData)
            {
                await game.CharacterLogAsync("偵察のパラメータが不正です。<emerge>管理者にお問い合わせください</emerge>");
            }
            else
            {
                var townOptional = await repo.Town.GetByIdAsync((uint)townIdOptional.Data.NumberValue);

                if (!townOptional.HasData)
                {
                    await game.CharacterLogAsync("ID:" + townIdOptional.Data + " の都市は存在しません。<emerge>管理者にお問い合わせください</emerge>");
                }
                else
                {
                    var town = townOptional.Data;

                    var scoutedTown = ScoutedTown.From(townOptional.Data);
                    scoutedTown.ScoutedDateTime  = game.GameDateTime;
                    scoutedTown.ScoutedCountryId = character.CountryId;
                    scoutedTown.ScoutMethod      = ScoutMethod.SpyCommand;

                    await repo.ScoutedTown.AddScoutAsync(scoutedTown);

                    await repo.SaveChangesAsync();

                    var savedScoutedTown = (await repo.ScoutedTown.GetByTownIdAsync(townOptional.Data.Id, character.CountryId)).Data;
                    if (savedScoutedTown != null)
                    {
                        await StatusStreaming.Default.SendCountryAsync(ApiData.From(savedScoutedTown), character.CountryId);
                    }

                    var items = await repo.CharacterItem.GetByTownIdAsync(town.Id);

                    var itemInfos = items.GetInfos();

                    await game.CharacterLogAsync($"都市 {town.Name} を偵察しました");

                    await game.CharacterLogAsync($"都市 {town.Name} のアイテム: {string.Join(", ", itemInfos.Select(i => i.Name))}");

                    character.Money        -= 200;
                    character.Contribution += 40;
                    character.AddIntellectEx(50);
                    character.SkillPoint++;
                }
            }
        }
예제 #16
0
        public async Task <ApiArrayData <ChatMessage> > GetPrivateChatMessagesAsync(
            [FromQuery] uint sinceId = default,
            [FromQuery] int count    = default)
        {
            IEnumerable <ChatMessage> messages;

            using (var repo = MainRepository.WithRead())
            {
                messages = await repo.ChatMessage.GetPrivateMessagesAsync(this.AuthData.CharacterId, sinceId, count);
            }
            return(ApiData.From(messages));
        }
예제 #17
0
        public static async Task DenyCountryPromotions(MainRepository repo, Country country)
        {
            var promotions = (await repo.ChatMessage.GetPromotionMessagesAsync(country.Id)).Where(p => p.Type == ChatMessageType.Promotion);

            foreach (var p in promotions)
            {
                p.Type = ChatMessageType.PromotionDenied;
                await StatusStreaming.Default.SendCharacterAsync(ApiData.From(p), p.TypeData);

                await StatusStreaming.Default.SendCharacterAsync(ApiData.From(p), p.TypeData2);
            }
        }
        public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game)
        {
            if (character.Money < 50)
            {
                await game.CharacterLogAsync("金が足りません。<num>50</num> 必要です");

                return;
            }

            var townOptional = await repo.Town.GetByIdAsync(character.TownId);

            if (townOptional.HasData)
            {
                var town = townOptional.Data;
                if (town.CountryId != character.CountryId)
                {
                    await game.CharacterLogAsync("<town>" + town.Name + "</town>で訓練しようとしましたが、自国の都市ではありません");

                    return;
                }

                var add = (int)(character.Leadership / 6.0f + RandomService.Next(0, character.Leadership) / 6.0f);
                if (add < 1)
                {
                    add = 1;
                }

                var charas = await repo.Town.GetCharactersAsync(town.Id);

                foreach (var chara in charas.Where(c => c.CountryId == character.CountryId))
                {
                    chara.Proficiency = (short)Math.Min(100, chara.Proficiency + add);
                    if (chara.Id != character.Id)
                    {
                        await game.CharacterLogByIdAsync(chara.Id, $"<character>{character.Name}</character> による合同訓練で、訓練が <num>+{add}</num> 上がりました");

                        await StatusStreaming.Default.SendCharacterAsync(ApiData.From(chara), chara.Id);
                    }
                }

                // 経験値、金の増減
                character.Money        -= 50;
                character.Contribution += 30;
                character.AddLeadershipEx(50);
                character.SkillPoint++;
                await game.CharacterLogAsync("訓練を <num>+" + add + "</num> 上げました");
            }
            else
            {
                await game.CharacterLogAsync("ID:" + character.TownId + " の都市は存在しません。<emerge>管理者にお問い合わせください</emerge>");
            }
        }
예제 #19
0
        public async Task <ApiArrayData <ChatMessage> > GetGlobalChatMessagesAsync(
            [FromQuery] uint sinceId = default,
            [FromQuery] int type     = default,
            [FromQuery] int count    = default)
        {
            IEnumerable <ChatMessage> messages;

            using (var repo = MainRepository.WithRead())
            {
                messages = await repo.ChatMessage.GetGlobalMessagesAsync(sinceId, type, count);
            }
            return(ApiData.From(messages));
        }
예제 #20
0
        public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game)
        {
            var townOptional = await repo.Town.GetByIdAsync(character.TownId);

            if (!townOptional.HasData)
            {
                await game.CharacterLogAsync("ID: " + character.TownId + " の都市は存在しません。<emerge>管理者に連絡してください</emerge>");
            }
            else if (character.SoldierNumber <= 0)
            {
                await game.CharacterLogAsync("守備には、最低でも 1 人以上の兵士が必要です");
            }
            else
            {
                var town = townOptional.Data;
                if (town.CountryId != character.CountryId)
                {
                    await game.CharacterLogAsync("自国の都市以外を守備することはできません");
                }
                else
                {
                    character.Contribution += 25;
                    character.AddLeadershipEx(50);
                    character.SkillPoint++;
                    var def = await repo.Town.SetDefenderAsync(character.Id, town.Id);

                    await game.CharacterLogAsync("<town>" + town.Name + "</town> の守備につきました");

                    def.Status = TownDefenderStatus.Available;
                    var townCharas = await repo.Town.GetCharactersAsync(town.Id);

                    await StatusStreaming.Default.SendCountryAsync(ApiData.From(def), character.CountryId);

                    await StatusStreaming.Default.SendCharacterAsync(ApiData.From(def), townCharas.Where(tc => tc.Id != character.Id && tc.CountryId != character.CountryId).Select(tc => tc.Id));

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

                    if (wars.Any(w => (w.InsistedCountryId == character.CountryId || w.RequestedCountryId == character.CountryId) && (w.Status != CountryWarStatus.None && w.Status != CountryWarStatus.Stoped)) &&
                        RandomService.Next(0, 128) == 0)
                    {
                        var info = await ItemService.PickTownHiddenItemAsync(repo, character.TownId, character);

                        if (info.HasData)
                        {
                            await game.CharacterLogAsync($"<town>{town.Name}</town> に隠されたアイテム {info.Data.Name} を手に入れました");
                        }
                    }
                }
            }
        }
예제 #21
0
        public async Task <ApiArrayData <ChatMessage> > GetCountryChatMessagesAsync(
            [FromQuery] uint sinceId = default,
            [FromQuery] int count    = default)
        {
            IEnumerable <ChatMessage> messages;

            using (var repo = MainRepository.WithRead())
            {
                var chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError);

                messages = await repo.ChatMessage.GetCountryMessagesAsync(chara.CountryId, sinceId, count);
            }
            return(ApiData.From(messages));
        }
예제 #22
0
        public static async Task <CharacterLog> AddCharacterLogAsync(MainRepository repo, GameDateTime current, uint id, string message)
        {
            var log = new CharacterLog
            {
                GameDateTime = current,
                DateTime     = DateTime.Now,
                CharacterId  = id,
                Message      = message,
            };
            await repo.Character.AddCharacterLogAsync(log);

            await StatusStreaming.Default.SendCharacterAsync(ApiData.From(log), id);

            return(log);
        }
예제 #23
0
        public async Task <ApiData <AuthenticationData> > Entry(
            [FromBody] EntryData param)
        {
            var ip = this.HttpContext.Connection.RemoteIpAddress?.ToString();

            using (var repo = MainRepository.WithReadAndWrite())
            {
                await EntryService.EntryAsync(repo, ip, param.Character, param.Icon, param.Password, param.Country, param.InvitationCode, param.IsCountryFree);

                await repo.SaveChangesAsync();

                var authData = await AuthenticationService.WithIdAndPasswordAsync(repo, param.Character.AliasId, param.Password, ip);

                return(ApiData.From(authData));
            }
        }
예제 #24
0
        public async Task DischargeUnitMemberAsync(
            [FromRoute] uint unitId,
            [FromRoute] uint charaId)
        {
            using (var repo = MainRepository.WithReadAndWrite())
            {
                var old = await repo.Unit.GetByIdAsync(unitId);

                if (!old.HasData)
                {
                    ErrorCode.UnitNotFoundError.Throw();
                }
                var unit = old.Data;

                var members = await repo.Unit.GetMembersAsync(unitId);

                if (!members.Any(u => u.Post == UnitMemberPostType.Leader && u.CharacterId == this.AuthData.CharacterId))
                {
                    ErrorCode.NotPermissionError.Throw();
                }

                if (this.AuthData.CharacterId == charaId)
                {
                    ErrorCode.InvalidOperationError.Throw();
                }

                UnitService.Leave(repo, charaId);

                var log = new CharacterLog
                {
                    CharacterId  = charaId,
                    DateTime     = DateTime.Now,
                    GameDateTime = (await repo.System.GetAsync()).GameDateTime,
                    Message      = $"部隊 {unit.Name} から除隊されました",
                };
                await repo.Character.AddCharacterLogAsync(log);

                await StatusStreaming.Default.SendCharacterAsync(ApiData.From(log), charaId);

                await StatusStreaming.Default.SendCharacterAsync(ApiData.From(new ApiSignal
                {
                    Type = SignalType.UnitDischarged,
                }), charaId);

                await repo.SaveChangesAsync();
            }
        }
예제 #25
0
        private static async Task RunCountryPolicyAsync(MainRepository repo, Country country, CountryPolicyType type)
        {
            if (type == CountryPolicyType.TotalMobilization || type == CountryPolicyType.TotalMobilization2)
            {
                foreach (var chara in await repo.Country.GetCharactersAsync(country.Id))
                {
                    chara.SoldierNumber = chara.Leadership;
                    chara.Proficiency   = 100;
                    var formation = await repo.Character.GetFormationAsync(chara.Id, chara.FormationType);

                    formation.Experience += 5000;
                    await CharacterService.StreamCharacterAsync(repo, chara);

                    await StatusStreaming.Default.SendCharacterAsync(ApiData.From(formation), chara.Id);
                }
                await LogService.AddMapLogAsync(repo, true, EventType.Policy, $"<country>{country.Name}</country> は、国民総動員を発動しました");
            }
            else if (type == CountryPolicyType.TotalMobilizationWall || type == CountryPolicyType.TotalMobilizationWall2)
            {
                foreach (var town in await repo.Town.GetByCountryIdAsync(country.Id))
                {
                    town.Technology = town.TechnologyMax;
                    town.Wall       = town.WallMax;
                    await StatusStreaming.Default.SendTownToAllAsync(ApiData.From(town), repo);
                }
                await LogService.AddMapLogAsync(repo, true, EventType.Policy, $"<country>{country.Name}</country> は、城壁作業員総動員を発動しました");
            }
            else if (type == CountryPolicyType.Austerity || type == CountryPolicyType.Austerity2)
            {
                foreach (var chara in await repo.Country.GetCharactersAsync(country.Id))
                {
                    chara.Money += 20_0000;
                    await CharacterService.StreamCharacterAsync(repo, chara);
                }
                await LogService.AddMapLogAsync(repo, true, EventType.Policy, $"<country>{country.Name}</country> は、緊縮財政を発動しました");
            }

            var info = CountryPolicyTypeInfoes.Get(type);

            if (info.HasData && info.Data.Effects.Any(e => e.Type == CountryPolicyEffectType.SubBuildingSizeMax))
            {
                country.TownSubBuildingExtraSpace +=
                    (short)info.Data.Effects
                    .Where(e => e.Type == CountryPolicyEffectType.SubBuildingSizeMax)
                    .Sum(e => e.Value);
            }
        }
예제 #26
0
        public static async Task ReleaseCharacterAsync(MainRepository repo, CharacterSkill item, Character chara)
        {
            var strong     = (short)item.GetSumOfValues(CharacterSkillEffectType.Strong);
            var intellect  = (short)item.GetSumOfValues(CharacterSkillEffectType.Intellect);
            var leadership = (short)item.GetSumOfValues(CharacterSkillEffectType.Leadership);
            var popularity = (short)item.GetSumOfValues(CharacterSkillEffectType.Popularity);

            chara.Strong     -= strong;
            chara.Intellect  -= intellect;
            chara.Leadership -= leadership;
            chara.Popularity -= popularity;

            item.Status = CharacterSkillStatus.Undefined;

            await StatusStreaming.Default.SendCharacterAsync(ApiData.From(chara), chara.Id);

            await StatusStreaming.Default.SendCharacterAsync(ApiData.From(item), chara.Id);
        }
예제 #27
0
        public static async Task RequestResetAsync(MainRepository repo, uint unifiedCountryId)
        {
            var system = await repo.System.GetAsync();

            system.IsWaitingReset     = true;
            system.IsBattleRoyaleMode = false;

            var currentMonth   = system.CurrentMonthStartDateTime;
            var todayResetHour = new DateTime(currentMonth.Year, currentMonth.Month, currentMonth.Day, 20, 0, 0, 0);
            var resetHour      = todayResetHour.AddDays(currentMonth.Hour < 20 ? 1 : 2);
            var sinceResetTime = resetHour - currentMonth;
            var resetTurn      = (int)Math.Round(sinceResetTime.TotalMinutes / 10.0f);

            system.ResetGameDateTime = GameDateTime.FromInt(system.GameDateTime.ToInt() + resetTurn);

            await RecordHistoryAsync(repo, system, unifiedCountryId);

            await StatusStreaming.Default.SendAllAsync(ApiData.From(system));
        }
예제 #28
0
        private static async Task ReleaseCharacterAsync(MainRepository repo, CharacterItem item, Character chara, CharacterItemStatus newStatus)
        {
            if ((item.Status != CharacterItemStatus.CharacterHold && item.Status != CharacterItemStatus.CharacterPending) || (chara != null && item.CharacterId != chara.Id))
            {
                return;
            }

            if (chara != null && item.Status == CharacterItemStatus.CharacterHold)
            {
                var strong     = (short)item.GetSumOfValues(CharacterItemEffectType.Strong);
                var intellect  = (short)item.GetSumOfValues(CharacterItemEffectType.Intellect);
                var leadership = (short)item.GetSumOfValues(CharacterItemEffectType.Leadership);
                var popularity = (short)item.GetSumOfValues(CharacterItemEffectType.Popularity);

                chara.Strong     -= strong;
                chara.Intellect  -= intellect;
                chara.Leadership -= leadership;
                chara.Popularity -= popularity;
            }

            item.Status      = newStatus;
            item.CharacterId = 0;

            if (newStatus == CharacterItemStatus.TownHidden || newStatus == CharacterItemStatus.TownOnSale)
            {
                if (chara == null)
                {
                    var towns = await repo.Town.GetAllAsync();

                    item.TownId = RandomService.Next(towns).Id;
                }
                else
                {
                    item.TownId = chara.TownId;
                }
            }

            if (chara != null)
            {
                await CharacterService.StreamCharacterAsync(repo, chara);
            }
            await StatusStreaming.Default.SendAllAsync(ApiData.From(item));
        }
예제 #29
0
        public async Task PostOtherCountryChatMessageAsync(
            [FromRoute] uint id,
            [FromBody] ChatMessage param)
        {
            var         ip = this.HttpContext.Connection.RemoteIpAddress?.ToString();
            ChatMessage message;
            Character   chara;

            if (string.IsNullOrEmpty(param.Message) || param.Message?.Length > 400)
            {
                ErrorCode.NumberRangeError.Throw(new ErrorCode.RangeErrorParameter("message", param.Message.Length, 1, 400));
            }

            using (var repo = MainRepository.WithReadAndWrite())
            {
                chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError);

                if (await repo.BlockAction.IsBlockedAsync(chara.Id, BlockActionType.StopCountryChat))
                {
                    ErrorCode.BlockedActionError.Throw();
                }

                var to = await repo.Country.GetAliveByIdAsync(id).GetOrErrorAsync(ErrorCode.CountryNotFoundError);

                var country = await repo.Country.GetAliveByIdAsync(id).GetOrErrorAsync(ErrorCode.CountryNotFoundError);

                var posts = (await repo.Country.GetPostsAsync(chara.CountryId)).Where(p => p.CharacterId == chara.Id);
                if (!posts.Any(p => p.Type.CanDiplomacy()))
                {
                    ErrorCode.NotPermissionError.Throw();
                }

                message = await ChatService.PostChatMessageAsync(repo, param, chara, ip, ChatMessageType.OtherCountry, chara.CountryId, id);

                await repo.SaveChangesAsync();
            }

            await StatusStreaming.Default.SendCountryAsync(ApiData.From(message), chara.CountryId);

            await StatusStreaming.Default.SendCountryAsync(ApiData.From(message), id);
        }
예제 #30
0
        public async Task PostPrivateChatMessageAsync(
            [FromRoute] uint id,
            [FromBody] ChatMessage param)
        {
            var         ip = this.HttpContext.Connection.RemoteIpAddress?.ToString();
            ChatMessage message;
            Character   chara;

            if (string.IsNullOrEmpty(param.Message) || param.Message?.Length > 400)
            {
                ErrorCode.NumberRangeError.Throw(new ErrorCode.RangeErrorParameter("message", param.Message.Length, 1, 400));
            }

            using (var repo = MainRepository.WithReadAndWrite())
            {
                chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError);

                var to = await repo.Character.GetByIdAsync(id).GetOrErrorAsync(ErrorCode.CharacterNotFoundError);

                if (chara.Id == to.Id)
                {
                    // 自分に対して個人宛は送れない
                    ErrorCode.MeaninglessOperationError.Throw();
                }

                if (await repo.BlockAction.IsBlockedAsync(chara.Id, BlockActionType.StopPrivateChatWithoutAdministrator))
                {
                    if (to.AiType != CharacterAiType.Administrator)
                    {
                        ErrorCode.BlockedActionError.Throw();
                    }
                }

                message = await ChatService.PostChatMessageAsync(repo, param, chara, ip, ChatMessageType.Private, chara.Id, id);

                await repo.SaveChangesAsync();
            }

            await StatusStreaming.Default.SendCharacterAsync(ApiData.From(message), new uint[] { chara.Id, id, });
        }