Esempio n. 1
0
        public void Init(int map_id, long match_id, int player_count)
        {
            // 이전에 등록했던 시작 이벤트 초기화
            OnStart = null;

            // 게임 시작 이벤트 등록
            foreach (var gameObject in World.Instance(WorldId).GetGameObjects())
            {
                if (gameObject.GetClassId() == (byte)GameObjectClassId.Trap)
                {
                    RegisterStartEvent(((Trap)gameObject).OnStart);
                }
                else if (gameObject.GetClassId() == (byte)GameObjectClassId.TreasureBox)
                {
                    RegisterStartEvent(((TreasureBox)gameObject).OnStart);
                }
                else if (gameObject.GetClassId() == (byte)GameObjectClassId.Train)
                {
                    RegisterStartEvent(((Train)gameObject).OnStart);
                }
            }


            mMapData            = ACDC.MapData[map_id];
            mGameModeData       = ACDC.GameModeData[mMapData.GameMode];
            game_mode           = CreateGameMode((GameModeType)mGameModeData.ID);
            mMatchId            = match_id;
            StartTime           = Timing.sInstance.GetFrameStartTime();
            state               = GameModeState.Init;
            InitTime            = Timing.sInstance.GetFrameStartTime();
            ReservedPlayerCount = player_count;
        }
        public void AddAI(Session session, JMapData map_data, JGameModeData game_mode)
        {
            var spawn = JsonData.Instance.SpawnPositions[map_data.ID];

            string session_id = Session.GetNewSessionId();
            // todo : AI 닉네임 설정이 필요.
            // 현재 응답에서 중복만 되지 않으면 문제가 없을 것으로 보임
            string user_id = session_id;

            var player = new ServerCommon.PlayerInfo()
            {
                user_no         = session.user_no,
                character_type  = session.character_type,
                user_id         = user_id,
                team            = (byte)spawn[replyToBattleServer.players.Count].spawnTeam,
                is_ai           = true,
                player_id       = replyToBattleServer.players.Count + 1,
                spawn_index     = replyToBattleServer.players.Count,
                character_level = 1,
            };

            replyToBattleServer.players.Add(session_id, player);
            replyToClient.CharacterList.Add(new StartPlayCharacterInfo()
            {
                SelectedCharacter = session.character_type, UserId = user_id, Team = player.team, PlayerId = player.player_id, SpawnIndex = player.spawn_index
            });
        }
        static int GetStartPlayerCount(JGameModeData game_mode)
        {
            if (StartPlayerCount != 0)
            {
                return(StartPlayerCount);
            }

            return(game_mode.PlayerCount);
        }
Esempio n. 4
0
        public override void Read(NetIncomingMessage inInputStream)
        {
            bool stateBit;

            //Debug.Log($"GameMode read");

            stateBit = inInputStream.ReadBoolean();
            if (stateBit)
            {
                mEntries.Clear();
                int entryCount = inInputStream.ReadInt32();
                //just replace everything that's here, it don't matter...
                for (int i = 0; i < entryCount; ++i)
                {
                    var entry = new core.Entry();
                    entry.Read(inInputStream);
                    mEntries.Add(entry);
                }
            }

            stateBit = inInputStream.ReadBoolean();
            if (stateBit)
            {
                var mode = (core.GameModeType)inInputStream.ReadUInt32(MaxGameModeTypeBits);
                game_mode = CreateGameMode(mode);
                game_mode.Read(inInputStream);
                mGameModeData = ACDC.GameModeData[(int)mode];
            }

            stateBit = inInputStream.ReadBoolean();
            if (stateBit)
            {
                state = (GameModeState)inInputStream.ReadUInt32(MaxGameModeStateBits);
                if (state == GameModeState.End)
                {
                    game_mode.ReadGameResult(inInputStream, this);
                    OnGameEnd();
                }
                //Debug.Log($"GameMode state {state}");
            }

            stateBit = inInputStream.ReadBoolean();
            if (stateBit)
            {
                // 최대 RTT 보정
                if (NetworkManager.Instance.GetRoundTripTimeClientSide() > 1f)
                {
                    StartTime = core.Timing.sInstance.GetFrameStartTime() + inInputStream.ReadFloat() - (1f * 0.5f);
                }
                else
                {
                    StartTime = core.Timing.sInstance.GetFrameStartTime() + inInputStream.ReadFloat() - (NetworkManager.Instance.GetRoundTripTimeClientSide() * 0.5f);
                }
                Debug.Log($"GameMode Start StartTime:{StartTime}, RemainTime:{RemainTime}, timestamp:{core.Timing.sInstance.GetFrameStartTime()}, RTT:{NetworkManager.Instance.GetRoundTripTimeClientSide()}");
                IsSetPlayTime = true;
            }
        }
        public async Task <bool> AddPlayer(Session session, JMapData map_data, JGameModeData game_mode)
        {
            if (replyToBattleServer.players.ContainsKey(session.session_id))
            {
                Log.Error($"AddPlayer duplicate session_id:{session.session_id}");
                return(false);
            }

            List <JSpawnData> spawn;

            if (JsonData.Instance.SpawnPositions.TryGetValue(map_data.ID, out spawn) == false)
            {
                Log.Error($"AddPlayer cannot find map_id:{map_data.ID}");
                return(false);
            }
            if (spawn.Count <= replyToBattleServer.players.Count)
            {
                Log.Error($"AddPlayer cannot find spawn index:{replyToBattleServer.players.Count}, size:{spawn.Count}");
                return(false);
            }
            var team = (byte)spawn[replyToBattleServer.players.Count].spawnTeam;

            int characterLevel = 0;
            var character      = await CharacterCache.Instance.GetEntity(session.member_no, session.character_no, true, false, false);

            if (character != null && character != default(Models.Character))
            {
                characterLevel = character.character_level;
            }

            var player = new ServerCommon.PlayerInfo()
            {
                user_no         = session.user_no,
                character_type  = session.character_type,
                user_id         = session.user_name,
                team            = (byte)team,
                player_id       = replyToBattleServer.players.Count + 1,
                spawn_index     = replyToBattleServer.players.Count,
                character_level = characterLevel,
            };

            replyToBattleServer.players.Add(session.session_id, player);
            replyToClient.CharacterList.Add(new StartPlayCharacterInfo()
            {
                SelectedCharacter = session.character_type, UserId = session.user_name, Team = player.team, PlayerId = player.player_id, SpawnIndex = player.spawn_index
            });
            return(true);
        }
        public void SetModeData(JGameModeData game_mode)
        {
            switch (game_mode.ID)
            {
            case (int)core.GameModeType.KillTheKing:
                int playerId_A = core.KillTheKing.GetNextKingPlayerId(replyToBattleServer.players.Values.Where(x => x.team == (byte)core.Team.TeamA).Select(x => x.player_id).ToList());
                int playerId_B = core.KillTheKing.GetNextKingPlayerId(replyToBattleServer.players.Values.Where(x => x.team == (byte)core.Team.TeamB).Select(x => x.player_id).ToList());
                replyToBattleServer.kill_the_king_info = new ServerCommon.KillTheKingInfo()
                {
                    king_player_id_A = playerId_A,
                    king_player_id_B = playerId_B
                };

                replyToClient.KillTheKingInfo = new KillTheKingInfo();
                replyToClient.KillTheKingInfo.KingPlayerIdForTeamA = playerId_A;
                replyToClient.KillTheKingInfo.KingPlayerIdForTeamB = playerId_B;

                break;
            }
        }
Esempio n. 7
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);
        }
Esempio 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 async Task Finish(byte world_id, string server_addr, string channel_id, JGameModeData game_mode)
        {
            replyToBattleServer.world_id   = world_id;
            replyToBattleServer.channel_id = channel_id;

            replyToClient.BattleServerAddr = server_addr;
            replyToClient.WorldId          = world_id;

            Complete();

            foreach (var player in replyToBattleServer.players)
            {
                var msg = new ServerCommon.PlayerLocation()
                {
                    channel_id = channel_id,
                    world_id   = world_id,
                    player_id  = player.Value.player_id,
                };

                await Cache.Instance.GetDatabase().StringSetAsync($"player:{player.Key}", JsonConvert.SerializeObject(msg), new TimeSpan(0, 15, 0));
            }
            SetModeData(game_mode);
        }
        public static async Task <(MatchResult, bool)> SearchPlayer(Session session, long match_id, JMapData map_data, JGameModeData game_mode)
        {
            bool result      = false;
            var  matchResult = new MatchResult(match_id, session.map_id);

            if (GetStartPlayerCount(game_mode) <= 1)
            {
                return(matchResult, true);
            }

            Session other_session = null;
            var     seq           = new RankSequencer()
            {
                rank = session.rank, min_rank = session.min_rank, max_rank = session.max_rank
            };

            foreach (var rank in seq)
            {
                var users = await WaitingList.GetWaitingUser(session.map_id, rank, defaultGetWaitingUser);

                for (int i = 0; i < users.Count; ++i)
                {
                    //Log.Information($"searching... waiting user : {users[i]}, rank : {rank}");

                    // 자신은 스킵
                    if (users[i] == session.user_no)
                    {
                        continue;
                    }

                    if ((other_session = await Session.GetSession(users[i], false)) == null // 대기중 유저 세션 만료
                        )
                    {
                        Log.Information("cannot find Session {0}", users[i]);
                        await WaitingList.RemoveWaitingUser(users[i]);

                        continue;
                    }

                    if (other_session.rank != rank)
                    {
                        continue;
                    }

                    if (await MatchUser.OccupyMatchUser(users[i], match_id) == false)
                    {
                        continue;
                    }

                    if (await matchResult.AddPlayer(other_session, map_data, game_mode) == false)
                    {
                        Log.Error($"SearchPlayer error user_no:{session.user_no}");
                        continue;
                    }

                    Log.Information($"Candidate User {other_session.user_no}");

                    if (matchResult.replyToBattleServer.players.Count == GetStartPlayerCount(game_mode) - 1)
                    {
                        result = true;
                        return(matchResult, result);
                    }
                }
            }

            return(matchResult, result);
        }
        public static async Task StartPlaySimulate(StartPlayRequest request, IServerStreamWriter <StartPlayReply> responseStream, ServerCallContext context, Session session, 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;
            }

            long match_id = await MatchInstanceId.GetMatchInstanceId();


            var matchResult = new MatchResult(match_id, request.MapId);

            if (await matchResult.AddPlayer(session, map_data, game_mode) == false)
            {
                await responseStream.WriteAsync(new StartPlayReply()
                {
                    Code = ErrorCode.NotEnough
                });

                return;
            }

            if (ServerConfiguration.Instance.gameSetting.EnableAIMatch)
            {
                matchResult.AddAI(session, map_data, game_mode);
            }
            await matchResult.Finish(worldId, server_addr, channel_id, game_mode);


            await responseStream.WriteAsync(matchResult.replyToClient);

            await PubStartPlay(matchResult.replyToBattleServer);


            _ = GameResult.WaitGameResult(session, channel_id, map_data, game_mode).ConfigureAwait(false);
        }
        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);
        }