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; }
// 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); } } } }
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); } }