void UUpdateManager::StartPlatformEnvironmentCheck()
{
	IOnlineSubsystem* OnlineSubConsole = IOnlineSubsystem::GetByPlatform();
	if (!bPlatformEnvironmentDetected &&
		OnlineSubConsole != nullptr &&
		OnlineSubConsole->GetIdentityInterface().IsValid())
	{
		SetUpdateState(EUpdateState::DetectingPlatformEnvironment);

		ULocalPlayer* LP = GetGameInstance()->GetFirstGamePlayer();
		if (LP != nullptr)
		{
			const int32 ControllerId = LP->GetControllerId();
			OnLoginConsoleCompleteHandle = OnlineSubConsole->GetIdentityInterface()->AddOnLoginCompleteDelegate_Handle(
				ControllerId,
				FOnLoginCompleteDelegate::CreateUObject(this, &ThisClass::PlatformEnvironmentCheck_OnLoginConsoleComplete)
				);

			OnlineSubConsole->GetIdentityInterface()->Login(ControllerId, FOnlineAccountCredentials());
		}
	}
	else
	{
		StartHotfixCheck();
	}
}
void APuzzlePresetPlayerController::OnEndTurn()
{
	/*UPuzzlePresetGameInstance* ppgi = Cast<UPuzzlePresetGameInstance>(GetGameInstance());
	ULocalPlayer* LocalPlayer = GetLocalPlayer();
	ppgi->HostSession(MakeShareable(LocalPlayer->GetControllerId()),)
	return;*/

	IOnlineSubsystem* ion = IOnlineSubsystem::Get(FName("Steam"));

	if (ion != nullptr)
	{
		ULocalPlayer* LocalPlayer = GetLocalPlayer();
		if (LocalPlayer && LocalPlayer->GetControllerId() != -1)
		{
			UE_LOG(LogTemp, Warning, TEXT("steam user name: %s"), *PlayerState->PlayerName);
			uint8 status = ion->GetIdentityInterface()->GetLoginStatus(LocalPlayer->GetControllerId());
			UE_LOG(LogTemp, Warning, TEXT("steam user status: %d"), status);
		}

		/*if (ion->InitSteamworksClient(false, 480))
		{
		UE_LOG(LogTemp, Warning, TEXT("Steam API initialized succesfully!"));
		}
		else
		{
		UE_LOG(LogTemp, Warning, TEXT("Failed to initialize Steam API :("));
		}*/
	}
}
void FTestCloudInterface::Test()
{
	IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get(FName(*Subsystem));
	check(OnlineSub); 

	if (OnlineSub->GetIdentityInterface().IsValid())
	{
		UserId = OnlineSub->GetIdentityInterface()->GetUniquePlayerId(0);
	}
	if (UserId.IsValid())
	{
		// Cache interfaces
		UserCloud = OnlineSub->GetUserCloudInterface();
		if (UserCloud.IsValid())
		{
			// Setup delegates
			EnumerationDelegate = FOnEnumerateUserFilesCompleteDelegate::CreateRaw(this, &FTestCloudInterface::OnEnumerateUserFilesComplete);
			OnWriteUserCloudFileCompleteDelegate = FOnWriteUserFileCompleteDelegate::CreateRaw(this, &FTestCloudInterface::OnWriteUserCloudFileComplete);
			OnReadEnumeratedUserFilesCompleteDelegate = FOnReadUserFileCompleteDelegate::CreateRaw(this, &FTestCloudInterface::OnReadEnumeratedUserFilesComplete);
			OnDeleteEnumeratedUserFilesCompleteDelegate = FOnDeleteUserFileCompleteDelegate::CreateRaw(this, &FTestCloudInterface::OnDeleteEnumeratedUserFilesComplete);

			SharedCloud = OnlineSub->GetSharedCloudInterface();
			if (SharedCloud.IsValid())
			{
				OnWriteSharedCloudFileCompleteDelegate = FOnWriteSharedFileCompleteDelegate::CreateRaw(this, &FTestCloudInterface::OnWriteSharedCloudFileComplete);
				OnReadEnumerateSharedFileCompleteDelegate = FOnReadSharedFileCompleteDelegate::CreateRaw(this, &FTestCloudInterface::OnReadEnumeratedSharedFileCompleteDelegate);

				// Pre-generated content
				SharedCloud->GetDummySharedHandlesForTest(RandomSharedFileHandles);
			}
		}
		else
		{
			UE_LOG(LogOnline, Warning, TEXT("Cloud test failed.  Cloud API not supported."));
			delete this;
		}
	}
	else
	{
		UE_LOG(LogOnline, Warning, TEXT("Cloud test failed.  No logged in user."));
		delete this;
	}
}
/** 
 * Serialize the voice packet data to a buffer 
 *
 * @param Ar buffer to write into
 */
void FVoicePacketImpl::Serialize(class FArchive& Ar)
{
	// Make sure not to overflow the buffer by reading an invalid amount
	if (Ar.IsLoading())
	{
		FString SenderStr;
		Ar << SenderStr;

		// Don't need to distinguish OSS interfaces here with world because we just want the create function below
		IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
		IOnlineIdentityPtr IdentityInt = OnlineSub->GetIdentityInterface();
		if (IdentityInt.IsValid())
		{
			Sender = IdentityInt->CreateUniquePlayerId(SenderStr);
		}

		Ar << Length;
		// Verify the packet is a valid size
		if (Length <= MAX_VOICE_DATA_SIZE)
		{
			Buffer.Empty(Length);
			Buffer.AddUninitialized(Length);
			Ar.Serialize(Buffer.GetData(), Length);

#if DEBUG_VOICE_PACKET_ENCODING
			uint32 CRC = 0;
			Ar << CRC;
			if (CRC != FCrc::MemCrc32(Buffer.GetData(), Length))
			{
				UE_LOG(LogVoice, Warning, TEXT("CRC Mismatch in voice packet"));
				Length = 0;
			}
#endif
		}
		else
		{
			Length = 0;
		}
	}
	else
	{
		check(Sender.IsValid());
		FString SenderStr = Sender->ToString();
		Ar << SenderStr;
		Ar << Length;

		// Always safe to save the data as the voice code prevents overwrites
		Ar.Serialize(Buffer.GetData(), Length);

#if DEBUG_VOICE_PACKET_ENCODING
		uint32 CRC = FCrc::MemCrc32(Buffer.GetData(), Length);
		Ar << CRC;
#endif
	}
}
void AShooterPlayerController::UpdateAchievementProgress( const FString& Id, float Percent )
{
	ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(Player);
	if (LocalPlayer)
	{
		IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
		if(OnlineSub)
		{
			IOnlineIdentityPtr Identity = OnlineSub->GetIdentityInterface();
			if (Identity.IsValid())
			{
				TSharedPtr<FUniqueNetId> UserId = Identity->GetUniquePlayerId(LocalPlayer->ControllerId);

				if (UserId.IsValid())
				{

					IOnlineAchievementsPtr Achievements = OnlineSub->GetAchievementsInterface();
					if (Achievements.IsValid() && (!WriteObject.IsValid() || WriteObject->WriteState != EOnlineAsyncTaskState::InProgress))
					{
						WriteObject = MakeShareable(new FOnlineAchievementsWrite());
						WriteObject->SetFloatStat(*Id, Percent);

						FOnlineAchievementsWriteRef WriteObjectRef = WriteObject.ToSharedRef();
						Achievements->WriteAchievements(*UserId.Get(), WriteObjectRef);
					}
					else
					{
						UE_LOG(LogOnline, Warning, TEXT("No valid achievement interface or another write is in progress."));
					}
				}
				else
				{
					UE_LOG(LogOnline, Warning, TEXT("No valid user id for this controller."));
				}
			}
			else
			{
				UE_LOG(LogOnline, Warning, TEXT("No valid identity interface."));
			}
		}
		else
		{
			UE_LOG(LogOnline, Warning, TEXT("No default online subsystem."));
		}
	}
	else
	{
		UE_LOG(LogOnline, Warning, TEXT("No local player, cannot update achievements."));
	}
}
void AShooterPlayerController::QueryAchievements()
{
	// precache achievements
	ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(Player);
	if (LocalPlayer)
	{
		IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
		if(OnlineSub)
		{
			IOnlineIdentityPtr Identity = OnlineSub->GetIdentityInterface();
			if (Identity.IsValid())
			{
				TSharedPtr<FUniqueNetId> UserId = Identity->GetUniquePlayerId(LocalPlayer->ControllerId);

				if (UserId.IsValid())
				{
					IOnlineAchievementsPtr Achievements = OnlineSub->GetAchievementsInterface();

					if (Achievements.IsValid())
					{
						Achievements->QueryAchievements( *UserId.Get(), FOnQueryAchievementsCompleteDelegate::CreateUObject( this, &AShooterPlayerController::OnQueryAchievementsComplete ));
					}
				}
				else
				{
					UE_LOG(LogOnline, Warning, TEXT("No valid user id for this controller."));
				}
			}
			else
			{
				UE_LOG(LogOnline, Warning, TEXT("No valid identity interface."));
			}
		}
		else
		{
			UE_LOG(LogOnline, Warning, TEXT("No default online subsystem."));
		}
	}
	else
	{
		UE_LOG(LogOnline, Warning, TEXT("No local player, cannot read achievements."));
	}
}
void FTestEntitlementsInterface::Test(UWorld* InWorld)
{
	IOnlineSubsystem* OSS = Online::GetSubsystem(InWorld, SubsystemName.Len() ? FName(*SubsystemName, FNAME_Find) : NAME_None);

	IdentityOSS = OSS->GetIdentityInterface();
	if (IdentityOSS.IsValid())
	{
		UserId = IdentityOSS->GetUniquePlayerId(LocalUserIdx);
	}
	if (UserId.IsValid() && UserId->IsValid())
	{
		EntitlementsOSS = OSS->GetEntitlementsInterface();
		if (EntitlementsOSS.IsValid())
		{
			// Add delegates for the various async calls
			OnQueryEntitlementsCompleteDelegateHandle = EntitlementsOSS->AddOnQueryEntitlementsCompleteDelegate_Handle(OnQueryEntitlementsCompleteDelegate);

			// kick off next test
			StartNextTest();
		}
		else
		{
			UE_LOG(LogOnline, Warning, TEXT("Entitlement test failed. Failed to get entitlement service API"));

			// done with the test
			FinishTest();
		}
	}
	else
	{
		UE_LOG(LogOnline, Warning, TEXT("Entitlement test failed. No logged in user"));

		// done with the test
		FinishTest();
	}
}
void UUpdateManager::StartPatchCheck()
{
	ensure(ChecksEnabled());

	UGameInstance* GameInstance = GetGameInstance();
	check(GameInstance);
	bool bStarted = false;

	SetUpdateState(EUpdateState::CheckingForPatch);

	IOnlineSubsystem* OnlineSubConsole = IOnlineSubsystem::GetByPlatform();
	if (OnlineSubConsole)
	{
		IOnlineIdentityPtr OnlineIdentityConsole = OnlineSubConsole->GetIdentityInterface();
		if (OnlineIdentityConsole.IsValid())
		{
			ULocalPlayer* LP = GameInstance->GetFirstGamePlayer();
			if (LP != nullptr)
			{
				const int32 ControllerId = LP->GetControllerId();
				TSharedPtr<const FUniqueNetId> UserId = OnlineIdentityConsole->GetUniquePlayerId(ControllerId);
				if (UserId.IsValid())
				{
					bStarted = true;
					OnlineIdentityConsole->GetUserPrivilege(*UserId,
						EUserPrivileges::CanPlayOnline, IOnlineIdentity::FOnGetUserPrivilegeCompleteDelegate::CreateUObject(this, &ThisClass::OnCheckForPatchComplete, true));
				}
				else
				{
					UE_LOG(LogHotfixManager, Warning, TEXT("No valid platform user id when starting patch check!"));
				}
			}
			else
			{
				UE_LOG(LogHotfixManager, Warning, TEXT("No local player to perform check!"));
			}
		}
	}
	else
	{
		if (GameInstance->IsDedicatedServerInstance())
		{
			bStarted = true;
			PatchCheckComplete(EPatchCheckResult::NoPatchRequired);
		}
		else
		{
			UWorld* World = GetWorld();
			IOnlineIdentityPtr IdentityInt = Online::GetIdentityInterface(World);
			if (IdentityInt.IsValid())
			{
				ULocalPlayer* LP = GameInstance->GetFirstGamePlayer();
				if (LP != nullptr)
				{
					const int32 ControllerId = LP->GetControllerId();
					TSharedPtr<const FUniqueNetId> UserId = IdentityInt->GetUniquePlayerId(ControllerId);
					if (!bInitialUpdateFinished && !UserId.IsValid())
					{
						// Invalid user for "before title/login" check, underlying code doesn't need a valid user currently
						UserId = IdentityInt->CreateUniquePlayerId(TEXT("InvalidUser"));
					}

					if (UserId.IsValid())
					{
						bStarted = true;
						IdentityInt->GetUserPrivilege(*UserId,
							EUserPrivileges::CanPlayOnline, IOnlineIdentity::FOnGetUserPrivilegeCompleteDelegate::CreateUObject(this, &ThisClass::OnCheckForPatchComplete, false));
					}
					else
					{
						UE_LOG(LogHotfixManager, Warning, TEXT("No valid user id when starting patch check!"));
					}
				}
				else
				{
					UE_LOG(LogHotfixManager, Warning, TEXT("No local player to perform check!"));
				}
			}
		}
	}

	if (!bStarted)
	{
		// Any failure to call GetUserPrivilege will result in completing the flow via this path
		PatchCheckComplete(EPatchCheckResult::PatchCheckFailure);
	}
}