Ejemplo n.º 1
0
        public static int CalcMedal(Models.User user, Session session, bool IsDraw, ServerCommon.PlayerResult player, bool is_character_rank_level_up, JGameModeData game_mode, ref int win_medal, ref int lose_medal, ref int draw_medal, ref int mvp_medal, ref int rankup_medal)
        {
            var    reason     = $"A_PLAY_{game_mode.LogName}";
            string sub_reason = "";

            int medal_count = 0;

            // 메달 수량 체크
            // 승패
            if (IsDraw)
            {
                medal_count += game_mode.RewardDrawMedal;
                sub_reason   = "3";
            }
            else if (player.IsWin)
            {
                medal_count += game_mode.RewardWinMedal;
                sub_reason   = "1";
            }
            else if (player.IsLose)
            {
                medal_count += game_mode.RewardLoseMedal;
                sub_reason   = "2";
            }

            // 메달 획득 허용치 체크 및 조정
            medal_count = GetAvailableMedalCount(user, session, medal_count);
            _           = LogProxy.writeResourceLog(session, "n", ((int)GameItemId.Medal).ToString(), medal_count, 0, user.medal + medal_count, "add", reason, sub_reason).ConfigureAwait(false);

            if (IsDraw)
            {
                draw_medal += medal_count;
            }
            else if (player.IsWin)
            {
                win_medal += medal_count;
            }
            else if (player.IsLose)
            {
                lose_medal += medal_count;
            }

            // MVP
            if (player.IsMvp)
            {
                medal_count += game_mode.RewardMVPMedal;
                mvp_medal   += game_mode.RewardMVPMedal;
                _            = LogProxy.writeResourceLog(session, "n", ((int)GameItemId.Medal).ToString(), game_mode.RewardMVPMedal, 0, user.medal + medal_count, "add", reason, "4").ConfigureAwait(false);
            }
            // 케릭터 랭크 레벨업
            if (is_character_rank_level_up)
            {
                medal_count  += game_mode.RewardRankupMedal;
                rankup_medal += game_mode.RewardRankupMedal;
                reason        = $"A_PLAY_RANKUP";
                _             = LogProxy.writeResourceLog(session, "n", ((int)GameItemId.Medal).ToString(), game_mode.RewardRankupMedal, 0, user.medal + medal_count, "add", reason, "").ConfigureAwait(false);
            }

            return(medal_count);
        }
Ejemplo n.º 2
0
        public static bool UseGoods(Session session, Models.User user, int item_id, int item_count, LogReason reason)
        {
            var game_item_data = ACDC.GameItemData[item_id];

            if (game_item_data == null || game_item_data == default(JGameItemData))
            {
                Log.Error($"cannot find item:{item_id}, user_name:{session.user_name}");
                return(false);
            }

            if (user[item_id] < item_count)
            {
                return(false);
            }

            user[item_id] -= item_count;

            user.IsDirty = true;
            //History.Info(session.member_no, session.user_no, session.character_no, HistoryLogAction.UseItem, (byte)reason, (int)item_id, (int)item_count, "", "");

            if (reason != null)
            {
                _ = LogProxy.writeResourceLog(session, reason.paid, item_id.ToString(), -1 * item_count, 0, user[item_id], "sub", reason.reason, reason.sub_reason).ConfigureAwait(false);
            }

            return(true);
        }
        public static async Task <(ErrorCode, Goods, CharacterInfo)> UpgradePowerLevel(Session session, int character_id)
        {
            var character_data = ACDC.CharacterData[character_id];

            if (character_data == null || character_data == default(JCharacterData))
            {
                Log.Information($"UpgradePowerLevel cannot find character_id:{character_id}, user_name:{session.user_name}");
                return(ErrorCode.WrongParam, null, null);
            }

            var           level_table    = character_data.LevelTable;
            var           goods          = new Goods();
            CharacterInfo character_info = null;

            await using (var mylock = await RedLock.CreateLockAsync($"lock:session:{session.session_id}"))
            {
                await using (var user = await UserCache.GetUser(session.member_no, session.user_no, true, true, false))
                    await using (var character = await CharacterCache.Instance.GetEntity(session.member_no, session.user_no, character_id, true, true, false))
                    {
                        if (character == null || character == default(Models.Character))
                        {
                            Log.Information($"UpgradePowerLevel cannot find character_id:{character_id}, user_name:{session.user_name}");
                            return(ErrorCode.WrongParam, null, null);
                        }

                        JPowerLevel_TableData power_level_data;
                        if (level_table.TryGetValue(character.character_level, out power_level_data) == false)
                        {
                            return(ErrorCode.OverLimit, null, null);
                        }

                        if (character.piece < power_level_data.Req_Piece)
                        {
                            return(ErrorCode.NotEnough, null, null);
                        }

                        if (Inventory.UseGoods(session, user, power_level_data.Pricetype, power_level_data.Req_PriceValue, new LogReason("S_UPGRADE_SMASHER", character_id.ToString())) == false)
                        {
                            return(ErrorCode.NotEnough, null, null);
                        }

                        character.piece           -= power_level_data.Req_Piece;
                        character.character_level += 1;
                        character.IsDirty          = true;

                        goods.Set(user);

                        character_info = CharacterManager.CreateCharacterInfo(character, character_data);

                        var game_item_data = ACDC.GameItemData.Values.Where(x => x.Item_Type == (int)GameItemType.CharacterPiece && x.LinkId == character_id).FirstOrDefault();
                        var item_id        = game_item_data.id;
                        var item_count     = power_level_data.Req_Piece;
                        _ = LogProxy.writeItemLog(session, game_item_data.Item_Type.ToString(), item_id.ToString(), "y", "", item_count, "", 0, 0, "add", "S_UPGRADE_SMASHER", character_id.ToString(), "").ConfigureAwait(false);
                        _ = LogProxy.writeActionLog(session, "캐릭터", "업그레이드", character.character_type.ToString()).ConfigureAwait(false);

                        History.Info(session.member_no, session.user_no, session.character_no, HistoryLogAction.UseItem, (byte)HistoryLogReason.UpgradePowerLevel, item_id, item_count, "", "");
                    }
            }
            return(ErrorCode.Success, goods, character_info);
        }
Ejemplo n.º 4
0
        public override async Task SelectFirstCharacter(SelectFirstCharacterRequest request, IServerStreamWriter <SelectFirstCharacterReply> responseStream, ServerCallContext context)
        {
            var session = await context.GetSession();

            var user = await UserCache.GetUser(session.member_no, session.user_no, false);

            if (session == null || user == null)
            {
                await responseStream.WriteAsync(new SelectFirstCharacterReply()
                {
                    Code = ErrorCode.LostSession
                });

                return;
            }

            if (session.character_no != 0 || user.character_no != 0)
            {
                await responseStream.WriteAsync(new SelectFirstCharacterReply()
                {
                    Code = ErrorCode.NotAvailable
                });

                return;
            }

            if (!ACDC.CharacterSelectData[1].CharacterId.Contains(request.CharacterId))
            {
                await responseStream.WriteAsync(new SelectFirstCharacterReply()
                {
                    Code = ErrorCode.WrongParam
                });

                return;
            }

            var character = await CharacterManager.InsertCharacter(session.member_no, session.user_no, session.user_name, session.player_id, request.CharacterId);

            if (character == null)
            {
                await responseStream.WriteAsync(new SelectFirstCharacterReply()
                {
                    Code = ErrorCode.NotAvailable
                });

                return;
            }
            await UserCache.UpdateUserLock(session, session.user_no, character.character_no);

            await Session.UpdateSessionLock(session.session_id, delegate(Session s) { s.character_no = character.character_no; });

            History.Info(session.member_no, session.user_no, session.character_no, HistoryLogAction.GainItem, (byte)HistoryLogReason.SelectCharacter, character.character_type, 1, "", "");
            _ = LogProxy.writeActionLog(session, "캐릭터", "최초획득", character.character_type.ToString()).ConfigureAwait(false);

            await responseStream.WriteAsync(new SelectFirstCharacterReply()
            {
                Code = ErrorCode.Success, CharacterInfo = CharacterManager.CreateCharacterInfo(character, ACDC.CharacterData[character.character_type])
            });
        }
        public static async Task <bool> RestoreMatchUser(Session session, IServerStreamWriter <StartPlayReply> responseStream)
        {
            var(match_success, reply, match_id) = await RestoreMatchUser(session);

            if (match_success == false)
            {
                return(false);
            }
            History.Info(session.member_no, session.user_no, session.character_no, HistoryLogAction.StartPlay, (byte)HistoryLogReason.None, reply.CharacterList.Count, reply.MapId, match_id.ToString(), session.character_type.ToString());
            _ = LogProxy.writeActionLog(session, "플레이", "매칭성공", reply.MapId.ToString()).ConfigureAwait(false);

            await responseStream.WriteAsync(reply);

            return(true);
        }
Ejemplo n.º 6
0
        public static async Task <(ErrorCode, ItemList, Goods)> BuyItem(Session session, int shopItemId, int shopId)
        {
            var Item         = new ItemList();
            var AccountGoods = new Goods();

            // 상점 아이템 목록 체크
            var shop_item_data = ACDC.ShopItemListData[shopItemId];

            if (shop_item_data == null || shop_item_data == default(JShopItemListData))
            {
                return(ErrorCode.WrongParam, Item, AccountGoods);
            }

            var item_data = ACDC.GameItemData[shop_item_data.ItemId];

            if (item_data == null || item_data == default(JGameItemData))
            {
                return(ErrorCode.WrongParam, Item, AccountGoods);
            }

            await using (var mylock = await RedLock.CreateLockAsync($"lock:session:{session.session_id}"))
            {
                // 유저 상점 리스트 얻기
                var shops = await ShopCache.Instance.GetEntities(session.member_no, session.user_no, true);

                // 상점 목록 갱신
                await Refresh(session, shops, true);

                // 구매하려는 아이템 목록에 있는지 체크
                var shop_item = shops.Where(x => x.shop_id == shopId && x.shop_item_id == shopItemId).FirstOrDefault();
                if (shop_item == null || shop_item == default(Models.Shop))
                {
                    return(ErrorCode.NotExist, Item, AccountGoods);
                }

                // 구매 한정 체크
                if (shop_item.purchase_count >= shop_item_data.PurchaseLimitedCount)
                {
                    return(ErrorCode.OverLimit, Item, AccountGoods);
                }

                await using (var user = await UserCache.GetUser(session.member_no, session.user_no, true, true, false))
                    await using (var character = await CharacterCache.Instance.GetEntity(session.member_no, session.character_no, true, true, false))
                    {
                        // 지불 금액 체크 및 소모
                        if (shop_item_data.PriceType != 0 && shop_item_data.PriceType != (int)GameItemId.Cash) // 0은 무료
                        {
                            var reason     = "S_BUY_ITEM";
                            var sub_reason = "";
                            if (item_data.Item_Type == (int)GameItemType.CharacterPiece)
                            {
                                reason     = "S_BUY_SMASHER";
                                sub_reason = item_data.LinkId.ToString();
                            }
                            if (shop_item_data.ShopItemType == (int)ShopItemType.Goods)
                            {
                                reason     = "S_BUY_MONEY";
                                sub_reason = item_data.LinkId.ToString();
                            }

                            if (Inventory.UseGoods(session, user, shop_item_data.PriceType, shop_item_data.PriceValue * shop_item.quantity, new LogReason(reason, sub_reason)) == false)
                            {
                                return(ErrorCode.NotEnough, Item, AccountGoods);
                            }
                        }

                        // 아이템 지급
                        shop_item.purchase_count += 1;
                        await ShopCache.Instance.UpdateEntity(session.member_no, shop_item);

                        await Inventory.Insert(session, user, character, shop_item_data.ItemId, shop_item.quantity, new LogReason(shop_item_data.logName, shop_item_data.LinkId.ToString()), Item);

                        AccountGoods.Set(user);

                        if (shop_item_data.logName == "AD")
                        {
                            _ = LogProxy.writeActionLog(session, "광고시청", "광고", shop_item_data.LinkId.ToString()).ConfigureAwait(false);
                        }
                    }
            }

            return(ErrorCode.Success, Item, AccountGoods);
        }
Ejemplo n.º 7
0
        public static async Task <bool> Insert(Session session, Models.User user, Models.Character character, int item_id, int item_count, LogReason reason, GameService.ItemList item = null, string sParam1 = "", string sParam2 = "")
        {
            var game_item_data = ACDC.GameItemData[item_id];

            if (game_item_data == null || game_item_data == default(JGameItemData))
            {
                Log.Error($"cannot find item:{item_id}, user_name:{session.user_name}");
                return(false);
            }

            switch ((GameItemType)game_item_data.Item_Type)
            {
            case GameItemType.Goods:
            {
                user[item_id] += item_count;

                user.IsDirty = true;

                if (item != null)
                {
                    item.Items.Add(new GameService.ItemInfo()
                        {
                            ItemId = item_id, ItemCount = item_count
                        });
                }
            }
            break;

            case GameItemType.Medal_Charging:
            {
                user.medal_charge      = (int)MedalChargeConst.MaxCharge;
                user.medal_charge_time = DateTime.UtcNow;

                user.IsDirty = true;

                if (item != null)
                {
                    item.Items.Add(new GameService.ItemInfo()
                        {
                            ItemId = item_id, ItemCount = item_count
                        });
                }
            }
            break;

            case GameItemType.Character:
            {
                if (await CharacterManager.InsertCharacter(session.member_no, session.user_no, session.user_name, session.player_id, game_item_data.LinkId) == null)
                {
                    return(false);
                }

                if (item != null)
                {
                    item.Items.Add(new GameService.ItemInfo()
                        {
                            ItemId = item_id, ItemCount = item_count
                        });
                }

                _ = LogProxy.writeActionLog(session, "캐릭터", "획득", game_item_data.LinkId.ToString()).ConfigureAwait(false);
            }
            break;

            case GameItemType.CharacterPiece:
            {
                if (await CharacterManager.AddCharacterPiece(session, character, game_item_data.LinkId, item_count) == false)
                {
                    return(false);
                }

                if (item != null)
                {
                    item.Items.Add(new GameService.ItemInfo()
                        {
                            ItemId = item_id, ItemCount = item_count
                        });
                }

                _ = LogProxy.writeActionLog(session, "캐릭터", "조각획득", game_item_data.LinkId.ToString()).ConfigureAwait(false);
            }
            break;

            case GameItemType.Gacha:
            {
                if (await GachaBox.Progress(session, user, character, game_item_data, item, reason) == false)
                {
                    return(false);
                }
            }
            break;

            default:
                return(false);
            }

            await MissionManager.OnTrigger(session, MissionUserAction.GetItem, item_id, item_count);

            //History.Info(session.member_no, session.user_no, session.character_no, HistoryLogAction.GainItem, (byte)reason, (int)item_id, (int)item_count, sParam1, sParam2);

            if (reason != null)
            {
                if ((GameItemType)game_item_data.Item_Type == GameItemType.Goods)
                {
                    _ = LogProxy.writeResourceLog(session, reason.paid, item_id.ToString(), item_count, 0, user[item_id], "add", reason.reason, reason.sub_reason).ConfigureAwait(false);
                }
                else
                {
                    _ = LogProxy.writeItemLog(session, game_item_data.Item_Type.ToString(), item_id.ToString(), "y", "", item_count, "", 0, 0, "add", reason.reason, reason.sub_reason, "").ConfigureAwait(false);
                }
            }

            return(true);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// 게임 결과 기다림
        /// </summary>
        /// <param name="session"></param>
        /// <param name="request"></param>
        /// <param name="responseStream"></param>
        /// <returns></returns>
        public static async Task WaitGameResult(Session session, string channel_id, JMapData map_data, JGameModeData game_mode)
        {
            string key = $"game_result:{channel_id}";

            Log.Information($"WaitGameResult {key}");

            Interlocked.Increment(ref RankMatchmaking.MatchCount);

            var queue = Cache.Instance.GetSubscriber().Subscribe(key);

            var cts = new CancellationTokenSource();

            cts.CancelAfter((int)game_result_expire.TotalMilliseconds);
            try
            {
                var ret = await queue.ReadAsync(cts.Token);

                Interlocked.Decrement(ref RankMatchmaking.MatchCount);

                ServerCommon.GameResult reply = JsonConvert.DeserializeObject <ServerCommon.GameResult>(ret.Message);

                Log.Information($"game result {ret.Message.ToString()}");

                int total_win_medal    = 0;
                int total_lose_medal   = 0;
                int total_draw_medal   = 0;
                int total_mvp_medal    = 0;
                int total_rankup_medal = 0;
                await Match.RemoveMatch(reply.match_id);

                var characterNames  = new List <string>();
                var characterLevels = new List <int>();


                foreach (var player in reply.player_result)
                {
                    if (player.Value.IsLeave)
                    {
                        continue;
                    }

                    var last_session = await Session.GetSession(player.Key, false);

                    if (last_session != null)
                    {
                        bool is_changed_character_rank_level = false;
                        await using (var mylock = await RedLock.CreateLockAsync($"lock:session:{last_session.session_id}"))
                        {
                            await using (var user = await UserCache.GetUser(last_session.member_no, last_session.user_no, true, true, true))
                                await using (var character = await CharacterCache.Instance.GetEntity(last_session.member_no, last_session.character_no, true, true, true))
                                {
                                    user.play_point += player.Value.play_point;
                                    var last_account_battle_score = user.battle_score;
                                    UserGrowth.IncreaseBattleScore(user, player.Value.battle_point);
                                    var last_battle_score = character.battle_score;
                                    var last_rank_level   = character.rank_level;
                                    CharacterGrowth.IncreaseBattleScore(character, player.Value.battle_point);

                                    var(abs, cbs, wc) = await Ranking.Update(last_session, reply.season_no, player.Value.battle_point, player.Value.IsWin);

                                    bool is_character_rank_level_up = false;
                                    if (last_rank_level != character.rank_level)
                                    {
                                        if (last_rank_level < character.rank_level)
                                        {
                                            is_character_rank_level_up = true;
                                        }
                                    }

                                    if (last_battle_score != character.battle_score)
                                    {
                                        var rankData = ACDC.RankData.GetRank(character.battle_score);
                                        if (rankData != null)
                                        {
                                            if (last_session.rank != rankData.Rank)
                                            {
                                                is_changed_character_rank_level = true;
                                                last_session.rank = rankData.Rank;
                                            }
                                        }
                                    }

                                    var last_medal  = user.medal;
                                    var medal_count = Medal.CalcMedal(user, last_session, reply.is_draw, player.Value, is_character_rank_level_up, game_mode, ref total_win_medal, ref total_lose_medal, ref total_draw_medal, ref total_mvp_medal, ref total_rankup_medal);
                                    await Inventory.Insert(last_session, user, character, (int)GameItemId.Medal, medal_count, null);


                                    // 배틀에서 넘어온 미션 데이터가 없는 경우 초기화
                                    if (player.Value.missions == null)
                                    {
                                        player.Value.missions = new Dictionary <int, int>();
                                    }
                                    player.Value.missions.Increment((int)MissionType.Mission_GetMedal, medal_count);

                                    await MissionManager.Progress(last_session, player.Value.missions);

                                    History.Info(last_session.member_no, last_session.user_no, last_session.character_no, HistoryLogAction.GainAccountBattleScore, (byte)HistoryLogReason.GameResultReward, (int)user.battle_score, (int)last_account_battle_score, reply.match_id.ToString(), "");
                                    History.Info(last_session.member_no, last_session.user_no, last_session.character_no, HistoryLogAction.GainCharacterBattleScore, (byte)HistoryLogReason.GameResultReward, (int)character.battle_score, (int)last_battle_score, reply.match_id.ToString(), "");

                                    characterNames.Add(last_session.user_name);
                                    characterLevels.Add(character.rank_level);
                                }
                        }

                        //Log.Information($"session:{last_session.session_id}, rank:{last_session.rank}");
                        if (is_changed_character_rank_level)
                        {
                            await Session.UpdateSessionLock(last_session.session_id, delegate(Session s) { s.rank = last_session.rank; });
                        }


                        // 게임 종료 이후 매칭 정보 삭제
                        await MatchUser.RemoveMatchUser(last_session.user_no);
                    }
                    else
                    {
                        Log.Warning($"game result lost session:{player.Key}, msg:{ret.Message}");
                    }
                }

                MatchLog.Info(reply, total_win_medal, total_lose_medal, total_draw_medal, total_mvp_medal, total_rankup_medal);

                string resultTp;
                if (reply.is_draw)
                {
                    resultTp = "26";
                    _        = LogProxy.writeActionLog(session, "플레이", "무승부", map_data.ID.ToString()).ConfigureAwait(false);
                }
                else if (reply.statistics.clear == 1)
                {
                    resultTp = "21";
                    _        = LogProxy.writeActionLog(session, "플레이", "클리어", map_data.ID.ToString()).ConfigureAwait(false);
                }
                else
                {
                    resultTp = "22";
                }

                _ = LogProxy.writeRoundLog(session, game_mode.Name, "", "", resultTp, 0, reply.statistics.start_time, reply.statistics.end_time, characterNames, characterLevels, "").ConfigureAwait(false);


                if (reply.statistics.leave_player > 0)
                {
                    _ = LogProxy.writeActionLog(session, "플레이", "이탈", map_data.ID.ToString(), reply.statistics.leave_player.ToString()).ConfigureAwait(false);
                }

                if (reply.statistics.normal_item > 0)
                {
                    _ = LogProxy.writeActionLog(session, "플레이", "일반아이템획득", map_data.ID.ToString(), reply.statistics.normal_item.ToString()).ConfigureAwait(false);
                }

                if (reply.statistics.tactic_item > 0)
                {
                    _ = LogProxy.writeActionLog(session, "플레이", "전략아이템획득", map_data.ID.ToString(), reply.statistics.tactic_item.ToString()).ConfigureAwait(false);
                }
            }
            catch (OperationCanceledException ex)
            {
                Log.Information($"game result timeout {ex.ToString()}");
            }
        }
        public static async Task StartPlay(StartPlayRequest request, IServerStreamWriter <StartPlayReply> responseStream, ServerCallContext context)
        {
            var mapData = ACDC.MapData[request.MapId];

            if (mapData == null)
            {
                Log.Warning($"StartPlay error map id {request.MapId}");
                await responseStream.WriteAsync(new StartPlayReply()
                {
                    Code = ErrorCode.WrongParam
                });

                return;
            }

            var gameModeData = ACDC.GameModeData[mapData.GameMode];

            if (gameModeData == null)
            {
                Log.Warning($"StartPlay error mode {mapData.GameMode}");
                await responseStream.WriteAsync(new StartPlayReply()
                {
                    Code = ErrorCode.WrongParam
                });

                return;
            }

            MinimumStartPlay minimumStartPlay;

            minimumStartPlayMap.TryGetValue(request.MapId, out minimumStartPlay);

            var session = await context.GetSession();

            if (session == null)
            {
                await responseStream.WriteAsync(new StartPlayReply()
                {
                    Code = ErrorCode.LostSession
                });

                return;
            }

            Log.Information($"StartPlay user_no:{session.user_no}, user_name:{session.user_name}, mapId:{request.MapId}, SelectedCharacter:{request.SelectedCharacter}, IsImmediatelyJoin{request.IsImmediatelyJoin}");

            bool checkSelectCharacter = await session.SelectCharacter(request.SelectedCharacter);

            if (checkSelectCharacter == false)
            {
                Log.Warning($"StartPlay error character id {request.SelectedCharacter}");
                await responseStream.WriteAsync(new StartPlayReply()
                {
                    Code = ErrorCode.WrongParam
                });

                return;
            }

            bool IsAISwitch     = false;
            bool IsFirstRequest = false;
            bool IsWaitingUser  = await WaitingList.IsWaitingUser(session.user_no);

            bool IsMatchTimeout = false;

            // 이미 대기중이 였지만 요청이 달라진 경우,  최초 요청으로 판단
            if (IsWaitingUser == false || session.IsChangeRequest(request))
            {
                IsFirstRequest = true;
                History.Info(session.member_no, session.user_no, session.character_no, HistoryLogAction.TryStartPlay, (byte)HistoryLogReason.None, request.SelectedCharacter, request.MapId, "", "");
                _ = LogProxy.writeActionLog(session, "플레이", "매칭시도", request.MapId.ToString()).ConfigureAwait(false);
            }
            else
            {
                if (DateTime.UtcNow > session.first_request_time.AddMilliseconds(ServerConfiguration.Instance.gameSetting.AIMatchTime))
                {
                    IsMatchTimeout = true;
                    if (ServerConfiguration.Instance.gameSetting.EnableAIMatch == true)
                    {
                        IsAISwitch = true;
                    }
                }

                if (minimumStartPlay != null &&
                    minimumStartPlay.Enable &&
                    DateTime.UtcNow > session.first_request_time.AddSeconds(minimumStartPlay.Timeout))
                {
                    Log.Information($"matchTimeout first_request_time:{session.first_request_time}, now:{DateTime.UtcNow}, timeout:{session.first_request_time.AddSeconds(minimumStartPlay.Timeout)}");
                    IsMatchTimeout = true;
                }
            }

            Log.Information($"flag IsAISwitch:{IsAISwitch}, IsFirstRequest:{IsFirstRequest}, IsWaitingUser{IsWaitingUser}, IsMatchTimeout{IsMatchTimeout}");


            if (request.SelectedCharacter != session.character_type || request.MapId != session.map_id)
            {
                var user = await UserCache.GetUser(session.member_no, session.user_no, false);

                user.character_no = session.character_no;
                user.map_id       = (byte)request.MapId;
                user.IsDirty      = true;
            }

            // 게임 시작 요청 정보를 캐싱
            await session.UpdateSessionLock(request.SelectedCharacter, request.MapId, IsFirstRequest);

            if (request.IsImmediatelyJoin)
            {
                await StartPlaySimulate(request, responseStream, context, session, mapData, gameModeData);

                return;
            }

            long match_id = await MatchInstanceId.GetMatchInstanceId();

            if ((await MatchUser.OccupyMatchUser(session.user_no, match_id)) == false)
            {
                // 다른 플레이어로 인해 매칭이 완료 되었는지 확인
                if ((await RestoreMatchUser(session, responseStream)) == true)
                {
                    if (ServerConfiguration.Instance.gameSetting.EnableReJoin == false)
                    {
                        // 재입장이 불가하면, 게임 시작 직후 매칭 정보 삭제
                        await MatchUser.RemoveMatchUser(session.user_no);
                    }
                    return;
                }
                else
                {
                    await responseStream.WriteAsync(new StartPlayReply()
                    {
                        Code             = ErrorCode.NotEnough,
                        IsStart          = false,
                        BattleServerAddr = "",
                        WorldId          = 0,
                        MapId            = request.MapId,
                    });

                    return;
                }
            }

            if (request.IsCancel)
            {
                // 대기 목록에서 제거
                await WaitingList.RemoveWaitingUser(session.user_no);

                await MatchUser.RemoveMatchUser(session.user_no);


                await responseStream.WriteAsync(new StartPlayReply()
                {
                    Code             = ErrorCode.NotEnough,
                    IsStart          = false,
                    BattleServerAddr = "",
                    WorldId          = 0,
                    MapId            = request.MapId,
                });

                return;
            }

            // 대기중이 플레이어 찾기
            (var matchResult, var search_success) = await SearchPlayer(session, match_id, mapData, gameModeData);

            if (search_success == false && IsAISwitch == true)
            {
                // 부족한 인원 만큼 AI로 채워 넣는다.(자신은 제외)
                int cnt = (GetStartPlayerCount(gameModeData) - 1) - matchResult.replyToClient.CharacterList.Count;
                for (int i = 0; i < cnt; ++i)
                {
                    matchResult.AddAI(session, mapData, gameModeData);
                }
            }

            if (search_success == true || IsAISwitch == true ||
                (ServerConfiguration.Instance.gameSetting.MatchForce && IsMatchTimeout) ||
                (minimumStartPlay != null && minimumStartPlay.Enable && IsMatchTimeout && matchResult.replyToClient.CharacterList.Count + 1 >= minimumStartPlay.PlayerCount)
                )
            {
                // 게임 시작
                if ((await StartPlay(match_id, session, request, responseStream, matchResult, mapData, gameModeData)) == false)
                {
                    // 예약했던 플레이어 취소
                    await MatchUser.CancelOccupiedMatchUser(matchResult.replyToBattleServer.players);
                }
                else
                {
                    if (ServerConfiguration.Instance.gameSetting.EnableReJoin == false)
                    {
                        // 재입장이 불가하면, 게임 시작 직후 매칭 정보 삭제
                        await MatchUser.RemoveMatchUser(session.user_no);
                    }
                }
                return;
            }

            // 예약했던 플레이어 취소
            await MatchUser.CancelOccupiedMatchUser(matchResult.replyToBattleServer.players);

            Log.Information("StartPlay waiting... {0}", session.user_no);

            // 대기
            await WaitStartPlay(session, request, responseStream);

            // 검색 실패시 다음 검색 조건 범위를 넓힌다.
            await session.WideningRangeRankLock();

            // 실패 결과 리턴
            matchResult.replyToClient.Code    = ErrorCode.NotEnough;
            matchResult.replyToClient.IsStart = false;
            matchResult.replyToClient.CharacterList.Add(new StartPlayCharacterInfo()); // 자신포함으로 빈슬롯 한개 넣어줌
            await responseStream.WriteAsync(matchResult.replyToClient);
        }
        public static async Task <bool> StartPlay(long match_id, Session session, StartPlayRequest request, IServerStreamWriter <StartPlayReply> responseStream, MatchResult matchResult, JMapData map_data, JGameModeData game_mode)
        {
            // 매칭에 필요한 인원을 모두 찾았을때
            // 전투 가능한 서버를 찾아 세팅
            (bool ret, string server_addr, byte worldId, string channel_key, string channel_id) = await Channel.GetAvailableServer(request.MapId);

            if (ret == false)
            {
                // 전투 가능한 서버가 없다
                Log.Error($"Cannot find Server user_no:{session.user_no}");
                await responseStream.WriteAsync(new StartPlayReply()
                {
                    Code = ErrorCode.BusyServer
                });

                return(false);
            }

            if (await matchResult.AddPlayer(session, map_data, game_mode) == false)
            {
                Log.Error($"StartPlay error user_no:{session.user_no}");
                await responseStream.WriteAsync(new StartPlayReply()
                {
                    Code = ErrorCode.NotEnough
                });

                return(false);
            }

            await matchResult.Finish(worldId, server_addr, channel_id, game_mode);

            // 매칭된 유저들에게 알림
            await Match.SaveMatch(match_id, matchResult.replyToClient);

            // 대기 목록에서 삭제
            foreach (var p in matchResult.replyToBattleServer.players.Values)
            {
                await WaitingList.RemoveWaitingUser(p.user_no);
            }


            // 배틀서버에 알림
            await PubStartPlay(matchResult.replyToBattleServer);

            Log.Information($"StartPlay {session.user_no}, channel_msg:{channel_key}");

            // 게임 시작 요청에 대한 응답 전송
            await responseStream.WriteAsync(matchResult.replyToClient);

            // 매칭이 성공적으로 이루어졌으므로 이후 매칭 결과를 pub/sub으로 전달 받는다.


            _ = GameResult.WaitGameResult(session, channel_id, map_data, game_mode).ConfigureAwait(false);

            History.Info(session.member_no, session.user_no, session.character_no, HistoryLogAction.StartPlay, (byte)HistoryLogReason.None, matchResult.replyToBattleServer.players.Count, matchResult.replyToClient.MapId, match_id.ToString(), session.character_type.ToString());
            _ = LogProxy.writeActionLog(session, "플레이", "매칭성공", matchResult.replyToClient.MapId.ToString()).ConfigureAwait(false);


            var characterNames  = new List <string>();
            var characterLevels = new List <int>();

            foreach (var player in matchResult.replyToBattleServer.players)
            {
                characterNames.Add(player.Value.user_id);
                characterLevels.Add(player.Value.character_level);
            }

            _ = LogProxy.writeRoundLog(session, game_mode.Name, "", "", "10", 0, 0, 0, characterNames, characterLevels, "").ConfigureAwait(false);

            return(true);
        }
Ejemplo n.º 11
0
        public override async Task <GameService.RewardAdvertisementReply> RewardAdvertisement(RewardAdvertisementRequest request, ServerCallContext context)
        {
            try
            {
                var session = await context.GetSession();

                if (session == null)
                {
                    return(new RewardAdvertisementReply()
                    {
                        Code = ErrorCode.LostSession
                    });
                }

                var adData = ACDC.AdListData[request.AdvertisementId];
                if (adData == null || adData == default(JAdListData))
                {
                    return(new RewardAdvertisementReply()
                    {
                        Code = ErrorCode.WrongParam
                    });
                }

                bool is_insert = false;

                var reply = new RewardAdvertisementReply();
                reply.AccountGoods = new Goods();
                reply.Item         = new ItemList();
                var currentTime = DateTime.UtcNow;
                int RewardCount = 0;
                await using (var mylock = await RedLock.CreateLockAsync($"lock:session:{session.session_id}"))
                {
                    var rewards = await AdvertisementRewardQuery.Gets(session.member_no, session.user_no);

                    var reward = rewards.Where(x => x.advertisement_id == request.AdvertisementId).FirstOrDefault();
                    if (reward == null || reward == default(Models.AdvertisementReward))
                    {
                        is_insert = true;
                        reward    = new AdvertisementReward()
                        {
                            user_no          = session.user_no,
                            advertisement_id = adData.Id,
                            reward           = 0,
                            occ_time         = currentTime,
                        };
                    }
                    else
                    {
                        // refresh
                        if (core.MathHelpers.GetResetTime(adData.ResetTime, reward.occ_time) != core.MathHelpers.GetResetTime(adData.ResetTime, currentTime))
                        {
                            reward.occ_time = currentTime;
                            reward.reward   = 0;
                        }
                    }

                    if (reward.reward >= adData.ViewLimit)
                    {
                        return(new RewardAdvertisementReply()
                        {
                            Code = ErrorCode.OverLimit
                        });
                    }

                    // 보상 지급
                    await using (var user = await UserCache.GetUser(session.member_no, session.user_no, true, true, false))
                        await using (var character = await CharacterCache.Instance.GetEntity(session.member_no, session.character_no, true, true, false))
                        {
                            await Inventory.Insert(session, user, character, adData.ItemId, adData.Count, new LogReason("A_AD", adData.Id.ToString()), reply.Item, null, adData.Id.ToString());

                            reply.AccountGoods.Set(user);
                        }

                    ++reward.reward;
                    RewardCount     = reward.reward;
                    reward.occ_time = currentTime;
                    if (is_insert)
                    {
                        await AdvertisementRewardQuery.Add(session.member_no, reward);
                    }
                    else
                    {
                        await AdvertisementRewardQuery.Update(session.member_no, reward);
                    }

                    _ = LogProxy.writeActionLog(session, "광고시청", "광고", adData.Id.ToString()).ConfigureAwait(false);
                }

                reply.Code            = ErrorCode.Success;
                reply.RewardCount     = RewardCount;
                reply.AdvertisementId = request.AdvertisementId;
                return(reply);
            }
            catch (Exception ex)
            {
                Log.Error($"GetRewardEvent {ex.ToString()}");

                return(new RewardAdvertisementReply()
                {
                    Code = ErrorCode.WrongParam
                });
            }
        }