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