void UOnlineSessionClient::OnDestroyForMainMenuComplete(FName SessionName, bool bWasSuccessful)
{
	UE_LOG(LogOnline, Verbose, TEXT("OnDestroyForMainMenuComplete %s bSuccess: %d"), *SessionName.ToString(), bWasSuccessful);

	IOnlineSessionPtr SessionInt = GetSessionInt();

	if (SessionInt.IsValid())
	{
		SessionInt->ClearOnDestroySessionCompleteDelegate_Handle(OnDestroyForMainMenuCompleteDelegateHandle);
	}	


	UWorld* World = GetWorld();
	UNetDriver* NetDriver = World ? World->GetNetDriver() : nullptr;
		
	// Call disconnect to force us back to the menu level
	GEngine->HandleDisconnect(World, NetDriver);

	bHandlingDisconnect = false;
}
void UGameInstance::Init()
{
	ReceiveInit();

	const auto OnlineSub = IOnlineSubsystem::Get();
	if (OnlineSub != nullptr)
	{
		IOnlineSessionPtr SessionInt = OnlineSub->GetSessionInterface();
		if (SessionInt.IsValid())
		{
			SessionInt->AddOnSessionUserInviteAcceptedDelegate_Handle(FOnSessionUserInviteAcceptedDelegate::CreateUObject(this, &UGameInstance::HandleSessionUserInviteAccepted));
		}
	}

	UClass* SpawnClass = GetOnlineSessionClass();
	OnlineSession = NewObject<UOnlineSession>(this, SpawnClass);
	if (OnlineSession)
	{
		OnlineSession->RegisterOnlineDelegates();
	}
}
bool UtrnetDemoGameInstance::HostSession(TSharedPtr<const FUniqueNetId> UserId, FName SessionName, bool bIsLAN, bool bIsPresence, int32 MaxNumPlayers)
{
    // Get the Session Interface, so we can call the "CreateSession" function on it
    IOnlineSessionPtr Sessions = GetSession();

    if (!Sessions.IsValid() || !UserId.IsValid())
    {
        GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("No Sessions or UserId found!"));
        return false;
   }
    /*
    Fill in all the Session Settings that we want to use.

    There are more with SessionSettings.Set(...);
    For example the Map or the GameMode/Type.
    */
    SessionSettings = MakeShareable(new FOnlineSessionSettings());

    SessionSettings->bIsLANMatch = bIsLAN;
    SessionSettings->bUsesPresence = bIsPresence;
    SessionSettings->NumPublicConnections = MaxNumPlayers;
    SessionSettings->NumPrivateConnections = 0;
    SessionSettings->bAllowInvites = true;
    SessionSettings->bAllowJoinInProgress = true;
    SessionSettings->bShouldAdvertise = true;
    SessionSettings->bAllowJoinViaPresence = true;
    SessionSettings->bAllowJoinViaPresenceFriendsOnly = false;

    SessionSettings->Set(SETTING_MAPNAME, FString("NewMap"), EOnlineDataAdvertisementType::ViaOnlineService);

    // Set the delegate to the Handle of the SessionInterface
    OnCreateSessionCompleteDelegateHandle = Sessions->AddOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteDelegate);

    // Our delegate should get called when this is complete (doesn't need to be successful!)
    bool bCreateSession = Sessions->CreateSession(*UserId, SessionName, *SessionSettings);
    if (!bCreateSession) {
        GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("Create Sessions fail"));
    }
    return bCreateSession;
}
Exemple #4
0
// Destroy Session And return to Start Map
void URadeGameInstance::OnDestroySessionComplete(FName SessionName, bool bWasSuccessful)
{
	// Get the OnlineSubsystem we want to work with
	IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
	if (OnlineSub)
	{
		// Get the SessionInterface from the OnlineSubsystem
		IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();

		if (Sessions.IsValid())
		{
			// Clear the Delegate
			Sessions->ClearOnDestroySessionCompleteDelegate_Handle(OnDestroySessionCompleteDelegateHandle);

			// If it was successful, we just load another level (could be a MainMenu!)
			if (bWasSuccessful)
			{
				UGameplayStatics::OpenLevel(GetWorld(), "SelectMap", true);
			}
		}
	}
}
void UtrnetDemoGameInstance::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, FString::Printf(TEXT("OnCreateSessionComplete %s, %s"), *SessionName.ToString(), bWasSuccessful ? TEXT("sucess") : TEXT("fail")));
    
    // Get the Session Interface to call the StartSession function
    IOnlineSessionPtr Sessions = GetSession();

    if (!Sessions.IsValid())
    {
        return;
    }
    // Clear the SessionComplete delegate handle, since we finished this call
    Sessions->ClearOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteDelegateHandle);
    if (bWasSuccessful)
    {
        // Set the StartSession delegate handle
        OnStartSessionCompleteDelegateHandle = Sessions->AddOnStartSessionCompleteDelegate_Handle(OnStartSessionCompleteDelegate);

        // Our StartSessionComplete delegate should get called after this
        Sessions->StartSession(SessionName);
    }
}
bool AFPSGPlayerController::destroySession(FName sessionName) const
{
	bool success = false;

	IOnlineSubsystem* onlineSubsystem = IOnlineSubsystem::Get();
	IOnlineSessionPtr sessions = onlineSubsystem != NULL ? onlineSubsystem->GetSessionInterface() : NULL;

	if (sessions.IsValid())
	{
		//Destroy the session
		success = sessions->DestroySession(sessionName);
		if (success)
		{
			GEngine->AddOnScreenDebugMessage(-1, 40.0f, FColor::Cyan, TEXT("AFPSGPlayerController::destroySession success"));
		}
		else
		{
			GEngine->AddOnScreenDebugMessage(-1, 40.0f, FColor::Cyan, TEXT("AFPSGPlayerController::destroySession NOT success"));
		}
	}
	return success;
}
void UtrnetDemoGameInstance::FindSessions(TSharedPtr<const FUniqueNetId> UserId, FName SessionName, bool bIsLAN, bool bIsPresence)
{
    isLoading_ = true;
    
    // Get the SessionInterface from our OnlineSubsystem
    IOnlineSessionPtr Sessions = GetSession();

    if (Sessions.IsValid() && Sessions.IsValid() && UserId.IsValid())
    {
        /*
        Fill in all the SearchSettings, like if we are searching for a LAN game and how many results we want to have!
        */
        SessionSearch = MakeShareable(new FOnlineSessionSearch());

        SessionSearch->bIsLanQuery = bIsLAN;
        SessionSearch->MaxSearchResults = 20;
        SessionSearch->PingBucketSize = 50;

        // We only want to set this Query Setting if "bIsPresence" is true
        if (bIsPresence)
        {
            SessionSearch->QuerySettings.Set(SEARCH_PRESENCE, bIsPresence, EOnlineComparisonOp::Equals);
        }

        TSharedRef<FOnlineSessionSearch> SearchSettingsRef = SessionSearch.ToSharedRef();

        // Set the Delegate to the Delegate Handle of the FindSession function
        OnFindSessionsCompleteDelegateHandle = Sessions->AddOnFindSessionsCompleteDelegate_Handle(OnFindSessionsCompleteDelegate);

        // Finally call the SessionInterface function. The Delegate gets called once this is finished
        if(!Sessions->FindSessions(*UserId, SearchSettingsRef)) {
            OnFindSessionsComplete(false);
        }
    } else {
        // If something goes wrong, just call the Delegate Function directly with "false".
        OnFindSessionsComplete(false);        
    }
}
bool AMahjongGameSession_Japanese::HostSession(TSharedPtr<const FUniqueNetId> UserId, FName SessionName, const FString& GameType, const FString& MapName, bool bIsLAN, bool bIsPresence, int32 MaxNumPlayers)
{
    IOnlineSubsystem* const OnlineSubsystem = IOnlineSubsystem::Get();
    if (OnlineSubsystem)
    {
        CurrentSessionParams.SessionName = SessionName;
        CurrentSessionParams.bIsLAN = bIsLAN;
        CurrentSessionParams.bIsPresence = bIsPresence;
        CurrentSessionParams.UserId = UserId;
        MaxPlayers = MaxNumPlayers;

        IOnlineSessionPtr Sessions = OnlineSubsystem->GetSessionInterface();
        if (Sessions.IsValid() && CurrentSessionParams.UserId.IsValid())
        {
            HostSettings = MakeShareable(new FMahjongOnlineSessionSettings(bIsLAN, bIsPresence, MaxPlayers));
            HostSettings->Set(SETTING_GAMEMODE, GameType, EOnlineDataAdvertisementType::ViaOnlineService);
            HostSettings->Set(SETTING_MAPNAME, MapName, EOnlineDataAdvertisementType::ViaOnlineService);
            HostSettings->Set(SETTING_MATCHING_HOPPER, FString("JapaneseMahjong"), EOnlineDataAdvertisementType::DontAdvertise);
            HostSettings->Set(SETTING_MATCHING_TIMEOUT, 120.0f, EOnlineDataAdvertisementType::ViaOnlineService);
            HostSettings->Set(SETTING_SESSION_TEMPLATE_NAME, FString("GameSession"), EOnlineDataAdvertisementType::DontAdvertise);
            HostSettings->Set(SEARCH_KEYWORDS, MahjongWords::CustomMatchKeyword, EOnlineDataAdvertisementType::ViaOnlineService);

            OnCreateSessionCompleteDelegateHandle = Sessions->AddOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteDelegate);
            return Sessions->CreateSession(*CurrentSessionParams.UserId, CurrentSessionParams.SessionName, *HostSettings);
        }
    }
#if !UE_BUILD_SHIPPING
    else
    {
        // Hack workflow in development
        OnCreatePresenceSessionComplete().Broadcast(GameSessionName, true);
        return true;
    }
#endif

    return false;
}
bool UQosEvaluator::FindQosServersByRegion(int32 RegionIdx, FOnQosSearchComplete InCompletionDelegate)
{
    bool bSuccess = false;
    if (Datacenters.IsValidIndex(RegionIdx))
    {
        FQosRegionInfo& Datacenter = Datacenters[RegionIdx];
        Datacenter.Reset();

        IOnlineSubsystem* OnlineSub = Online::GetSubsystem(GetWorld());
        if (OnlineSub)
        {
            IOnlineSessionPtr SessionInt = OnlineSub->GetSessionInterface();
            if (SessionInt.IsValid())
            {
                if (!Datacenter.Region.RegionId.IsEmpty())
                {
                    const TSharedRef<FOnlineSessionSearch> QosSearchParams = MakeShareable(new FOnlineSessionSearchQos());
                    QosSearchParams->QuerySettings.Set(SETTING_REGION, Datacenter.Region.RegionId, EOnlineComparisonOp::Equals);

                    QosSearchQuery = QosSearchParams;

                    FOnFindSessionsCompleteDelegate OnFindDatacentersCompleteDelegate = FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindQosServersByRegionComplete, RegionIdx, InCompletionDelegate);
                    OnFindDatacentersCompleteDelegateHandle = SessionInt->AddOnFindSessionsCompleteDelegate_Handle(OnFindDatacentersCompleteDelegate);

                    SessionInt->FindSessions(ControllerId, QosSearchParams);
                }
                else
                {
                    OnFindQosServersByRegionComplete(false, RegionIdx, InCompletionDelegate);
                }
                bSuccess = true;
            }
        }
    }

    return bSuccess;
}
void APartyBeaconHost::Tick(float DeltaTime)
{
	IOnlineSessionPtr SessionsInt = Online::GetSessionInterface();
	if (SessionsInt.IsValid())
	{
		FNamedOnlineSession* Session = SessionsInt->GetNamedSession(SessionName);
		if (Session)
		{
			TArray< TSharedPtr<FUniqueNetId> > PlayersToLogout;
			for (int32 ResIdx=0; ResIdx < Reservations.Num(); ResIdx++)
			{
				FPartyReservation& PartyRes = Reservations[ResIdx];

				// Determine if we have a client connection for the reservation 
				bool bIsConnectedReservation = false;
				for (int32 ClientIdx=0; ClientIdx < ClientActors.Num(); ClientIdx++)
				{
					APartyBeaconClient* Client = Cast<APartyBeaconClient>(ClientActors[ClientIdx]);
					if (Client)
					{
						const FPartyReservation& ClientRes = Client->GetPendingReservation();
						if (ClientRes.PartyLeader == PartyRes.PartyLeader)
						{
							bIsConnectedReservation = true;
							break;
						}
					}
					else
					{
						UE_LOG(LogBeacon, Error, TEXT("Missing PartyBeaconClient found in ClientActors array"));
						ClientActors.RemoveAtSwap(ClientIdx);
						ClientIdx--;
					}
				}

				// Don't update clients that are still connected
				if (bIsConnectedReservation)
				{
					for (int32 PlayerIdx=0; PlayerIdx < PartyRes.PartyMembers.Num(); PlayerIdx++)
					{
						FPlayerReservation& PlayerEntry = PartyRes.PartyMembers[PlayerIdx];
						PlayerEntry.ElapsedTime = 0.0f;
					}
				}
				// Once a client disconnects, update the elapsed time since they were found as a registrant in the game session
				else
				{
					for (int32 PlayerIdx=0; PlayerIdx < PartyRes.PartyMembers.Num(); PlayerIdx++)
					{
						FPlayerReservation& PlayerEntry = PartyRes.PartyMembers[PlayerIdx];

						// Determine if the player is the owner of the session	
						const bool bIsSessionOwner = Session->OwningUserId.IsValid() && (*Session->OwningUserId == *PlayerEntry.UniqueId);

						// Determine if the player member is registered in the game session
						if (SessionsInt->IsPlayerInSession(SessionName, *PlayerEntry.UniqueId) ||
							// Never timeout the session owner
							bIsSessionOwner)
						{
							FUniqueNetIdMatcher PlayerMatch(*PlayerEntry.UniqueId);
							int32 FoundIdx = PlayersPendingJoin.FindMatch(PlayerMatch);
							if (FoundIdx != INDEX_NONE)
							{
								UE_LOG(LogBeacon, Display, TEXT("Beacon (%s): pending player %s found in session (%s)."),
									*GetName(),
									*PlayerEntry.UniqueId->ToDebugString(),
									*SessionName.ToString());

								// reset elapsed time since found
								PlayerEntry.ElapsedTime = 0.0f;
								// also remove from pending join list
								PlayersPendingJoin.RemoveAtSwap(FoundIdx);
							}
						}
						else
						{
							// update elapsed time
							PlayerEntry.ElapsedTime += DeltaTime;

							// if the player is pending it's initial join then check against TravelSessionTimeoutSecs instead
							FUniqueNetIdMatcher PlayerMatch(*PlayerEntry.UniqueId);
							int32 FoundIdx = PlayersPendingJoin.FindMatch(PlayerMatch);
							const bool bIsPlayerPendingJoin = FoundIdx != INDEX_NONE;
							// if the timeout has been exceeded then add to list of players 
							// that need to be logged out from the beacon
							if ((bIsPlayerPendingJoin && PlayerEntry.ElapsedTime > TravelSessionTimeoutSecs) ||
								(!bIsPlayerPendingJoin && PlayerEntry.ElapsedTime > SessionTimeoutSecs))
							{
								PlayersToLogout.AddUnique(PlayerEntry.UniqueId.GetUniqueNetId());
							}
						}
					}
				}
			}

			// Logout any players that timed out
			for (int32 LogoutIdx=0; LogoutIdx < PlayersToLogout.Num(); LogoutIdx++)
			{
				bool bFound = false;
				const TSharedPtr<FUniqueNetId>& UniqueId = PlayersToLogout[LogoutIdx];
				float ElapsedSessionTime = 0.f;
				for (int32 ResIdx=0; ResIdx < Reservations.Num(); ResIdx++)
				{
					FPartyReservation& PartyRes = Reservations[ResIdx];
					for (int32 PlayerIdx=0; PlayerIdx < PartyRes.PartyMembers.Num(); PlayerIdx++)
					{
						FPlayerReservation& PlayerEntry = PartyRes.PartyMembers[PlayerIdx];
						if (*PlayerEntry.UniqueId == *UniqueId)
						{
							ElapsedSessionTime = PlayerEntry.ElapsedTime;
							bFound = true;
							break;
						}
					}

					if (bFound)
					{
						break;
					}
				}

				UE_LOG(LogBeacon, Display, TEXT("Beacon (%s): player logout due to timeout for %s, elapsed time = %0.3f"),
					*GetName(),
					*UniqueId->ToDebugString(),
					ElapsedSessionTime);
				// Also remove from pending join list
				PlayersPendingJoin.RemoveSingleSwap(UniqueId);
				// let the beacon handle the logout and notifications/delegates
				FUniqueNetIdRepl RemovedId(UniqueId);
				HandlePlayerLogout(RemovedId);
			}
		}
	}
}
Exemple #11
0
bool UUModGameInstance::StartNewGame(bool single, bool local, int32 max, FString map, FString hostName)
{
	ULocalPlayer* const Player = GetFirstGamePlayer();

	Player->PlayerController->ClientTravel("LoadScreen", ETravelType::TRAVEL_Absolute);
	
	TSharedPtr<const FUniqueNetId> UserId = Player->GetPreferredUniqueNetId();

	IOnlineSubsystem* const OnlineSub = IOnlineSubsystem::Get();

	IOnlineSessionPtr Sessions = NULL;

	if (OnlineSub == NULL) {
		return false;
	}

	Sessions = OnlineSub->GetSessionInterface();
	
	if (!Sessions.IsValid() || !UserId.IsValid()) {
		return false;
	}

	if (!CurSessionName.IsEmpty()){
		DestroyCurSession(Sessions);
		return false;
	}

	TSharedPtr<class FOnlineSessionSettings> SessionSettings = MakeShareable(new FOnlineSessionSettings());
	
	if (single) {
		SessionSettings->bIsLANMatch = true;
		IsLAN = true;
	} else {
		SessionSettings->bIsLANMatch = local;
		IsLAN = local;
	}
	SessionSettings->bUsesPresence = true;
	if (single) {
		SessionSettings->NumPublicConnections = 1;
	} else {
		SessionSettings->NumPublicConnections = max;
	}	
	SessionSettings->NumPrivateConnections = 0;
	SessionSettings->bAllowInvites = true;
	SessionSettings->bAllowJoinInProgress = true;
	SessionSettings->bShouldAdvertise = true;
	SessionSettings->bAllowJoinViaPresence = true;
	SessionSettings->bAllowJoinViaPresenceFriendsOnly = false;

	SessionSettings->Set(SETTING_MAPNAME, map, EOnlineDataAdvertisementType::ViaOnlineService);
	SessionSettings->Set(SETTING_GAMEMODE, AUModGameMode::StaticClass()->GetPathName(), EOnlineDataAdvertisementType::ViaOnlineService);	

	if (single) {
		hostName = TEXT("UMod_SinglePlayer");
	}

	OnCreateSessionCompleteDelegateHandle = Sessions->AddOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteDelegate);

	CurSessionMapName = map;

	FName name = FName(*hostName);

	CurSessionName = hostName;

	return Sessions->CreateSession(*UserId, name, *SessionSettings);
}
void UQosEvaluator::OnFindQosServersByRegionComplete(bool bWasSuccessful, int32 RegionIdx, FOnQosSearchComplete InCompletionDelegate)
{
    IOnlineSubsystem* OnlineSub = Online::GetSubsystem(GetWorld());
    if (OnlineSub)
    {
        IOnlineSessionPtr SessionInt = OnlineSub->GetSessionInterface();
        if (SessionInt.IsValid())
        {
            SessionInt->ClearOnFindSessionsCompleteDelegate_Handle(OnFindDatacentersCompleteDelegateHandle);
        }
    }

    if (!bCancelOperation)
    {
        FQosRegionInfo& Datacenter = Datacenters[RegionIdx];
        Datacenter.Result = bWasSuccessful ? EQosCompletionResult::Success : EQosCompletionResult::Failure;

        // Copy the search results for later evaluation
        Datacenter.SearchResults = QosSearchQuery->SearchResults;
        QosSearchQuery = nullptr;

        int32 NextRegionIdx = GetNextRegionId(RegionIdx);
        if (Datacenters.IsValidIndex(NextRegionIdx))
        {
            TWeakObjectPtr<UQosEvaluator> WeakThisCap(this);
            GetWorldTimerManager().SetTimerForNextTick(FTimerDelegate::CreateLambda([InCompletionDelegate, NextRegionIdx, WeakThisCap]()
            {
                if (WeakThisCap.IsValid())
                {
                    auto StrongThis = WeakThisCap.Get();
                    // Move to the next region results
                    if (!StrongThis->FindQosServersByRegion(NextRegionIdx, InCompletionDelegate))
                    {
                        // Failed to start
                        StrongThis->GetWorldTimerManager().SetTimerForNextTick(FTimerDelegate::CreateLambda([InCompletionDelegate, WeakThisCap]()
                        {
                            if (WeakThisCap.IsValid())
                            {
                                auto StrongThis1 = WeakThisCap.Get();
                                StrongThis1->FinalizeDatacenterResult(InCompletionDelegate, EQosCompletionResult::Failure, TArray<FQosRegionInfo>());
                            }
                        }));
                    }
                }
            }));
        }
        else
        {
            // Evaluate search results for all regions next tick
            FOnQosPingEvalComplete CompletionDelegate = FOnQosPingEvalComplete::CreateUObject(this, &ThisClass::OnEvaluateForDatacenterComplete, InCompletionDelegate);

            TWeakObjectPtr<UQosEvaluator> WeakThisCap(this);
            GetWorldTimerManager().SetTimerForNextTick(FTimerDelegate::CreateLambda([CompletionDelegate, WeakThisCap]()
            {
                if (WeakThisCap.IsValid())
                {
                    auto StrongThis = WeakThisCap.Get();
                    StrongThis->bInProgress = false;
                    StrongThis->StartServerPing(CompletionDelegate);
                }
            }));
        }
    }
    else
    {
        QosSearchQuery = nullptr;

        // Mark all remaining datacenters as canceled
        for (int32 Idx = RegionIdx; Idx < Datacenters.Num(); Idx++)
        {
            Datacenters[Idx].Result = EQosCompletionResult::Canceled;
        }

        FinalizeDatacenterResult(InCompletionDelegate, EQosCompletionResult::Canceled, Datacenters);
    }
}