/**
 *	Create a search result from a server response
 *
 * @param ServerDetails Steam server details
 */
void FOnlineAsyncTaskSteamFindServerBase::ParseSearchResult(class gameserveritem_t* ServerDetails)
{
	TSharedRef<FInternetAddr> ServerAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();

	ServerAddr->SetIp(ServerDetails->m_NetAdr.GetIP());
	ServerAddr->SetPort(ServerDetails->m_NetAdr.GetConnectionPort());
	int32 ServerQueryPort = ServerDetails->m_NetAdr.GetQueryPort();

	UE_LOG_ONLINE(Warning, TEXT("Server response IP:%s"), *ServerAddr->ToString(false));
	if (ServerDetails->m_bHadSuccessfulResponse)
	{
		FString GameTags(UTF8_TO_TCHAR(ServerDetails->m_szGameTags));

		// Check for build compatibility
		int32 ServerBuildId = 0;
		int32 BuildUniqueId = GetBuildUniqueId();

		TArray<FString> TagArray;
		GameTags.ParseIntoArray(TagArray, TEXT(","), true);
		if (TagArray.Num() > 0 && TagArray[0].StartsWith(STEAMKEY_BUILDUNIQUEID))
		{
			ServerBuildId = FCString::Atoi(*TagArray[0].Mid(ARRAY_COUNT(STEAMKEY_BUILDUNIQUEID)));
		}

		if (ServerBuildId != 0 && ServerBuildId == BuildUniqueId)
		{
			// Create a new pending search result 
			FPendingSearchResultSteam* NewPendingSearch = new (PendingSearchResults) FPendingSearchResultSteam(this);
			NewPendingSearch->ServerId = FUniqueNetIdSteam(ServerDetails->m_steamID);
			NewPendingSearch->HostAddr = ServerAddr;

			// Fill search result members
			FOnlineSessionSearchResult* NewSearchResult = &NewPendingSearch->PendingSearchResult;
			NewSearchResult->PingInMs = FMath::Clamp(ServerDetails->m_nPing, 0, MAX_QUERY_PING);

			// Fill session members
			FOnlineSession* NewSession = &NewSearchResult->Session;

			//NewSession->OwningUserId = ;
			NewSession->OwningUserName = UTF8_TO_TCHAR(ServerDetails->GetName());

			NewSession->NumOpenPublicConnections = ServerDetails->m_nMaxPlayers - ServerDetails->m_nPlayers;
			NewSession->NumOpenPrivateConnections = 0;

			// Fill session settings members
			NewSession->SessionSettings.NumPublicConnections = ServerDetails->m_nMaxPlayers;
			NewSession->SessionSettings.NumPrivateConnections = 0;
			NewSession->SessionSettings.bAntiCheatProtected = ServerDetails->m_bSecure ? true : false;
			NewSession->SessionSettings.Set(SETTING_MAPNAME, FString(UTF8_TO_TCHAR(ServerDetails->m_szMap)), EOnlineDataAdvertisementType::ViaOnlineService);

			// Start a rules request for this new result
			NewPendingSearch->ServerQueryHandle = SteamMatchmakingServersPtr->ServerRules(ServerDetails->m_NetAdr.GetIP(), ServerQueryPort, NewPendingSearch);
			if (NewPendingSearch->ServerQueryHandle == HSERVERQUERY_INVALID)
			{
				// Remove the failed element
				PendingSearchResults.RemoveAtSwap(PendingSearchResults.Num() - 1);
			}
		}
		else
		{
			UE_LOG_ONLINE(Warning, TEXT("Removed incompatible build: ServerBuildUniqueId = 0x%08x, GetBuildUniqueId() = 0x%08x"),
				ServerBuildId, BuildUniqueId);
		}
	}
}
bool FOnlineSessionNull::CreateSession(int32 HostingPlayerNum, FName SessionName, const FOnlineSessionSettings& NewSessionSettings)
{
	uint32 Result = E_FAIL;

	// Check for an existing session
	FNamedOnlineSession* Session = GetNamedSession(SessionName);
	if (Session == NULL)
	{
		// Create a new session and deep copy the game settings
		Session = AddNamedSession(SessionName, NewSessionSettings);
		check(Session);
		Session->SessionState = EOnlineSessionState::Creating;
		Session->NumOpenPrivateConnections = NewSessionSettings.NumPrivateConnections;
		Session->NumOpenPublicConnections = NewSessionSettings.NumPublicConnections;	// always start with full public connections, local player will register later

		Session->HostingPlayerNum = HostingPlayerNum;

		check(NullSubsystem);
		IOnlineIdentityPtr Identity = NullSubsystem->GetIdentityInterface();
		if (Identity.IsValid())
		{
			Session->OwningUserId = Identity->GetUniquePlayerId(HostingPlayerNum);
			Session->OwningUserName = Identity->GetPlayerNickname(HostingPlayerNum);
		}

		// if did not get a valid one, use just something
		if (!Session->OwningUserId.IsValid())
		{
			Session->OwningUserId = MakeShareable(new FUniqueNetIdString(FString::Printf(TEXT("%d"), HostingPlayerNum)));
			Session->OwningUserName = FString(TEXT("NullUser"));
		}
		
		// Unique identifier of this build for compatibility
		Session->SessionSettings.BuildUniqueId = GetBuildUniqueId();

		// Setup the host session info
		FOnlineSessionInfoNull* NewSessionInfo = new FOnlineSessionInfoNull();
		NewSessionInfo->Init(*NullSubsystem);
		Session->SessionInfo = MakeShareable(NewSessionInfo);

		Result = UpdateLANStatus();

		if (Result != ERROR_IO_PENDING)
		{
			// Set the game state as pending (not started)
			Session->SessionState = EOnlineSessionState::Pending;

			if (Result != ERROR_SUCCESS)
			{
				// Clean up the session info so we don't get into a confused state
				RemoveNamedSession(SessionName);
			}
			else
			{
				RegisterLocalPlayers(Session);
			}
		}
	}
	else
	{
		UE_LOG_ONLINE(Warning, TEXT("Cannot create session '%s': session already exists."), *SessionName.ToString());
	}

	if (Result != ERROR_IO_PENDING)
	{
		TriggerOnCreateSessionCompleteDelegates(SessionName, (Result == ERROR_SUCCESS) ? true : false);
	}
	
	return Result == ERROR_IO_PENDING || Result == ERROR_SUCCESS;
}
void UAdvancedSessionsLibrary::GetCurrentUniqueBuildID(int32 &UniqueBuildId)
{
	UniqueBuildId = GetBuildUniqueId();
}