public static void CancelMatchmaking(Session session) { // 메시지 핸들러 함수는 세션 ID 를 이벤트 태그로 하는 이벤트 위에서 실행합니다. // 아래는 이 함수를 메시지 핸들러 위에서 실행하게 강제하게 검사하는 식입니다. // 세션 ID 별로 이 함수를 직렬화하지 않으면 동시에 서로 다른 곳에서 // 이 세션에 접근할 수 있습니다. Log.Assert(Event.GetCurrentEventTag() == session.Id); JObject context = session.Context; if (context[kMatchHistory] == null || context[kMatchHistory].Type != JTokenType.Object) { // 매칭을 요청한 적이 없습니다. 종료합니다. return; } Log.Assert(context[kMatchHistory][kAccountId] != null && context[kMatchHistory][kAccountId].Type == JTokenType.String); Log.Assert(context[kMatchHistory][kMatchType] != null && context[kMatchHistory][kMatchType].Type == JTokenType.Integer); string account_id = context[kMatchHistory][kAccountId].Value <string>(); long match_type = context[kMatchHistory][kMatchType].Value <long>(); funapi.Matchmaking.Client.CancelCallback cancel_callback = new funapi.Matchmaking.Client.CancelCallback( (string account_id2, funapi.Matchmaking.CancelResult result) => { // 아무것도 하지 않습니다. }); Log.Info("Canceling matchmaking(with session context): session_id={0}, account_id={1}, match_type={2}", session.Id, account_id, match_type); funapi.Matchmaking.Client.Cancel(match_type, account_id, cancel_callback); }
// 세션을 정리합니다. public static void FreeUser(Session session) { // 유저를 정리하기 위한 Context 를 읽어옵니다. string matching_state; string id; session.GetFromContext("matching", out matching_state); session.GetFromContext("id", out id); // Session Context 를 초기화 합니다. session.Context = new JObject(); // 로그아웃하고 세션을 종료합니다. if (id != string.Empty) { AccountManager.LogoutCallback logout_cb = (string param_account_id, Session param_session, bool param_result) => { Log.InfoIf(param_result, "Logged out(local) by session close: id={0}", param_account_id); }; AccountManager.SetLoggedOutAsync(id, logout_cb); } // 매치메이킹이 진행 중이면 취소합니다. if (matching_state == "doing") { // Matchmaking cancel 결과를 처리할 람다 함수입니다. funapi.Matchmaking.Client.CancelCallback cancel_cb = (string player_id, funapi.Matchmaking.CancelResult result) => { if (result == funapi.Matchmaking.CancelResult.kSuccess) { Log.Info("Succeed to cancel matchmaking by session close: id={0}", id); } else { Log.Info("Failed to cancel matchmaking by session close: id={0}", id); } }; funapi.Matchmaking.Client.Cancel((long)MatchmakingType.kMatch1vs1, id, cancel_cb); } }
private static void CancelMatchmaking(Session session, Session.EncodingScheme encoding) { // 로그인 한 Id 를 가져옵니다. string id; if (!session.GetFromContext("id", out id)) { Log.Warning("Failed to cancel matchmaking. Not logged in."); if (encoding == Session.EncodingScheme.kJsonEncoding) { session.SendMessage("error", Utility.MakeResponse("fail", "not logged in")); } else { Log.Assert(encoding == Session.EncodingScheme.kProtobufEncoding); FunMessage funmsg = new FunMessage(); PongErrorMessage msg = new PongErrorMessage(); msg.result = "fail"; msg.msg = "not logged in"; funmsg.AppendExtension_pong_error(msg); session.SendMessage("error", funmsg); } return; } // 매치메이킹 취소 상태로 변경합니다. session.AddToContext("matching", "cancel"); funapi.Matchmaking.Client.CancelCallback cancel_cb = (string player_id, funapi.Matchmaking.CancelResult result) => { if (encoding == Session.EncodingScheme.kJsonEncoding) { JObject response = new JObject(); if (result == funapi.Matchmaking.CancelResult.kSuccess) { Log.Info("Succeed to cancel matchmaking: id={0}", player_id); response = Utility.MakeResponse("Cancel"); } else if (result == funapi.Matchmaking.CancelResult.kNoRequest) { response = Utility.MakeResponse("NoRequest"); } else { response = Utility.MakeResponse("Error"); } session.SendMessage("match", response, Session.Encryption.kDefault); } else { Log.Assert(encoding == Session.EncodingScheme.kProtobufEncoding); FunMessage funmsg = new FunMessage(); LobbyMatchReply reply = new LobbyMatchReply(); if (result == funapi.Matchmaking.CancelResult.kSuccess) { Log.Info("Succeed to cancel matchmaking: id={0}", player_id); reply.result = "Cancel"; } else if (result == funapi.Matchmaking.CancelResult.kNoRequest) { reply.result = "NoRequest"; } else { reply.result = "Error"; } funmsg.AppendExtension_lobby_match_repl(reply); session.SendMessage("match", funmsg, Session.Encryption.kDefault); } }; funapi.Matchmaking.Client.Cancel((int)MatchmakingType.kMatch1vs1, id, (_1, _2) => { cancel_cb(_1, _2); }); }
public static void CancelMatchmaking( Session session, JObject message, SessionResponse.SessionResponseHandler handler) { // 메시지 핸들러 함수는 세션 ID 를 이벤트 태그로 하는 이벤트 위에서 실행합니다. // 아래는 이 함수를 메시지 핸들러 위에서 실행하게 강제하게 검사하는 식입니다. // 세션 ID 별로 이 함수를 직렬화하지 않으면 동시에 서로 다른 곳에서 // 이 세션에 접근할 수 있습니다. Log.Assert(Event.GetCurrentEventTag() == session.Id); // 클라이언트는 다음 메시지 형태로 매치메이킹 취소를 요청합니다. // { // "account_id": "id", // "match_type": 1 // } if (message[kAccountId] == null || message[kAccountId].Type != JTokenType.String || message[kMatchType] == null || message[kMatchType].Type != JTokenType.Integer) { Log.Error("Missing required fields: '{0}' / '{1}': session_id={2}, message={3}", kAccountId, kMatchType, session.Id, message.ToString()); handler(SessionResponse.ResponseResult.FAILED, new SessionResponse(session, 400, "Missing required fields.", new JObject())); return; } // 매치 타입 long match_type = message[kMatchType].Value <long>(); if (!MatchmakingType.IsValidMatchType(match_type)) { Log.Error("Invalid match_type: session_id={0}, message={1}", session.Id, message.ToString()); handler(SessionResponse.ResponseResult.FAILED, new SessionResponse(session, 400, "Invalid arguments.", new JObject())); return; } if (match_type == (long)MatchmakingType.MatchType.kNoMatching) { // 매치메이킹 기능을 쓰지 않으므로 취소 처리한다. handler(SessionResponse.ResponseResult.OK, new SessionResponse(session, 200, "OK.", new JObject())); } // 계정 string account_id = message[kAccountId].Value <string>(); // 요청한 계정과 로그인 중인 세션이 일치하는 지 검사합니다. // 이 검사를 통해 다른 유저 ID 로 매칭을 취소하는 행위를 방지할 수 있습니다. if (AccountManager.FindLocalSession(account_id).Id != session.Id) { Log.Info("CancelMatchmaking denied: bad request: session_id={0}, message={1}", session.Id, message.ToString()); handler(SessionResponse.ResponseResult.FAILED, new SessionResponse(session, 400, "Access denied for this account.", new JObject())); return; } funapi.Matchmaking.Client.CancelCallback cancel_callback = new funapi.Matchmaking.Client.CancelCallback( (string account_id2, funapi.Matchmaking.CancelResult result2) => { if (result2 != funapi.Matchmaking.CancelResult.kSuccess) { // kCRNoRequest (요청하지 않은 매치) 또는 // kCRError (엔진 내부 에러)가 올 수 있습니다. handler(SessionResponse.ResponseResult.FAILED, new SessionResponse(session, 500, "Internal server error.", new JObject())); } else { handler(SessionResponse.ResponseResult.OK, new SessionResponse(session, 200, "OK.", new JObject())); } }); Log.Info("Canceling matchmaking: session_id={0}, account_id={1}, match_type={2}", session.Id, account_id, match_type); funapi.Matchmaking.Client.Cancel(match_type, account_id, cancel_callback); }