완성 코드 분석 - 서버 / UI(2)
저번에 코드 분석을 너무 세세하게 작성하느라 시간이 많이 소요되어서, 이번에는 이해한 흐름은 간단하게 기록하고 넘어가려고 한다.
지난번에 이어서 FindServers() 함수의 흐름을 분석할 것이다.
전체 흐름
IOnlineSessionPtr SessionInterface 헤더에 정의
-> SessionInterface에 FindSessionCompleteDelegate를 등록. 서치가 완료되면 신호를 받게 구현함.
-> SessionSearch의 쿼리를 통해 검색 기준 설정
TSharedPtr<FOnlineSessionSearch> SessionSearch
->서치 쿼리 설정완료
->SessionInterface의 FindSessions 호출, bFindStarted에 서치가 시작되었음을 저장함
(FindSession을 실패했을때에 대비하여 방어코드 추가)
이후 서버 찾기가 완료되고 나면 FindSessionsCompleteDelegate를 통해 신호가 전달된다.
GameInstance에서 해당 델리게이트는 다음과 같이 바인딩 되어있다.
FindSessionsCompleteDelegate
= FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindSessionsComplete);
OnFindSessionsComplete()
흐름
1. SessionInterface가 유효하다면 델리게이트 바인딩을 해제한다.
2. 세션 찾기 실패 시 return (방어코드)
3. 발견된 방 개수 FoundCount에 저장
int32 FoundCount = SessionSearch->SearchResults.Num();
4. 스팀 닉네임 저장
FString MySteamName;
if (ULocalPlayer* LocalPlayer = GetFirstGamePlayer())
{
MySteamName = LocalPlayer->GetNickname();
}
5. 발견된 방을 순회하면서 방이 유효한지 판단
6. 유효한 방의 MapName을 받아옴
const bool bHasMapName =
Result.Session.SessionSettings.Get(SETTING_MAPNAME, MapName);
Result.Session.SessionSettings.Get(SETTING_MAPNAME, MapName);
7. 내가 연 세션은 제외
if (!MySteamName.IsEmpty() &&
Result.Session.OwningUserName == MySteamName)
{
UE_LOG(LogTemp, Warning,
TEXT("[%d] Skip My Session"),
i);
continue;
}
8. 맵 내에 빈자리가 있는지 체크
9. 세션 정보가 유효한지 체크
10. bFoundValidSession 를 true로 설정, TargetSessionIndex = i(지금 확인한 인덱스);
11. bFoundValideSession이 true -> JoinServer(TargetSessionIndex), false -> CreateServer()
JoinServer와 CreateServer 살펴보기
JoinServer(int32 SessionIndex)
1. bUseLobbiesIfAvailable = bUsePresence;
SearchResult.Session.SessionSettings.bUseLobbiesIfAvailable =
SessionResult.Session.SessionSettings.bUsePresence;
Steam JoinSession은 두 값이 같아야함.
2. Join Delegate 등록 해제 후 재등록 (이전 Join 기록때문에 꼬이지 않게 하기 위함)
3. SessionInterface의 JoinSession 함수 호출->리턴값으로 Join 성공 여부 받아서 저장
4. bJoinResult가 false일 경우 JoinSessionCompleteDelegate 등록 해제.
이렇게까지 하면 방을 찾고 접속하는 흐름이 완성된다.
CreateServer
1. 기존에 남아있는 서버가 있다면 파괴
// 해당 플레이어의 NetId 가져오기
FUniqueNetIdRepl PreferredNetId = LocalPlayer->GetPreferredUniqueNetId();
2. 만들 세션의 세팅 설정
3. CreateSessionCompleteDelegate 등록
4. 세션 만들기
const bool bCreateStarted =
SessionInterface->CreateSession(*PreferredNetId, NAME_GameSession, SessionSettings);
5. 세션이 만들어지지 않으면 bReturnTOMainMenuAfterDestroy = false; (무사히 세션이 파괴되지 않았다는 뜻)
CreateSessionCompleteDelegate도 등록 해제
여기까지 하면 방을 만들고, 존재하는 방에 참가하는 로직 분석 완료.