mordentral / AdvancedSessionsPlugin

Advanced Sessions Plugin for UE4
https://www.vreue4.com
MIT License
597 stars 141 forks source link

Find Sessions Advanced Never Calls OnSuccess #1

Closed ughstudios closed 4 years ago

ughstudios commented 4 years ago

image

OnSuccess and OnFailure are never called, only the top execute pin. I even went and did a full debug of the method and went line by line, the FindSessions() method returns true, and is successful, but then the Advanced FindSessions method just simply doesn't run onsuccessful

ughstudios commented 4 years ago

I should mention that CreateSessionAdvanced works perfectly!

ughstudios commented 4 years ago

image This is how I define my session btw, in my game mode blueprint

ughstudios commented 4 years ago

The only differences are in here: if (SearchSettings->bIsLanQuery)

bool FOnlineSessionHVS::FindSessions(int32 SearchingPlayerNum, const TSharedRef<FOnlineSessionSearch>& SearchSettings)
{
    uint32 Return = ONLINE_FAIL;

    // Don't start another search while one is in progress
    if (!CurrentSessionSearch.IsValid() && SearchSettings->SearchState != EOnlineAsyncTaskState::InProgress)
    {
        // Free up previous results
        SearchSettings->SearchResults.Empty();

        // Copy the search pointer so we can keep it around
        CurrentSessionSearch = SearchSettings;

        // remember the time at which we started search, as this will be used for a "good enough" ping estimation
        SessionSearchStartInSeconds = FPlatformTime::Seconds();

        // Check if its a LAN query
        if (SearchSettings->bIsLanQuery)
        {
            Return = FindLANSession();

            if (Return == ONLINE_IO_PENDING)
            {
                SearchSettings->SearchState = EOnlineAsyncTaskState::InProgress;
            }
        }
        else
        {
            FOnlineSessionSearchResult SearchResult;
            TSharedPtr<FOnlineSessionInfoHVS> SessionInfo = MakeShareable(new FOnlineSessionInfoHVS());
            TSharedPtr<FInternetAddr> InternetAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
            FString IpAddr;
            SearchSettings->QuerySettings.Get(FName("IpAddr"), IpAddr);
            GLog->Log("OnlineSessionInterfaceHVS::FindSessions IpAddr: " + IpAddr);
            bool bSuccessful;           
            InternetAddress->SetIp(*IpAddr, bSuccessful);
            int Port;
            SearchSettings->QuerySettings.Get(FName("Port"), Port);
            InternetAddress->SetPort(Port);

            GLog->Log("OnlineSessionInterfaceHVS::FindSessions SetIp successful?: " + FString::FromInt(bSuccessful));

            GLog->Log("InternetAddress ToString(): " + InternetAddress->ToString(true));

            SessionInfo->HostAddr = InternetAddress;
            FString OptionsOut;
            SearchSettings->QuerySettings.Get(FName("Options"), OptionsOut);

            GLog->Log("Options : " + OptionsOut);

            SessionInfo->Options = OptionsOut;
            SearchResult.Session.SessionInfo = SessionInfo;

            CurrentSessionSearch->SearchResults.Add(SearchResult);

            Return = ONLINE_SUCCESS;
            GLog->Log("Successful.");
        }
    }
    else
    {
        UE_LOG_ONLINE_SESSION(Warning, TEXT("Ignoring game search request while one is pending"));
        Return = ONLINE_IO_PENDING;
    }

    return Return == ONLINE_SUCCESS || Return == ONLINE_IO_PENDING;
}

I should mention that I am using a custom online subsystem and this is my find sessions method.

ughstudios commented 4 years ago

My custom find sessions method should simply just create a session search object and give it to the search results in CurrentSessionSearch->SearchResults

My JoinSession is exactly the same as the Null Subsystem ( my subsystem was actually copied exactly from the null subsystem but i've set it up to find matches from my custom master server ).

/** Get a resolved connection string from a session info */
static bool GetConnectStringFromSessionInfo(TSharedPtr<FOnlineSessionInfoHVS>& SessionInfo, FString& ConnectInfo, int32 PortOverride=0)
{
    bool bSuccess = false;
    if (SessionInfo.IsValid())
    {
        if (SessionInfo->HostAddr.IsValid() && SessionInfo->HostAddr->IsValid())
        {
            /*if (PortOverride != 0)
            {
                ConnectInfo = FString::Printf(TEXT("%s:%d"), *SessionInfo->HostAddr->ToString(false), PortOverride);
            }
            else
            {
                ConnectInfo = FString::Printf(TEXT("%s"), *SessionInfo->HostAddr->ToString(true));
            }*/

            ConnectInfo = SessionInfo->HostAddr->ToString(true) + SessionInfo->Options;

            bSuccess = true;
        }
    }

    return bSuccess;
}

This is what unreal uses to get the url to pass into ClientTravel()

ughstudios commented 4 years ago

image

Then I simply pass the correct stuff into the find sessions function which then essentially, in my overwriten function for my custom subsystem it essentially just takkes these filters and creates a session result for it (to be used to connect). because by the time i'm ready to connect, my game already has the ip, port, and options to connect, but I need to be connected to a session otherwise the voice chat doesn't work lol. Because AGameModeBase::InitNewPlayer() calls GameSession->RegisterPlayer() which calls PlayerState->RegisterServerWithSubsystem, which then will try to get a session locally, if there is one, and then it will call RegisterVoice(), I'm essentially only doing this so I can use the built in voice system over the network, and also because I want to setup team chats. If there is a better way, then let me know.

ughstudios commented 4 years ago

Figured it out, make sure you have these in your FindSessions() function:

            Return = ONLINE_SUCCESS;
            SearchSettings->SearchState = EOnlineAsyncTaskState::Done;
            TriggerOnFindSessionsCompleteDelegates(true);
ughstudios commented 4 years ago

Don't forget guys that inside of JoinSessionCallbackProxy.cpp the engine actually calls ClientTravel and gets the connection string from GetResolvedConnectString() which is defined in your OnlineSessionInteface.cpp file

void UJoinSessionCallbackProxy::OnCompleted(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
    FOnlineSubsystemBPCallHelper Helper(TEXT("JoinSessionCallback"), WorldContextObject);
    Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get());

    if (Helper.IsValid())
    {
        auto Sessions = Helper.OnlineSub->GetSessionInterface();
        if (Sessions.IsValid())
        {
            Sessions->ClearOnJoinSessionCompleteDelegate_Handle(DelegateHandle);

            if (Result == EOnJoinSessionCompleteResult::Success)
            {
                // Client travel to the server
                FString ConnectString;
                if (Sessions->GetResolvedConnectString(NAME_GameSession, ConnectString) && PlayerControllerWeakPtr.IsValid())
                {
                    UE_LOG_ONLINE_SESSION(Log, TEXT("Join session: traveling to %s"), *ConnectString);
                    PlayerControllerWeakPtr->ClientTravel(ConnectString, TRAVEL_Absolute);
                    OnSuccess.Broadcast();
                    return;
                }
            }
        }
    }

    OnFailure.Broadcast();
}