Documentation for the Unreal C++ Library
Loading...
Searching...
No Matches
PVROMultiplayerIdentity.cpp
Go to the documentation of this file.
1// Copyright(c) 2023 PixoVR, LLC. All Rights Reserved.
2
4#include "Misc/CommandLine.h"
5#include "Misc/Guid.h"
6#include "Misc/OutputDeviceRedirector.h"
7#include "PVROSubsystem.h"
8#include "IPAddress.h"
9#include "SocketSubsystem.h"
10#include "OnlineError.h"
11
12#include "PVROPrivate.h"
13
14DEFINE_LOG_CATEGORY_STATIC(LogPVROMultiplayerIdentity, Log, All);
15
16#define Log(pmt, ...) UE_LOG(LogPVROMultiplayerIdentity, Log, TEXT(pmt), ##__VA_ARGS__)
17#define Warn(pmt, ...) UE_LOG(LogPVROMultiplayerIdentity, Warning, TEXT(pmt), ##__VA_ARGS__)
18#define Error(pmt, ...) UE_LOG(LogPVROMultiplayerIdentity, Error, TEXT(pmt), ##__VA_ARGS__)
19#define Fatal(pmt, ...) UE_LOG(LogPVROMultiplayerIdentity, Fatal, TEXT(pmt), ##__VA_ARGS__)
20
21bool FPVROUserAccount::GetAuthAttribute(const FString& AttrName, FString& OutAttrValue) const
22{
23 const FString* FoundAttr = AdditionalAuthData.Find(AttrName);
24 if (FoundAttr != nullptr)
25 {
26 OutAttrValue = *FoundAttr;
27 return true;
28 }
29 return false;
30}
31
32bool FPVROUserAccount::GetUserAttribute(const FString& AttrName, FString& OutAttrValue) const
33{
34 const FString* FoundAttr = UserAttributes.Find(AttrName);
35 if (FoundAttr != nullptr)
36 {
37 OutAttrValue = *FoundAttr;
38 return true;
39 }
40 return false;
41}
42
43bool FPVROUserAccount::SetUserAttribute(const FString& AttrName, const FString& AttrValue)
44{
45 const FString* FoundAttr = UserAttributes.Find(AttrName);
46 if (FoundAttr == nullptr || *FoundAttr != AttrValue)
47 {
48 UserAttributes.Add(AttrName, AttrValue);
49 return true;
50 }
51 return false;
52}
53
54inline FString GenerateRandomUserId(int32 LocalUserNum)
55{
56 FString HostName;
57 if (!ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->GetHostName(HostName))
58 {
59 // could not get hostname, use address
60 bool bCanBindAll;
61 TSharedPtr<class FInternetAddr> Addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->GetLocalHostAddr(*GLog, bCanBindAll);
62 HostName = Addr->ToString(false);
63 }
64
65 if ( !GIsEditor )
66 {
67 FString UserId = FString::Printf( TEXT( "%s-%s" ), *HostName, *FPlatformMisc::GetLoginId().ToUpper() );
68 if(!FParse::Value(FCommandLine::Get(), TEXT("-PVRMP_SERVER_NAME="), UserId))
69 {
70 // OK, we failed to find the module version reading from the terminal. Let's check the ini files.
71 if(GConfig && !GConfig->GetString(TEXT("PixoVRMultiplayer"), TEXT("ServerName"), UserId, GEngineIni))
72 {
73 UserId = "PVROServer";
74 }
75 }
76
77 // When possible, return a stable user id
78 return UserId;
79 }
80
81
82 // If we're not the first instance (or in the editor), return truly random id
83 return FString::Printf( TEXT( "%s-%s" ), *HostName, *FGuid::NewGuid().ToString() );
84}
85
86bool FPVROIdentity::Login(int32 LocalUserNum, const FOnlineAccountCredentials& AccountCredentials)
87{
88 FString ErrorStr;
89 TSharedPtr<FPVROUserAccount> UserAccountPtr;
90
91 // Do we have a valid Local Player index?
92 if (LocalUserNum < 0 || LocalUserNum >= MAX_LOCAL_PLAYERS)
93 {
94 ErrorStr = FString::Printf(TEXT("Invalid LocalUserNum=%d"), LocalUserNum);
95 }
96 else if (AccountCredentials.Id.IsEmpty())
97 {
98 ErrorStr = TEXT("Invalid account id, string empty");
99 }
100 else
101 {
102 FUniqueNetIdPtr* UserId = UserIds.Find(LocalUserNum);
103 if (UserId == nullptr)
104 {
105 FString RandomUserId = GenerateRandomUserId(LocalUserNum);
106
107 UserAccountPtr = MakeShareable(new FPVROUserAccount(RandomUserId));
108 UserAccountPtr->UserAttributes.Add(USER_ATTR_ID, RandomUserId);
109
110#if ENGINE_MAJOR_VERSION >= 5
111 FUniqueNetIdPixoVRRef NewUserIdRef = FUniqueNetIdPixoVR::Create(RandomUserId);
112 UserAccounts.Add(*NewUserIdRef, UserAccountPtr.ToSharedRef());
113#else
114 FUniqueNetIdPixoVR NewUserId(RandomUserId);
115 UserAccounts.Add(NewUserId, UserAccountPtr.ToSharedRef());
116#endif
117 // keep track of user ids for local users
118 UserIds.Add(LocalUserNum, UserAccountPtr->GetUserId());
119 }
120 else
121 {
122 const FUniqueNetIdPixoVR* UniqueIdStr = (FUniqueNetIdPixoVR*)(UserId->Get());
123 TSharedRef<FPVROUserAccount>* TempPtr = UserAccounts.Find(*UniqueIdStr);
124 check(TempPtr);
125 UserAccountPtr = *TempPtr;
126 }
127 }
128
129 if (!ErrorStr.IsEmpty())
130 {
131 Warn("Login request failed. %s", *ErrorStr);
132#if ENGINE_MAJOR_VERSION >= 5
133 TriggerOnLoginCompleteDelegates(LocalUserNum, false, FUniqueNetIdPixoVR::EmptyId().Get(), ErrorStr);
134#else
135 TriggerOnLoginCompleteDelegates(LocalUserNum, false, FUniqueNetIdPixoVR(), ErrorStr);
136#endif
137 return false;
138 }
139
140 TriggerOnLoginCompleteDelegates(LocalUserNum, true, UserAccountPtr->GetUserId().Get(), ErrorStr);
141 return true;
142}
143
144bool FPVROIdentity::Logout(int32 LocalUserNum)
145{
146 FUniqueNetIdPtr UserIdPtr = GetUniquePlayerId(LocalUserNum);
147 if (UserIdPtr.IsValid())
148 {
149 // remove cached user account
150#if ENGINE_MAJOR_VERSION >= 5
151 UserAccounts.Remove(FUniqueNetIdPixoVR::Cast(*UserIdPtr));
152#else
153 UserAccounts.Remove(FUniqueNetIdPixoVR(*UserIdPtr));
154#endif
155 // remove cached user id
156 UserIds.Remove(LocalUserNum);
157 // not async but should call completion delegate anyway
158 TriggerOnLogoutCompleteDelegates(LocalUserNum, true);
159
160 return true;
161 }
162 else
163 {
164 Warn("No logged in user found for LocalUserNum=%d.", LocalUserNum);
165 TriggerOnLogoutCompleteDelegates(LocalUserNum, false);
166 }
167 return false;
168}
169
170bool FPVROIdentity::AutoLogin(int32 LocalUserNum)
171{
172 FString LoginStr;
173 FString PasswordStr;
174 FString TypeStr;
175
176 FParse::Value(FCommandLine::Get(), TEXT("AUTH_LOGIN="), LoginStr);
177 FParse::Value(FCommandLine::Get(), TEXT("AUTH_PASSWORD="), PasswordStr);
178 FParse::Value(FCommandLine::Get(), TEXT("AUTH_TYPE="), TypeStr);
179
180 bool bEnableWarning = LoginStr.Len() > 0 || PasswordStr.Len() > 0 || TypeStr.Len() > 0;
181
182 if (!LoginStr.IsEmpty())
183 {
184 if (!PasswordStr.IsEmpty())
185 {
186 if (!TypeStr.IsEmpty())
187 {
188 return Login(0, FOnlineAccountCredentials(TypeStr, LoginStr, PasswordStr));
189 }
190 else if (bEnableWarning)
191 {
192 Warn("AutoLogin missing AUTH_TYPE=<type>.");
193 }
194 }
195 else if (bEnableWarning)
196 {
197 Warn("AutoLogin missing AUTH_PASSWORD=<password>.");
198 }
199 }
200 else if (bEnableWarning)
201 {
202 Warn("AutoLogin missing AUTH_LOGIN=<login id>.");
203 }
204
205 return false;
206}
207
208TSharedPtr<FUserOnlineAccount> FPVROIdentity::GetUserAccount(const FUniqueNetId& UserId) const
209{
210 TSharedPtr<FUserOnlineAccount> Result;
211
212#if ENGINE_MAJOR_VERSION >= 5
213 FUniqueNetIdPixoVR StringUserId = FUniqueNetIdPixoVR::Cast(UserId);
214#else
215 FUniqueNetIdPixoVR StringUserId(UserId);
216#endif
217 const TSharedRef<FPVROUserAccount>* FoundUserAccount = UserAccounts.Find(StringUserId);
218 if (FoundUserAccount != nullptr)
219 {
220 Result = *FoundUserAccount;
221 }
222
223 return Result;
224}
225
226TArray<TSharedPtr<FUserOnlineAccount> > FPVROIdentity::GetAllUserAccounts() const
227{
228 TArray<TSharedPtr<FUserOnlineAccount> > Result;
229
230 for (TMap<FUniqueNetIdPixoVR, TSharedRef<FPVROUserAccount>>::TConstIterator It(UserAccounts); It; ++It)
231 {
232 Result.Add(It.Value());
233 }
234
235 return Result;
236}
237
239{
240 const FUniqueNetIdPtr* FoundId = UserIds.Find(LocalUserNum);
241 if (FoundId != nullptr)
242 {
243 return *FoundId;
244 }
245 return nullptr;
246}
247
249{
250 if (Bytes != nullptr && Size > 0)
251 {
252 FString StrId(Size, (TCHAR*)Bytes);
253#if ENGINE_MAJOR_VERSION >= 5
254 return FUniqueNetIdPixoVR::Create(StrId);
255#else
256 return MakeShareable(new FUniqueNetIdPixoVR(StrId));
257#endif
258
259 }
260 return nullptr;
261}
262
264{
265#if ENGINE_MAJOR_VERSION >= 5
266 return FUniqueNetIdPixoVR::Create(Str);
267#else
268 return MakeShareable(new FUniqueNetIdPixoVR(Str));
269#endif
270}
271
272ELoginStatus::Type FPVROIdentity::GetLoginStatus(int32 LocalUserNum) const
273{
274 FUniqueNetIdPtr UserId = GetUniquePlayerId(LocalUserNum);
275 if (UserId.IsValid())
276 {
277 return GetLoginStatus(*UserId);
278 }
279 return ELoginStatus::NotLoggedIn;
280}
281
282ELoginStatus::Type FPVROIdentity::GetLoginStatus(const FUniqueNetId& UserId) const
283{
284 TSharedPtr<FUserOnlineAccount> UserAccount = GetUserAccount(UserId);
285 if (UserAccount.IsValid() &&
286 UserAccount->GetUserId()->IsValid())
287 {
288 return ELoginStatus::LoggedIn;
289 }
290 return ELoginStatus::NotLoggedIn;
291}
292
293FString FPVROIdentity::GetPlayerNickname(int32 LocalUserNum) const
294{
295 FUniqueNetIdPtr UniqueId = GetUniquePlayerId(LocalUserNum);
296 if (UniqueId.IsValid())
297 {
298 return UniqueId->ToString();
299 }
300
301 return TEXT("PixoVRUser");
302}
303
304FString FPVROIdentity::GetPlayerNickname(const FUniqueNetId& UserId) const
305{
306 return UserId.ToString();
307}
308
309void FPVROIdentity::SetPlayerNickname(int32 LocalUserNum, const FString PlayerNickname)
310{
311 FUniqueNetIdPtr UniqueId = GetUniquePlayerId(LocalUserNum);
312 if (UniqueId.IsValid())
313 {
314 SetPlayerNickname(*UniqueId, PlayerNickname);
315 }
316}
317
318void FPVROIdentity::SetPlayerNickname(const FUniqueNetId& UserId, const FString PlayerNickname)
319{
320 const FUniqueNetIdPixoVR* UniqueIdStr = (FUniqueNetIdPixoVR*)(&UserId);
321 TSharedRef<FPVROUserAccount>* UserAccountPtr = UserAccounts.Find(*UniqueIdStr);
322 if (UserAccountPtr)
323 {
324 UserAccountPtr->Get().UserName = PlayerNickname;
325 }
326}
327
328FString FPVROIdentity::GetAuthToken(int32 LocalUserNum) const
329{
330 FUniqueNetIdPtr UserId = GetUniquePlayerId(LocalUserNum);
331 if (UserId.IsValid())
332 {
333 TSharedPtr<FUserOnlineAccount> UserAccount = GetUserAccount(*UserId);
334 if (UserAccount.IsValid())
335 {
336 return UserAccount->GetAccessToken();
337 }
338 }
339 return FString();
340}
341
342void FPVROIdentity::RevokeAuthToken(const FUniqueNetId& UserId, const FOnRevokeAuthTokenCompleteDelegate& Delegate)
343{
344 Log("FPVROIdentity::RevokeAuthToken not implemented");
345}
346
348 : Subsystem(InSubsystem)
349{
350 // autologin the 0-th player
351 Login(0, FOnlineAccountCredentials(TEXT("PVROGenericPlayer"), TEXT("PVROGenericUser"), TEXT("PVROGenericId")) );
352}
353
357
358void FPVROIdentity::GetUserPrivilege(const FUniqueNetId& UserId, EUserPrivileges::Type Privilege, const FOnGetUserPrivilegeCompleteDelegate& Delegate)
359{
360 Delegate.ExecuteIfBound(UserId, Privilege, (uint32)EPrivilegeResults::NoFailures);
361}
362
363FPlatformUserId FPVROIdentity::GetPlatformUserIdFromUniqueNetId(const FUniqueNetId& UniqueNetId) const
364{
365 for (int LocalPlayerIndex = 0; LocalPlayerIndex < MAX_LOCAL_PLAYERS; ++LocalPlayerIndex)
366 {
367 auto CurrentUniqueId = GetUniquePlayerId(LocalPlayerIndex);
368 if (CurrentUniqueId.IsValid() && (*CurrentUniqueId == UniqueNetId))
369 {
370#if ENGINE_MAJOR_VERSION >= 5
371 return GetPlatformUserIdFromLocalUserNum(LocalPlayerIndex);
372#else
373 return LocalPlayerIndex;
374#endif
375 }
376 }
377
378 return PLATFORMUSERID_NONE;
379}
380
382{
383 return TEXT("");
384}
385
386#undef Log
387#undef Warn
388#undef Error
389#undef Fatal
#define Warn(pmt,...)
#define Log(pmt,...)
DEFINE_LOG_CATEGORY_STATIC(LogPVROMultiplayerIdentity, Log, All)
FString GenerateRandomUserId(int32 LocalUserNum)
#define Log(pmt,...)
TSharedPtr< const FUniqueNetId > FUniqueNetIdPtr
FPVROIdentity()=delete
virtual void SetPlayerNickname(int32 LocalUserNum, const FString PlayerNickname)
virtual ELoginStatus::Type GetLoginStatus(int32 LocalUserNum) const override
virtual FString GetPlayerNickname(int32 LocalUserNum) const override
virtual FUniqueNetIdPtr CreateUniquePlayerId(uint8 *Bytes, int32 Size) override
TMap< int32, FUniqueNetIdPtr > UserIds
virtual FString GetAuthToken(int32 LocalUserNum) const override
virtual bool Logout(int32 LocalUserNum) override
virtual bool AutoLogin(int32 LocalUserNum) override
virtual FPlatformUserId GetPlatformUserIdFromUniqueNetId(const FUniqueNetId &UniqueNetId) const override
virtual void GetUserPrivilege(const FUniqueNetId &UserId, EUserPrivileges::Type Privilege, const FOnGetUserPrivilegeCompleteDelegate &Delegate) override
TMap< FUniqueNetIdPixoVR, TSharedRef< FPVROUserAccount > > UserAccounts
virtual FUniqueNetIdPtr GetUniquePlayerId(int32 LocalUserNum) const override
virtual TArray< TSharedPtr< FUserOnlineAccount > > GetAllUserAccounts() const override
virtual FString GetAuthType() const override
virtual TSharedPtr< FUserOnlineAccount > GetUserAccount(const FUniqueNetId &UserId) const override
virtual bool Login(int32 LocalUserNum, const FOnlineAccountCredentials &AccountCredentials) override
virtual void RevokeAuthToken(const FUniqueNetId &UserId, const FOnRevokeAuthTokenCompleteDelegate &Delegate) override
TMap< FString, FString > UserAttributes
virtual bool GetAuthAttribute(const FString &AttrName, FString &OutAttrValue) const override
virtual bool GetUserAttribute(const FString &AttrName, FString &OutAttrValue) const override
TMap< FString, FString > AdditionalAuthData
virtual bool SetUserAttribute(const FString &AttrName, const FString &AttrValue) override