FArchive& operator<<( FArchive& Ar, FUniqueNetIdRepl& UniqueNetId) { int32 Size = UniqueNetId.IsValid() ? UniqueNetId->GetSize() : 0; Ar << Size; if (Size > 0) { if (Ar.IsSaving()) { check(UniqueNetId.IsValid()); FString Contents = UniqueNetId->ToString(); Ar << Contents; } else if (Ar.IsLoading()) { FString Contents; Ar << Contents; // that takes care about possible overflow // Don't need to distinguish OSS interfaces here with world because we just want the create function below IOnlineIdentityPtr IdentityInt = Online::GetIdentityInterface(); if (IdentityInt.IsValid()) { TSharedPtr<FUniqueNetId> UniqueNetIdPtr = IdentityInt->CreateUniquePlayerId(Contents); UniqueNetId.SetUniqueNetId(UniqueNetIdPtr); } } } return Ar; }
bool FOnlineLeaderboardsNull::ReadLeaderboardsForFriends(int32 LocalUserNum, FOnlineLeaderboardReadRef& ReadObject) { TArray< TSharedRef<const FUniqueNetId> > FriendsList; // always add a UniqueNetId for local user check(NullSubsystem); IOnlineIdentityPtr Identity = NullSubsystem->GetIdentityInterface(); if (Identity.IsValid()) { if (Identity->GetUniquePlayerId(LocalUserNum).IsValid()) { FriendsList.Add(Identity->GetUniquePlayerId(LocalUserNum).ToSharedRef()); } } // add all known players FLeaderboardNull* Leaderboard = Leaderboards.Find(ReadObject->LeaderboardName); if (Leaderboard) { for (int32 UserIdx = 0; UserIdx < Leaderboard->Rows.Num(); ++UserIdx) { if (Leaderboard->Rows[UserIdx].PlayerId.IsValid()) { FriendsList.AddUnique(Leaderboard->Rows[UserIdx].PlayerId.ToSharedRef()); } } } return ReadLeaderboards(FriendsList, ReadObject); }
virtual void FireEvent_FlushChatStats() override { if (AnalyticsProvider.IsValid()) { IOnlineIdentityPtr OnlineIdentity = Online::GetIdentityInterface(TEXT("MCP")); if (OnlineIdentity.IsValid()) { TSharedPtr<const FUniqueNetId> UserId = OnlineIdentity->GetUniquePlayerId(0); if (UserId.IsValid()) { auto RecordSocialChatCountsEvents = [=](const TMap<FString, int32>& ChatCounts, const FString& ChatType) { if (ChatCounts.Num()) { TArray<FAnalyticsEventAttribute> Attributes; for (const auto& Pair : ChatCounts) { Attributes.Empty(3); Attributes.Emplace(TEXT("Name"), Pair.Key); Attributes.Emplace(TEXT("Type"), ChatType); Attributes.Emplace(TEXT("Count"), Pair.Value); AnalyticsProvider->RecordEvent("Social.Chat.Counts.2", Attributes); } } }; RecordSocialChatCountsEvents(ChannelChatCounts, TEXT("Channel")); RecordSocialChatCountsEvents(PrivateChatCounts, TEXT("Private")); } } } ChannelChatCounts.Empty(); PrivateChatCounts.Empty(); }
/** * 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 } }
virtual bool SupportsOnlinePIE() const override { const UOnlinePIESettings* OnlinePIESettings = GetDefault<UOnlinePIESettings>(); if (OnlinePIESettings->bOnlinePIEEnabled && GetNumPIELogins() > 0) { // If we can't get the identity interface then things are either not configured right or disabled IOnlineIdentityPtr IdentityInt = Online::GetIdentityInterface(); return IdentityInt.IsValid(); } return false; }
void AShooterPlayerController::GameHasEnded(class AActor* EndGameFocus, bool bIsWinner) { // write stats ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(Player); if (LocalPlayer) { AShooterPlayerState* ShooterPlayerState = Cast<AShooterPlayerState>(PlayerState); if (ShooterPlayerState) { // update local saved profile UShooterPersistentUser* const PersistentUser = GetPersistentUser(); if (PersistentUser) { PersistentUser->AddMatchResult( ShooterPlayerState->GetKills(), ShooterPlayerState->GetDeaths(), ShooterPlayerState->GetNumBulletsFired(), ShooterPlayerState->GetNumRocketsFired(), bIsWinner); PersistentUser->SaveIfDirty(); } // update achievements UpdateAchievementsOnGameEnd(); // update leaderboards IOnlineSubsystem* const OnlineSub = IOnlineSubsystem::Get(); if(OnlineSub) { IOnlineIdentityPtr Identity = OnlineSub->GetIdentityInterface(); if (Identity.IsValid()) { TSharedPtr<FUniqueNetId> UserId = Identity->GetUniquePlayerId(LocalPlayer->ControllerId); if (UserId.IsValid()) { IOnlineLeaderboardsPtr Leaderboards = OnlineSub->GetLeaderboardsInterface(); if (Leaderboards.IsValid()) { FShooterAllTimeMatchResultsWrite WriteObject; WriteObject.SetIntStat(LEADERBOARD_STAT_SCORE, ShooterPlayerState->GetKills()); WriteObject.SetIntStat(LEADERBOARD_STAT_KILLS, ShooterPlayerState->GetKills()); WriteObject.SetIntStat(LEADERBOARD_STAT_DEATHS, ShooterPlayerState->GetDeaths()); WriteObject.SetIntStat(LEADERBOARD_STAT_MATCHESPLAYED, 1); // the call will copy the user id and write object to its own memory Leaderboards->WriteLeaderboards(ShooterPlayerState->SessionName, *UserId, WriteObject); } } } } } } Super::GameHasEnded(EndGameFocus, bIsWinner); }
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 FFriendsMessageManager::Init( FOnFriendsNotification& NotificationDelegate, bool bInCanJointGame ) { // Clear existing data Logout(); FriendsListNotificationDelegate = &NotificationDelegate; bCanJoinGame = bInCanJointGame; bPollForMessages = false; OnlineSubMcp = static_cast< FOnlineSubsystemMcp* >( IOnlineSubsystem::Get( TEXT( "MCP" ) ) ); if (OnlineSubMcp != NULL && OnlineSubMcp->GetIdentityInterface().IsValid() && OnlineSubMcp->GetMessageInterface().IsValid()) { // Add our delegate for the async call OnEnumerateMessagesCompleteDelegate = FOnEnumerateMessagesCompleteDelegate::CreateSP(this, &FFriendsMessageManager::OnEnumerateMessagesComplete); OnReadMessageCompleteDelegate = FOnReadMessageCompleteDelegate::CreateSP(this, &FFriendsMessageManager::OnReadMessageComplete); OnSendMessageCompleteDelegate = FOnSendMessageCompleteDelegate::CreateSP(this, &FFriendsMessageManager::OnSendMessageComplete); OnDeleteMessageCompleteDelegate = FOnDeleteMessageCompleteDelegate::CreateSP(this, &FFriendsMessageManager::OnDeleteMessageComplete); OnlineSubMcp->GetMessageInterface()->AddOnEnumerateMessagesCompleteDelegate(0, OnEnumerateMessagesCompleteDelegate); OnlineSubMcp->GetMessageInterface()->AddOnReadMessageCompleteDelegate(0, OnReadMessageCompleteDelegate); OnlineSubMcp->GetMessageInterface()->AddOnSendMessageCompleteDelegate(0, OnSendMessageCompleteDelegate); OnlineSubMcp->GetMessageInterface()->AddOnDeleteMessageCompleteDelegate(0, OnDeleteMessageCompleteDelegate); IOnlineIdentityPtr OnlineIdentity = OnlineSubMcp->GetIdentityInterface(); TSharedPtr<FUniqueNetId> UserId = OnlineIdentity->GetUniquePlayerId(0); if ( UserId.IsValid() ) { DisplayName = OnlineIdentity->GetUserAccount( *UserId )->GetDisplayName(); } if ( UpdateMessagesTickerDelegate.IsBound() == false ) { UpdateMessagesTickerDelegate = FTickerDelegate::CreateSP( this, &FFriendsMessageManager::Tick ); } ManagerState = EFriendsMessageManagerState::Idle; FTicker::GetCoreTicker().AddTicker( UpdateMessagesTickerDelegate ); } }
bool FOnlineSubsystemImpl::IsLocalPlayer(const FUniqueNetId& UniqueId) const { if (!IsDedicated()) { IOnlineIdentityPtr IdentityInt = GetIdentityInterface(); if (IdentityInt.IsValid()) { for (int32 LocalUserNum = 0; LocalUserNum < MAX_LOCAL_PLAYERS; LocalUserNum++) { TSharedPtr<const FUniqueNetId> LocalUniqueId = IdentityInt->GetUniquePlayerId(LocalUserNum); if (LocalUniqueId.IsValid() && UniqueId == *LocalUniqueId) { return true; } } } } return false; }
bool FOnlineSubsystemImpl::HandleFriendExecCommands(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar) { bool bWasHandled = false; if (FParse::Command(&Cmd, TEXT("BLOCK"))) { FString LocalNumStr = FParse::Token(Cmd, false); int32 LocalNum = FCString::Atoi(*LocalNumStr); FString UserId = FParse::Token(Cmd, false); if (UserId.IsEmpty() || LocalNum < 0 || LocalNum > MAX_LOCAL_PLAYERS) { UE_LOG_ONLINE(Warning, TEXT("usage: FRIEND BLOCK <localnum> <userid>")); } else { IOnlineIdentityPtr IdentityInt = GetIdentityInterface(); if (IdentityInt.IsValid()) { TSharedPtr<const FUniqueNetId> BlockUserId = IdentityInt->CreateUniquePlayerId(UserId); IOnlineFriendsPtr FriendsInt = GetFriendsInterface(); if (FriendsInt.IsValid()) { FriendsInt->BlockPlayer(0, *BlockUserId); } } } } else if (FParse::Command(&Cmd, TEXT("DUMPBLOCKED"))) { IOnlineFriendsPtr FriendsInt = GetFriendsInterface(); if (FriendsInt.IsValid()) { FriendsInt->DumpBlockedPlayers(); } bWasHandled = true; } return bWasHandled; }
bool FOnlineSessionNull::CreateSession(int32 HostingPlayerNum, FName SessionName, const FOnlineSessionSettings& NewSessionSettings) { uint32 Result = E_FAIL; // Check for an existing session FNamedOnlineSession* Session = GetNamedSession(SessionName); if (Session == NULL) { // Create a new session and deep copy the game settings Session = AddNamedSession(SessionName, NewSessionSettings); check(Session); Session->SessionState = EOnlineSessionState::Creating; Session->NumOpenPrivateConnections = NewSessionSettings.NumPrivateConnections; Session->NumOpenPublicConnections = NewSessionSettings.NumPublicConnections; // always start with full public connections, local player will register later Session->HostingPlayerNum = HostingPlayerNum; check(NullSubsystem); IOnlineIdentityPtr Identity = NullSubsystem->GetIdentityInterface(); if (Identity.IsValid()) { Session->OwningUserId = Identity->GetUniquePlayerId(HostingPlayerNum); Session->OwningUserName = Identity->GetPlayerNickname(HostingPlayerNum); } // if did not get a valid one, use just something if (!Session->OwningUserId.IsValid()) { Session->OwningUserId = MakeShareable(new FUniqueNetIdString(FString::Printf(TEXT("%d"), HostingPlayerNum))); Session->OwningUserName = FString(TEXT("NullUser")); } // Unique identifier of this build for compatibility Session->SessionSettings.BuildUniqueId = GetBuildUniqueId(); // Setup the host session info FOnlineSessionInfoNull* NewSessionInfo = new FOnlineSessionInfoNull(); NewSessionInfo->Init(*NullSubsystem); Session->SessionInfo = MakeShareable(NewSessionInfo); Result = UpdateLANStatus(); if (Result != ERROR_IO_PENDING) { // Set the game state as pending (not started) Session->SessionState = EOnlineSessionState::Pending; if (Result != ERROR_SUCCESS) { // Clean up the session info so we don't get into a confused state RemoveNamedSession(SessionName); } else { RegisterLocalPlayers(Session); } } } else { UE_LOG_ONLINE(Warning, TEXT("Cannot create session '%s': session already exists."), *SessionName.ToString()); } if (Result != ERROR_IO_PENDING) { TriggerOnCreateSessionCompleteDelegates(SessionName, (Result == ERROR_SUCCESS) ? true : false); } return Result == ERROR_IO_PENDING || Result == ERROR_SUCCESS; }
void TestUniqueIdRepl(UWorld* InWorld) { bool bSuccess = true; IOnlineIdentityPtr IdentityPtr = Online::GetIdentityInterface(InWorld); if (IdentityPtr.IsValid()) { TSharedPtr<FUniqueNetId> UserId = IdentityPtr->GetUniquePlayerId(0); FUniqueNetIdRepl EmptyIdIn; if (EmptyIdIn.IsValid()) { UE_LOG(LogNet, Warning, TEXT("EmptyId is valid."), *EmptyIdIn->ToString()); bSuccess = false; } FUniqueNetIdRepl ValidIdIn(UserId); if (!ValidIdIn.IsValid() || UserId != ValidIdIn.GetUniqueNetId()) { UE_LOG(LogNet, Warning, TEXT("UserId input %s != UserId output %s"), *UserId->ToString(), *ValidIdIn->ToString()); bSuccess = false; } if (bSuccess) { TArray<uint8> Buffer; for (int32 i=0; i<2; i++) { Buffer.Empty(); FMemoryWriter TestWriteUniqueId(Buffer); if (i == 0) { // Normal serialize TestWriteUniqueId << EmptyIdIn; TestWriteUniqueId << ValidIdIn; } else { // Net serialize bool bSuccess = false; EmptyIdIn.NetSerialize(TestWriteUniqueId, NULL, bSuccess); ValidIdIn.NetSerialize(TestWriteUniqueId, NULL, bSuccess); } FMemoryReader TestReadUniqueId(Buffer); FUniqueNetIdRepl EmptyIdOut; TestReadUniqueId << EmptyIdOut; if (EmptyIdOut.GetUniqueNetId().IsValid()) { UE_LOG(LogNet, Warning, TEXT("EmptyId %s should have been invalid"), *EmptyIdOut->ToString()); bSuccess = false; } FUniqueNetIdRepl ValidIdOut; TestReadUniqueId << ValidIdOut; if (*UserId != *ValidIdOut.GetUniqueNetId()) { UE_LOG(LogNet, Warning, TEXT("UserId input %s != UserId output %s"), *ValidIdIn->ToString(), *ValidIdOut->ToString()); bSuccess = false; } } } } if (!bSuccess) { UE_LOG(LogNet, Warning, TEXT("TestUniqueIdRepl test failure!")); } }
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); } }