コード例 #1
0
bool FOnlineSessionNull::GetResolvedConnectString(const class FOnlineSessionSearchResult& SearchResult, FName PortType, FString& ConnectInfo)
{
	bool bSuccess = false;
	if (SearchResult.Session.SessionInfo.IsValid())
	{
		TSharedPtr<FOnlineSessionInfoNull> SessionInfo = StaticCastSharedPtr<FOnlineSessionInfoNull>(SearchResult.Session.SessionInfo);

		if (PortType == BeaconPort)
		{
			int32 BeaconListenPort = 15000;
			if (SearchResult.Session.SessionSettings.Get(SETTING_BEACONPORT, BeaconListenPort) && BeaconListenPort > 0)
			{
				bSuccess = GetConnectStringFromSessionInfo(SessionInfo, ConnectInfo, BeaconListenPort);
			}
		}
		else if (PortType == GamePort)
		{
			bSuccess = GetConnectStringFromSessionInfo(SessionInfo, ConnectInfo);
		}
	}
	
	if (!bSuccess || ConnectInfo.IsEmpty())
	{
		UE_LOG_ONLINE(Warning, TEXT("Invalid session info in search result to GetResolvedConnectString()"));
	}

	return bSuccess;
}
コード例 #2
0
bool APartyBeaconClient::RequestReservation(const FString& ConnectInfoStr, const FString& InSessionId, const FUniqueNetIdRepl& RequestingPartyLeader, const TArray<FPlayerReservation>& PartyMembers)
{
	bool bSuccess = false;

	FURL ConnectURL(NULL, *ConnectInfoStr, TRAVEL_Absolute);
	if (InitClient(ConnectURL))
	{
		DestSessionId = InSessionId;
		PendingReservation.PartyLeader = RequestingPartyLeader;
		PendingReservation.PartyMembers = PartyMembers;
		bPendingReservationSent = false;
		RequestType = EClientRequestType::ExistingSessionReservation;
		bSuccess = true;
	}
	else
	{
		UE_LOG_ONLINE(Warning, TEXT("RequestReservation: Failure to init client beacon with %s."), *ConnectURL.ToString());
		RequestType = EClientRequestType::NonePending;
	}

	if (!bSuccess)
	{
		OnFailure();
	}

	return bSuccess;
}
コード例 #3
0
/** 
 * Write out the steam app id to the steam_appid.txt file before initializing the API
 * @param SteamAppId id assigned to the application by Steam
 */
static void WriteSteamAppIdToDisk(int32 SteamAppId)
{
	if (SteamAppId > 0)
	{
		// Turn off sandbox temporarily to make sure file is where it's always expected
		FScopeSandboxContext ScopedSandbox(false);

		// Access the physical file writer directly so that we still write next to the executable in CotF builds.
		FString SteamAppIdFilename = GetSteamAppIdFilename();
		IFileHandle* Handle = IPlatformFile::GetPlatformPhysical().OpenWrite(*SteamAppIdFilename, false, false);
		if (!Handle)
		{
			UE_LOG_ONLINE(Fatal, TEXT("Failed to create file: %s"), *SteamAppIdFilename);
		}
		else
		{
			FString AppId = FString::Printf(TEXT("%d"), SteamAppId);

			FBufferArchive Archive;
			Archive.Serialize((void*)TCHAR_TO_ANSI(*AppId), AppId.Len());

			Handle->Write(Archive.GetData(), Archive.Num());
			delete Handle;
			Handle = nullptr;
		}
	}
}
コード例 #4
0
bool FOnlineSessionNull::CancelFindSessions()
{
	uint32 Return = E_FAIL;
	if (CurrentSessionSearch->SearchState == EOnlineAsyncTaskState::InProgress)
	{
		// Make sure it's the right type
		Return = ERROR_SUCCESS;

		FinalizeLANSearch();

		CurrentSessionSearch->SearchState = EOnlineAsyncTaskState::Failed;
		CurrentSessionSearch = NULL;
	}
	else
	{
		UE_LOG_ONLINE(Warning, TEXT("Can't cancel a search that isn't in progress"));
	}

	if (Return != ERROR_IO_PENDING)
	{
		TriggerOnCancelFindSessionsCompleteDelegates(true);
	}

	return Return == ERROR_SUCCESS || Return == ERROR_IO_PENDING;
}
コード例 #5
0
void FOnlineSubsystemSteamModule::StartupModule()
{
    bool bSuccess = false;

    // Load the Steam modules before first call to API
    LoadSteamModules();
    if (AreSteamDllsLoaded())
    {
        // Create and register our singleton factory with the main online subsystem for easy access
        SteamFactory = new FOnlineFactorySteam();

        FOnlineSubsystemModule& OSS = FModuleManager::GetModuleChecked<FOnlineSubsystemModule>("OnlineSubsystem");
        OSS.RegisterPlatformService(STEAM_SUBSYSTEM, SteamFactory);
        bSuccess = true;
    }
    else
    {
        UE_LOG_ONLINE(Warning, TEXT("Steam SDK %s libraries not present at %s or failed to load!"), STEAM_SDK_VER, *GetSteamModulePath());
    }

    if (!bSuccess)
    {
        UnloadSteamModules();
    }
}
コード例 #6
0
bool FOnlineSessionNull::FindSessions(int32 SearchingPlayerNum, const TSharedRef<FOnlineSessionSearch>& SearchSettings)
{
	uint32 Return = E_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
		Return = FindLANSession();

		if (Return == ERROR_IO_PENDING)
		{
			SearchSettings->SearchState = EOnlineAsyncTaskState::InProgress;
		}
	}
	else
	{
		UE_LOG_ONLINE(Warning, TEXT("Ignoring game search request while one is pending"));
		Return = ERROR_IO_PENDING;
	}

	return Return == ERROR_SUCCESS || Return == ERROR_IO_PENDING;
}
コード例 #7
0
void FOnlineSubsystemSteamModule::LoadSteamModules()
{
    UE_LOG_ONLINE(Display, TEXT("Loading Steam SDK %s"), STEAM_SDK_VER);

#if PLATFORM_WINDOWS
#if PLATFORM_64BITS
    FString RootSteamPath = GetSteamModulePath();
    FPlatformProcess::PushDllDirectory(*RootSteamPath);
    SteamDLLHandle = FPlatformProcess::GetDllHandle(*(RootSteamPath + "steam_api64.dll"));
#if 0 //64 bit not supported well at present, use Steam Client dlls
    // Load the Steam dedicated server dlls (assumes no Steam Client running)
    if (IsRunningDedicatedServer())
    {
        SteamServerDLLHandle = FPlatformProcess::GetDllHandle(*(RootSteamPath + "steamclient64.dll"));
    }
#endif
    FPlatformProcess::PopDllDirectory(*RootSteamPath);
#else	//PLATFORM_64BITS
    FString RootSteamPath = GetSteamModulePath();
    FPlatformProcess::PushDllDirectory(*RootSteamPath);
    SteamDLLHandle = FPlatformProcess::GetDllHandle(*(RootSteamPath + "steam_api.dll"));
    if (IsRunningDedicatedServer())
    {
        SteamServerDLLHandle = FPlatformProcess::GetDllHandle(*(RootSteamPath + "steamclient.dll"));
    }
    FPlatformProcess::PopDllDirectory(*RootSteamPath);
#endif	//PLATFORM_64BITS
#elif PLATFORM_MAC
    SteamDLLHandle = FPlatformProcess::GetDllHandle(TEXT("libsteam_api.dylib"));
#endif	//PLATFORM_WINDOWS
}
コード例 #8
0
/**
 * ** INTERNAL **
 * Called by an async task after completing an achievement read.
 *
 * @param PlayerId - id of a player we were making read for
 * @param bReadSuccessfully - whether the read completed successfully
 */
void FOnlineAchievementsSteam::UpdateAchievementsForUser(const FUniqueNetIdSteam& PlayerId, bool bReadSuccessfully)
{
	// shouldn't get this far if no achievements are configured
	check(bHaveConfiguredAchievements);

	ISteamUserStats* SteamUserStatsPtr = SteamUserStats();
	check(SteamUserStatsPtr);
	CSteamID SteamUserId = PlayerId;

	// new array
	TArray<FOnlineAchievement> AchievementsForPlayer;
	const int32 AchNum = Achievements.Num();

	for (int32 AchIdx = 0; AchIdx < AchNum; ++AchIdx)
	{
		// get the info
		bool bUnlocked;
		uint32 UnlockUnixTime;
		if (!SteamUserStatsPtr->GetAchievementAndUnlockTime(TCHAR_TO_UTF8(*Achievements[AchIdx].Id), &bUnlocked, &UnlockUnixTime))
		{
			UE_LOG_ONLINE(Warning, TEXT("GetAchievementAndUnlockTime() failed for achievement '%s'"), *Achievements[AchIdx].Id);
			// skip this achievement
			continue;
		}

		FOnlineAchievementSteam NewAch = Achievements[ AchIdx ];
		NewAch.bReadFromSteam = true;
		NewAch.Progress = bUnlocked ? 100.0 : 0.0;	// TODO: we may want to support more fine-grained progress based on associated stat and min/max, 
													// although we can only map it one-way (i.e. when reading, but not when writing)
		NewAch.UnlockTime = FDateTime::FromUnixTimestamp(UnlockUnixTime);

		NewAch.Title = FText::FromString( UTF8_TO_TCHAR( SteamUserStatsPtr->GetAchievementDisplayAttribute(TCHAR_TO_UTF8(*Achievements[AchIdx].Id), "name") ) );
		NewAch.LockedDesc = FText::FromString( UTF8_TO_TCHAR( SteamUserStatsPtr->GetAchievementDisplayAttribute(TCHAR_TO_UTF8(*Achievements[AchIdx].Id), "desc") ) );
		NewAch.UnlockedDesc = NewAch.LockedDesc;

		NewAch.bIsHidden = FCString::Atoi( UTF8_TO_TCHAR( SteamUserStatsPtr->GetAchievementDisplayAttribute(TCHAR_TO_UTF8(*Achievements[AchIdx].Id), "desc") ) ) != 0;

		UE_LOG_ONLINE(Verbose, TEXT("Read achievement %d: %s"), AchIdx, *NewAch.ToDebugString());
		AchievementsForPlayer.Add( NewAch );

		// add mapping (should replace any existing one)
		AchievementDescriptions.Add(NewAch.Id, NewAch);
	}

	// should replace any already existing values
	PlayerAchievements.Add(PlayerId, AchievementsForPlayer);
}
コード例 #9
0
void FOnlineSessionNull::AppendSessionSettingsToPacket(FNboSerializeToBufferNull& Packet, FOnlineSessionSettings* SessionSettings)
{
#if DEBUG_LAN_BEACON
	UE_LOG_ONLINE(Verbose, TEXT("Sending session settings to client"));
#endif 

	// Members of the session settings class
	Packet << SessionSettings->NumPublicConnections
		<< SessionSettings->NumPrivateConnections
		<< (uint8)SessionSettings->bShouldAdvertise
		<< (uint8)SessionSettings->bIsLANMatch
		<< (uint8)SessionSettings->bIsDedicated
		<< (uint8)SessionSettings->bUsesStats
		<< (uint8)SessionSettings->bAllowJoinInProgress
		<< (uint8)SessionSettings->bAllowInvites
		<< (uint8)SessionSettings->bUsesPresence
		<< (uint8)SessionSettings->bAllowJoinViaPresence
		<< (uint8)SessionSettings->bAllowJoinViaPresenceFriendsOnly
		<< (uint8)SessionSettings->bAntiCheatProtected
	    << SessionSettings->BuildUniqueId;

	// First count number of advertised keys
	int32 NumAdvertisedProperties = 0;
	for (FSessionSettings::TConstIterator It(SessionSettings->Settings); It; ++It)
	{	
		const FOnlineSessionSetting& Setting = It.Value();
		if (Setting.AdvertisementType >= EOnlineDataAdvertisementType::ViaOnlineService)
		{
			NumAdvertisedProperties++;
		}
	}

	// Add count of advertised keys and the data
	Packet << (int32)NumAdvertisedProperties;
	for (FSessionSettings::TConstIterator It(SessionSettings->Settings); It; ++It)
	{
		const FOnlineSessionSetting& Setting = It.Value();
		if (Setting.AdvertisementType >= EOnlineDataAdvertisementType::ViaOnlineService)
		{
			Packet << It.Key();
			Packet << Setting;
#if DEBUG_LAN_BEACON
			UE_LOG_ONLINE(Verbose, TEXT("%s"), *Setting.ToString());
#endif
		}
	}
}
コード例 #10
0
bool FOnlineIdentityLeet::Login(int32 LocalUserNum, const FOnlineAccountCredentials& AccountCredentials)
{
	UE_LOG_ONLINE(Display, TEXT("FOnlineIdentityLeet::Login"));
	FString ErrorStr;

	if (bHasLoginOutstanding)
	{
		ErrorStr = FString::Printf(TEXT("Registration already pending for user %d"),
			LocalUserNumPendingLogin);
	}
	else if (!(LoginUrl.Len() && LoginRedirectUrl.Len() && ClientId.Len()))
	{
		ErrorStr = FString::Printf(TEXT("OnlineSubsystemLeet is improperly configured in DefaultEngine.ini LeetEndpoint=%s RedirectUrl=%s ClientId=%s"),
			*LoginUrl, *LoginRedirectUrl, *ClientId);
	}
	else
	{
		// random number to represent client generated state for verification on login
		State = FString::FromInt(FMath::Rand() % 100000);
		// auth url to spawn in browser
		const FString& Command = FString::Printf(TEXT("%s?redirect_uri=%s&client_id=%s&state=%s&response_type=token"),
			*LoginUrl, *LoginRedirectUrl, *ClientId, *State);
		UE_LOG_ONLINE(Display, TEXT("FOnlineIdentityLeet::Login - %s"), *LoginUrl);
		// This should open the browser with the command as the URL
		if (FPlatformMisc::OsExecute(TEXT("open"), *Command))
		{
			// keep track of local user requesting registration
			LocalUserNumPendingLogin = LocalUserNum;
			bHasLoginOutstanding = true;
		}
		else
		{
			ErrorStr = FString::Printf(TEXT("Failed to execute command %s"),
				*Command);
		}
	}

	if (!ErrorStr.IsEmpty())
	{
		UE_LOG(LogOnline, Error, TEXT("RegisterUser() failed: %s"),
			*ErrorStr);
		TriggerOnLoginCompleteDelegates(LocalUserNum, false, FUniqueNetIdString(TEXT("")), ErrorStr);
		return false;
	}
	return true;
}
コード例 #11
0
void FOnlineAsyncTaskSteamDeleteUserFile::Tick()
{
	bWasSuccessful = false;

	if (SteamRemoteStorage() && FileName.Len() > 0)
	{
		CSteamID SteamId(*(uint64*)UserId.GetBytes());
		if (SteamUser()->BLoggedOn() && SteamUser()->GetSteamID() == SteamId)
		{
			bool bCloudDeleteSuccess = true;
			if (bShouldCloudDelete)
			{
				// Remove the cloud flag, the file remains safely available on the local machine
				bCloudDeleteSuccess = SteamRemoteStorage()->FileForget(TCHAR_TO_UTF8(*FileName));
			}

			bool bLocalDeleteSuccess = true;
			if (bShouldLocallyDelete)
			{
				bLocalDeleteSuccess = false;
				// Only clear the tables if we're permanently deleting the file
				// Need to make sure nothing async is happening	first (this is a formality as nothing in Steam actually is)
				IOnlineUserCloudPtr UserCloud = Subsystem->GetUserCloudInterface();
				if (UserCloud->ClearFile(UserId, FileName))
				{
					// Permanent delete
					bLocalDeleteSuccess = SteamRemoteStorage()->FileDelete(TCHAR_TO_UTF8(*FileName));
					Subsystem->ClearUserCloudMetadata(UserId, FileName);
				}
			}

			bWasSuccessful = bCloudDeleteSuccess && bLocalDeleteSuccess;
		}	
		else
		{
			UE_LOG_ONLINE(Warning, TEXT("Can only delete cloud files for logged in user."));
		}
	}
	else
	{
		UE_LOG_ONLINE(Warning, TEXT("Steam remote storage API disabled."));
	}

	bIsComplete = true;
}
コード例 #12
0
bool FOnlineUserCloudOculus::DeleteUserFile(const FUniqueNetId& UserId, const FString& FileName, bool bShouldCloudDelete, bool bShouldLocallyDelete)
{
	auto LoggedInPlayerId = OculusSubsystem.GetIdentityInterface()->GetUniquePlayerId(0);
	if (!LoggedInPlayerId.IsValid() || UserId != *LoggedInPlayerId)
	{
		UE_LOG_ONLINE(Warning, TEXT("Can only save data for logged in player"));
		return false;
	}

	if (bShouldLocallyDelete && ReadCache.Contains(FileName))
	{
		ReadCache.FindAndRemoveChecked(FileName);
	}

	if (bShouldCloudDelete)
	{
		FString BucketName;
		FString Key;
		if (!(FileName.Split(SEPARATOR, &BucketName, &Key)))
		{
			BucketName = DefaultBucket;
			Key = FileName;
		}

		auto DelegateLambda = FOculusMessageOnCompleteDelegate::CreateLambda([this, BucketName, Key, LoggedInPlayerId, FileName](ovrMessageHandle Message, bool bIsError)
		{
			if (bIsError)
			{
				UE_LOG_ONLINE(Warning, TEXT("Failed to Delete: %s%s%s"), *BucketName, *SEPARATOR, *Key);
			}

			TriggerOnDeleteUserFileCompleteDelegates(!bIsError, *LoggedInPlayerId, FileName);
		});

		OculusSubsystem.AddRequestDelegate(
			ovr_CloudStorage_Delete(TCHAR_TO_UTF8(*BucketName), TCHAR_TO_UTF8(*Key)),
			std::move(DelegateLambda));
	}
	else
	{
		TriggerOnDeleteUserFileCompleteDelegates(false, *LoggedInPlayerId, FileName);
	}

	return true;
}
コード例 #13
0
bool FOnlineUserCloudOculus::GetFileContents(const FUniqueNetId& UserId, const FString& FileName, TArray<uint8>& FileContents)
{
	auto LoggedInPlayerId = OculusSubsystem.GetIdentityInterface()->GetUniquePlayerId(0);
	if (!LoggedInPlayerId.IsValid() || UserId != *LoggedInPlayerId)
	{
		UE_LOG_ONLINE(Warning, TEXT("Can only read data for logged in player"));
		return false;
	}

	if (!ReadCache.Contains(FileName))
	{
		UE_LOG_ONLINE(Warning, TEXT("No data from ReadUserFile for: %s"), *FileName);
		return false;
	}

	FileContents = ReadCache.FindAndRemoveChecked(FileName);
	return true;
}
/**
 * Give the async task a chance to marshal its data back to the game thread
 * Can only be called on the game thread by the async task manager
 */
void FOnlineAsyncEventSteamInviteAccepted::Finalize()
{
	FOnlineSessionSteamPtr SessionInt = StaticCastSharedPtr<FOnlineSessionSteam>(Subsystem->GetSessionInterface());
	if (SessionInt.IsValid() && !SessionInt->CurrentSessionSearch.IsValid())
	{
		// Create a search settings object
		TSharedRef<FOnlineSessionSearch> SearchSettings = MakeShareable(new FOnlineSessionSearch());
		SessionInt->CurrentSessionSearch = SearchSettings;
		SessionInt->CurrentSessionSearch->SearchState = EOnlineAsyncTaskState::InProgress;

		TCHAR ParsedURL[1024];
		if (!FParse::Value(*ConnectionURL, TEXT("SteamConnectIP="), ParsedURL, ARRAY_COUNT(ParsedURL)))
		{
			UE_LOG_ONLINE(Warning, TEXT("FOnlineAsyncEventSteamInviteAccepted: Failed to parse connection URL"));
			return;
		}

		// Determine the port
		int32 Port = 0;
		TCHAR* PortToken = FCString::Strchr(ParsedURL, ':');
		if (PortToken)
		{
			Port = FCString::Atoi(PortToken+1);
			PortToken[0] = '\0';
		}

		Port = (Port > 0) ? Port : Subsystem->GetGameServerGamePort();

		// Parse the address
		bool bIsValid;
		TSharedRef<FInternetAddr> IpAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
		IpAddr->SetIp(ParsedURL, bIsValid);
		if (bIsValid)
		{
			SessionInt->CurrentSessionSearch->QuerySettings.Set(FName(SEARCH_STEAM_HOSTIP), IpAddr->ToString(false), EOnlineComparisonOp::Equals);
			FOnlineAsyncTaskSteamFindServer* NewTask = new FOnlineAsyncTaskSteamFindServer(Subsystem, SearchSettings, LocalUserNum, SessionInt->OnSessionUserInviteAcceptedDelegates);
			Subsystem->QueueAsyncTask(NewTask);
		}
	}
	else
	{
		UE_LOG_ONLINE(Warning, TEXT("Invalid session or search already in progress when accepting invite.  Ignoring invite request."));
	}
}
コード例 #15
0
bool FOnlineUserCloudOculus::ReadUserFile(const FUniqueNetId& UserId, const FString& FileName)
{
	auto LoggedInPlayerId = OculusSubsystem.GetIdentityInterface()->GetUniquePlayerId(0);
	if (!LoggedInPlayerId.IsValid() || UserId != *LoggedInPlayerId)
	{
		UE_LOG_ONLINE(Warning, TEXT("Can only read data for logged in player"));
		return false;
	}

	FString BucketName;
	FString Key;
	if (!(FileName.Split(SEPARATOR, &BucketName, &Key)))
	{
		BucketName = DefaultBucket;
		Key = FileName;
	}

	OculusSubsystem.AddRequestDelegate(
		ovr_CloudStorage_Load(TCHAR_TO_UTF8(*BucketName), TCHAR_TO_UTF8(*Key)),
		FOculusMessageOnCompleteDelegate::CreateLambda([this, BucketName, Key, LoggedInPlayerId, FileName](ovrMessageHandle Message, bool bIsError)
	{
		ovrCloudStorageDataHandle response = ovr_Message_GetCloudStorageData(Message);
		check(BucketName == UTF8_TO_TCHAR(ovr_CloudStorageData_GetBucket(response)));
		check(Key == UTF8_TO_TCHAR(ovr_CloudStorageData_GetKey(response)));

		if (bIsError)
		{
			UE_LOG_ONLINE(Warning, TEXT("Failed to Load: %s%s%s"), *BucketName, *SEPARATOR, *Key);
		}
		else
		{
			int64 BlobSize = ovr_CloudStorageData_GetDataSize(response);
			const void* RawBlob = ovr_CloudStorageData_GetData(response);

			TArray<uint8> Blob;
			Blob.Insert(static_cast<const uint8 *>(RawBlob), BlobSize, 0);

			ReadCache.Add(FileName, MoveTemp(Blob));
		}
		TriggerOnReadUserFileCompleteDelegates(!bIsError, *LoggedInPlayerId, FileName);
	}));

	return true;
}
コード例 #16
0
void FOnlineUserCloudOculus::RequestEnumeratePagedBuckets(TSharedPtr<const FUniqueNetId> UserId, ovrCloudStorageMetadataArrayHandle previousPage)
{
	auto Delegate = FOculusMessageOnCompleteDelegate::CreateLambda([this, UserId](ovrMessageHandle Message, bool bIsError)
	{
		const FString& BucketName(Buckets[EnumerateBucketsCounter]);

		if (bIsError)
		{
			// NOTE: this may be too harsh.  depending on the error we might be able to keep going.
			// check when better error handling is enabled in t11136437
			UE_LOG_ONLINE(Warning, TEXT("Failed to Enumerate bucket: %s"), *BucketName);
			EnumerateBucketsCounter = -1;
			EnumerateCache.Reset();
			TriggerOnEnumerateUserFilesCompleteDelegates(false, *UserId);
			return;
		}

		ovrCloudStorageMetadataArrayHandle response = ovr_Message_GetCloudStorageMetadataArray(Message);

		// adds all the keys to the cache in the format: BucketName / Key
		for (size_t i = 0; i < ovr_CloudStorageMetadataArray_GetSize(response); i++) {
			ovrCloudStorageMetadataHandle Metadatum = ovr_CloudStorageMetadataArray_GetElement(response, i);
			FString Key = ovr_CloudStorageMetadata_GetKey(Metadatum);
			FString Filename = FString::Printf(TEXT("%s%s%s"), *BucketName, *SEPARATOR, *Key);
			unsigned int Size = ovr_CloudStorageMetadata_GetDataSize(Metadatum);
			EnumerateCache.Add(FCloudFileHeader("", Filename, Size));
		}

		// First check to see if we need to get another page of entires for this Bucket
		if (ovr_CloudStorageMetadataArray_HasNextPage(response))
		{
			RequestEnumeratePagedBuckets(UserId, response);
		}
		// see if we need to move on to the next bucket
		else if (EnumerateBucketsCounter < (Buckets.Num() - 1))
		{
			EnumerateBucketsCounter++;
			RequestEnumeratePagedBuckets(UserId, nullptr);
		}
		// Otherwise we are done - notify the App
		else
		{
			EnumerateBucketsCounter = -1;
			TriggerOnEnumerateUserFilesCompleteDelegates(true, *UserId);
		}
	});

	if (previousPage)
	{
		OculusSubsystem.AddRequestDelegate(ovr_CloudStorage_GetNextCloudStorageMetadataArrayPage(previousPage), std::move(Delegate));
	}
	else
	{
		OculusSubsystem.AddRequestDelegate(ovr_CloudStorage_LoadBucketMetadata(TCHAR_TO_UTF8(*Buckets[EnumerateBucketsCounter])), std::move(Delegate));
	}
}
コード例 #17
0
void FOnlineSubsystemOculusModule::ShutdownModule()
{
	UE_LOG_ONLINE(Log, TEXT("Oculus Shutdown!"));

	FOnlineSubsystemModule& OSS = FModuleManager::GetModuleChecked<FOnlineSubsystemModule>("OnlineSubsystem");
	OSS.UnregisterPlatformService(OCULUS_SUBSYSTEM);
	
	delete OculusFactory;
	OculusFactory = nullptr;
}
コード例 #18
0
bool FOnlineSessionNull::UnregisterPlayers(FName SessionName, const TArray< TSharedRef<const FUniqueNetId> >& Players)
{
	bool bSuccess = true;

	FNamedOnlineSession* Session = GetNamedSession(SessionName);
	if (Session)
	{
		for (int32 PlayerIdx=0; PlayerIdx < Players.Num(); PlayerIdx++)
		{
			const TSharedRef<const FUniqueNetId>& PlayerId = Players[PlayerIdx];

			FUniqueNetIdMatcher PlayerMatch(*PlayerId);
			int32 RegistrantIndex = Session->RegisteredPlayers.IndexOfByPredicate(PlayerMatch);
			if (RegistrantIndex != INDEX_NONE)
			{
				Session->RegisteredPlayers.RemoveAtSwap(RegistrantIndex);
				UnregisterVoice(*PlayerId);

				// update number of open connections
				if (Session->NumOpenPublicConnections < Session->SessionSettings.NumPublicConnections)
				{
					Session->NumOpenPublicConnections++;
				}
				else if (Session->NumOpenPrivateConnections < Session->SessionSettings.NumPrivateConnections)
				{
					Session->NumOpenPrivateConnections++;
				}
			}
			else
			{
				UE_LOG_ONLINE(Warning, TEXT("Player %s is not part of session (%s)"), *PlayerId->ToDebugString(), *SessionName.ToString());
			}
		}
	}
	else
	{
		UE_LOG_ONLINE(Warning, TEXT("No game present to leave for session (%s)"), *SessionName.ToString());
		bSuccess = false;
	}

	TriggerOnUnregisterPlayersCompleteDelegates(SessionName, Players, bSuccess);
	return bSuccess;
}
コード例 #19
0
bool FOnlineSessionNull::RegisterPlayers(FName SessionName, const TArray< TSharedRef<const FUniqueNetId> >& Players, bool bWasInvited)
{
	bool bSuccess = false;
	FNamedOnlineSession* Session = GetNamedSession(SessionName);
	if (Session)
	{
		bSuccess = true;

		for (int32 PlayerIdx=0; PlayerIdx<Players.Num(); PlayerIdx++)
		{
			const TSharedRef<const FUniqueNetId>& PlayerId = Players[PlayerIdx];

			FUniqueNetIdMatcher PlayerMatch(*PlayerId);
			if (Session->RegisteredPlayers.IndexOfByPredicate(PlayerMatch) == INDEX_NONE)
			{
				Session->RegisteredPlayers.Add(PlayerId);
				RegisterVoice(*PlayerId);

				// update number of open connections
				if (Session->NumOpenPublicConnections > 0)
				{
					Session->NumOpenPublicConnections--;
				}
				else if (Session->NumOpenPrivateConnections > 0)
				{
					Session->NumOpenPrivateConnections--;
				}
			}
			else
			{
				RegisterVoice(*PlayerId);
				UE_LOG_ONLINE(Log, TEXT("Player %s already registered in session %s"), *PlayerId->ToDebugString(), *SessionName.ToString());
			}			
		}
	}
	else
	{
		UE_LOG_ONLINE(Warning, TEXT("No game present to join for session (%s)"), *SessionName.ToString());
	}

	TriggerOnRegisterPlayersCompleteDelegates(SessionName, Players, bSuccess);
	return bSuccess;
}
コード例 #20
0
void FOnlineSubsystemOculusModule::StartupModule()
{
	UE_LOG_ONLINE(Log, TEXT("Oculus Startup!"));

	OculusFactory = new FOnlineFactoryOculus();

	// Create and register our singleton factory with the main online subsystem for easy access
	FOnlineSubsystemModule& OSS = FModuleManager::GetModuleChecked<FOnlineSubsystemModule>("OnlineSubsystem");
	OSS.RegisterPlatformService(OCULUS_SUBSYSTEM, OculusFactory);
}
コード例 #21
0
void FOnlineSubsystemImpl::OnNamedInterfaceCleanup()
{
	if (NamedInterfaces)
	{
		UE_LOG_ONLINE(Display, TEXT("Removing %d named interfaces"), NamedInterfaces->GetNumInterfaces());
		NamedInterfaces->RemoveFromRoot();
		NamedInterfaces->OnCleanup().RemoveAll(this);
		NamedInterfaces = nullptr;
	}
}
コード例 #22
0
void FOnlineAsyncTaskSteamEnumerateUserFiles::Tick()
{
	bIsComplete = true;
	bWasSuccessful = false;

	if (SteamRemoteStorage())
	{
		CSteamID SteamId(*(uint64*)UserId.GetBytes());
		if (SteamUser()->BLoggedOn() && SteamUser()->GetSteamID() == SteamId)
		{
			//SteamSubsystem->GetUserCloudInterface()->DumpCloudState(UserId);

			FScopeLock ScopeLock(&Subsystem->UserCloudDataLock);

			// Get or create the user metadata entry and empty it
			FSteamUserCloudData* UserMetadata = Subsystem->GetUserCloudEntry(UserId);

			UserMetadata->CloudMetadata.Empty();

			// Fill in the metadata entries
			const int32 FileCount = (int32) SteamRemoteStorage()->GetFileCount();
			for (int32 FileIdx = 0; FileIdx < FileCount; FileIdx++)
			{
				int32 FileSize = 0;
				const char *FileName = SteamRemoteStorage()->GetFileNameAndSize(FileIdx, &FileSize);
				new (UserMetadata->CloudMetadata) FCloudFileHeader(UTF8_TO_TCHAR(FileName), UTF8_TO_TCHAR(FileName), int32(FileSize));

				//SteamSubsystem->GetUserCloudInterface()->DumpCloudFileState(UserId, FileName);
			}

			bWasSuccessful = true;
		}
		else
		{
			UE_LOG_ONLINE(Warning, TEXT("Can only enumerate cloud files for logged in user."));
		}
	}
	else
	{
		UE_LOG_ONLINE(Warning, TEXT("Steam remote storage API disabled."));
	}
}
コード例 #23
0
EOnlineCachedResult::Type FOnlineAchievementsSteam::GetCachedAchievements(const FUniqueNetId& PlayerId, TArray<FOnlineAchievement> & OutAchievements)
{
	if (!bHaveConfiguredAchievements)
	{
		// we don't have achievements
		UE_LOG_ONLINE(Warning, TEXT("Steam achievements have not been configured in .ini"));
		return EOnlineCachedResult::NotFound;
	}

	const TArray<FOnlineAchievement> * PlayerAch = PlayerAchievements.Find(FUniqueNetIdSteam (PlayerId));
	if (NULL == PlayerAch)
	{
		// achievements haven't been read for a player
		UE_LOG_ONLINE(Warning, TEXT("Steam achievements have not been read for player %s"), *PlayerId.ToString());
		return EOnlineCachedResult::NotFound;
	}

	OutAchievements = *PlayerAch;
	return EOnlineCachedResult::Success;
};
コード例 #24
0
void FOnlineUserCloudOculus::GetUserFileList(const FUniqueNetId& UserId, TArray<FCloudFileHeader>& UserFiles)
{
	auto LoggedInPlayerId = OculusSubsystem.GetIdentityInterface()->GetUniquePlayerId(0);
	if (!LoggedInPlayerId.IsValid() || UserId != *LoggedInPlayerId)
	{
		UE_LOG_ONLINE(Warning, TEXT("Can get file list for logged in player"));
		return;
	}

	UserFiles = MoveTemp(EnumerateCache);
}
コード例 #25
0
/** 
 * Callback function into Steam error messaging system
 * @param Severity - error level
 * @param Message - message from Steam
 */
static void __cdecl SteamworksWarningMessageHook(int Severity, const char *Message)
{
	const TCHAR *MessageType;
	switch (Severity)
	{
		case 0: MessageType = TEXT("message"); break;
		case 1: MessageType = TEXT("warning"); break;
		default: MessageType = TEXT("notification"); break;  // Unknown severity; new SDK?
	}
	UE_LOG_ONLINE(Warning, TEXT("Steamworks SDK %s: %s"), MessageType, UTF8_TO_TCHAR(Message));
}
コード例 #26
0
bool FOnlineSessionNull::EndSession(FName SessionName)
{
	uint32 Result = E_FAIL;

	// Grab the session information by name
	FNamedOnlineSession* Session = GetNamedSession(SessionName);
	if (Session)
	{
		// Can't end a match that isn't in progress
		if (Session->SessionState == EOnlineSessionState::InProgress)
		{
			Session->SessionState = EOnlineSessionState::Ended;

			// If the session should be advertised and the lan beacon was destroyed, recreate
			Result = UpdateLANStatus();
		}
		else
		{
			UE_LOG_ONLINE(Warning, TEXT("Can't end session (%s) in state %s"),
				*SessionName.ToString(),
				EOnlineSessionState::ToString(Session->SessionState));
		}
	}
	else
	{
		UE_LOG_ONLINE(Warning, TEXT("Can't end an online game for session (%s) that hasn't been created"),
			*SessionName.ToString());
	}

	if (Result != ERROR_IO_PENDING)
	{
		if (Session)
		{
			Session->SessionState = EOnlineSessionState::Ended;
		}

		TriggerOnEndSessionCompleteDelegates(SessionName, (Result == ERROR_SUCCESS) ? true : false);
	}

	return Result == ERROR_SUCCESS || Result == ERROR_IO_PENDING;
}
コード例 #27
0
bool FOnlineUserCloudOculus::ClearFiles(const FUniqueNetId& UserId)
{
	auto LoggedInPlayerId = OculusSubsystem.GetIdentityInterface()->GetUniquePlayerId(0);
	if (!LoggedInPlayerId.IsValid() || UserId != *LoggedInPlayerId)
	{
		UE_LOG_ONLINE(Warning, TEXT("Can only clear data for logged in player"));
		return false;
	}

	ReadCache.Reset();
	return true;
}
コード例 #28
0
	virtual IOnlineSubsystemPtr CreateSubsystem(FName InstanceName)
	{
		FOnlineSubsystemNullPtr OnlineSub = MakeShareable(new FOnlineSubsystemNull(InstanceName));
		if (OnlineSub->IsEnabled())
		{
			if(!OnlineSub->Init())
			{
				UE_LOG_ONLINE(Warning, TEXT("Null API failed to initialize!"));
				OnlineSub->Shutdown();
				OnlineSub = NULL;
			}
		}
		else
		{
			UE_LOG_ONLINE(Warning, TEXT("Null API disabled!"));
			OnlineSub->Shutdown();
			OnlineSub = NULL;
		}

		return OnlineSub;
	}
コード例 #29
0
bool FOnlineUserCloudOculus::WriteUserFile(const FUniqueNetId& UserId, const FString& FileName, TArray<uint8>& FileContents)
{
	auto LoggedInPlayerId = OculusSubsystem.GetIdentityInterface()->GetUniquePlayerId(0);
	if (!LoggedInPlayerId.IsValid() || UserId != *LoggedInPlayerId)
	{
		UE_LOG_ONLINE(Warning, TEXT("Can only save data for logged in player"));
		return false;
	}

	FString BucketName;
	FString Key;
	if (!(FileName.Split(SEPARATOR, &BucketName, &Key)))
	{
		BucketName = DefaultBucket;
		Key = FileName;
	}

	// store the save data in a temporary buffer until the Oculus Platform threadpool can process the request
	TArray<uint8> *TmpBuffer = new TArray<uint8>(MoveTemp(FileContents));

	auto DelegateLambda = FOculusMessageOnCompleteDelegate::CreateLambda([this, BucketName, Key, LoggedInPlayerId, FileName, TmpBuffer](ovrMessageHandle Message, bool bIsError)
	{
		check(BucketName == UTF8_TO_TCHAR(ovr_CloudStorageUpdateResponse_GetBucket(ovr_Message_GetCloudStorageUpdateResponse(Message))));
		check(Key == UTF8_TO_TCHAR(ovr_CloudStorageUpdateResponse_GetKey(ovr_Message_GetCloudStorageUpdateResponse(Message))));

		if (bIsError)
		{
			UE_LOG_ONLINE(Warning, TEXT("Failed to Save: %s%s%s"), *BucketName, *SEPARATOR, *Key);
		}

		delete TmpBuffer;
		TriggerOnWriteUserFileCompleteDelegates(!bIsError, *LoggedInPlayerId, FileName);
	});

	OculusSubsystem.AddRequestDelegate(
		ovr_CloudStorage_Save(TCHAR_TO_UTF8(*BucketName), TCHAR_TO_UTF8(*Key), TmpBuffer->GetData(), TmpBuffer->Num(), 0, nullptr),
		std::move(DelegateLambda));

	return true;
}
コード例 #30
0
bool FOnlineSubsystemSteam::Shutdown()
{
	UE_LOG_ONLINE(Display, TEXT("OnlineSubsystemSteam::Shutdown()"));

	FOnlineSubsystemImpl::Shutdown();

	if (OnlineAsyncTaskThread)
	{
		// Destroy the online async task thread
		delete OnlineAsyncTaskThread;
		OnlineAsyncTaskThread = nullptr;
	}

	if (OnlineAsyncTaskThreadRunnable)
	{
		delete OnlineAsyncTaskThreadRunnable;
		OnlineAsyncTaskThreadRunnable = nullptr;
	}
	
	#define DESTRUCT_INTERFACE(Interface) \
	if (Interface.IsValid()) \
	{ \
		ensure(Interface.IsUnique()); \
		Interface = nullptr; \
	}

	// Destruct the interfaces
	DESTRUCT_INTERFACE(AchievementsInterface);
	DESTRUCT_INTERFACE(ExternalUIInterface);
	DESTRUCT_INTERFACE(VoiceInterface);
	DESTRUCT_INTERFACE(LeaderboardsInterface);
	DESTRUCT_INTERFACE(SharedCloudInterface);
	DESTRUCT_INTERFACE(UserCloudInterface);
	DESTRUCT_INTERFACE(FriendInterface);
	DESTRUCT_INTERFACE(IdentityInterface);
	DESTRUCT_INTERFACE(SessionInterface);

	#undef DESTRUCT_INTERFACE

	ClearUserCloudFiles();

	DestroySteamSocketSubsystem();

	ShutdownSteamworks();

#if !UE_BUILD_SHIPPING && !UE_BUILD_SHIPPING_WITH_EDITOR
	DeleteSteamAppIdFromDisk();
#endif // !UE_BUILD_SHIPPING && !UE_BUILD_SHIPPING_WITH_EDITOR

	return true;
}