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); }
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; } }
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); }
/// <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); }